]> gcc.gnu.org Git - gcc.git/commitdiff
libgo: update to Go1.17rc2
authorIan Lance Taylor <iant@golang.org>
Fri, 30 Jul 2021 21:28:58 +0000 (14:28 -0700)
committerIan Lance Taylor <iant@golang.org>
Fri, 13 Aug 2021 03:23:07 +0000 (20:23 -0700)
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/341629

2004 files changed:
gcc/go/gofrontend/MERGE
libgo/MERGE
libgo/Makefile.am
libgo/Makefile.in
libgo/VERSION
libgo/check-packages.txt
libgo/configure
libgo/configure.ac
libgo/go/archive/tar/stat_actime1.go
libgo/go/archive/tar/stat_actime2.go
libgo/go/archive/tar/stat_unix.go
libgo/go/archive/tar/tar_test.go
libgo/go/archive/zip/reader.go
libgo/go/archive/zip/reader_test.go
libgo/go/archive/zip/struct.go
libgo/go/archive/zip/writer.go
libgo/go/archive/zip/writer_test.go
libgo/go/bufio/bufio.go
libgo/go/bufio/bufio_test.go
libgo/go/bufio/scan.go
libgo/go/bytes/boundary_test.go
libgo/go/bytes/buffer.go
libgo/go/bytes/buffer_test.go
libgo/go/cmd/cgo/doc.go
libgo/go/cmd/cgo/gcc.go
libgo/go/cmd/cgo/main.go
libgo/go/cmd/cgo/out.go
libgo/go/cmd/go.mod
libgo/go/cmd/go/alldocs.go
libgo/go/cmd/go/go11.go
libgo/go/cmd/go/go_test.go
libgo/go/cmd/go/go_unix_test.go
libgo/go/cmd/go/internal/base/path.go
libgo/go/cmd/go/internal/base/signal_notunix.go
libgo/go/cmd/go/internal/base/signal_unix.go
libgo/go/cmd/go/internal/bug/bug.go
libgo/go/cmd/go/internal/cache/cache.go
libgo/go/cmd/go/internal/cache/hash.go
libgo/go/cmd/go/internal/cfg/cfg.go
libgo/go/cmd/go/internal/clean/clean.go
libgo/go/cmd/go/internal/doc/doc.go
libgo/go/cmd/go/internal/envcmd/env.go
libgo/go/cmd/go/internal/fix/fix.go
libgo/go/cmd/go/internal/fmtcmd/fmt.go
libgo/go/cmd/go/internal/fsys/fsys.go
libgo/go/cmd/go/internal/generate/generate.go
libgo/go/cmd/go/internal/get/get.go
libgo/go/cmd/go/internal/help/helpdoc.go
libgo/go/cmd/go/internal/imports/read.go
libgo/go/cmd/go/internal/imports/read_test.go
libgo/go/cmd/go/internal/imports/testdata/android/tags.txt [new file with mode: 0644]
libgo/go/cmd/go/internal/imports/testdata/android/want.txt [new file with mode: 0644]
libgo/go/cmd/go/internal/imports/testdata/illumos/tags.txt [new file with mode: 0644]
libgo/go/cmd/go/internal/imports/testdata/illumos/want.txt [new file with mode: 0644]
libgo/go/cmd/go/internal/imports/testdata/star/tags.txt [new file with mode: 0644]
libgo/go/cmd/go/internal/imports/testdata/star/want.txt [new file with mode: 0644]
libgo/go/cmd/go/internal/list/context.go
libgo/go/cmd/go/internal/list/list.go
libgo/go/cmd/go/internal/load/flag.go
libgo/go/cmd/go/internal/load/pkg.go
libgo/go/cmd/go/internal/load/test.go
libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go
libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_other.go
libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_plan9.go
libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_test.go
libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_unix.go
libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_windows.go
libgo/go/cmd/go/internal/lockedfile/lockedfile_filelock.go
libgo/go/cmd/go/internal/lockedfile/lockedfile_plan9.go
libgo/go/cmd/go/internal/lockedfile/lockedfile_test.go
libgo/go/cmd/go/internal/lockedfile/transform_test.go
libgo/go/cmd/go/internal/modcmd/download.go
libgo/go/cmd/go/internal/modcmd/edit.go
libgo/go/cmd/go/internal/modcmd/graph.go
libgo/go/cmd/go/internal/modcmd/init.go
libgo/go/cmd/go/internal/modcmd/tidy.go
libgo/go/cmd/go/internal/modcmd/vendor.go
libgo/go/cmd/go/internal/modcmd/verify.go
libgo/go/cmd/go/internal/modcmd/why.go
libgo/go/cmd/go/internal/modconv/convert.go
libgo/go/cmd/go/internal/modconv/convert_test.go [deleted file]
libgo/go/cmd/go/internal/modconv/testdata/traefik.dep [new file with mode: 0644]
libgo/go/cmd/go/internal/modconv/testdata/traefik.out [new file with mode: 0644]
libgo/go/cmd/go/internal/modfetch/bootstrap.go
libgo/go/cmd/go/internal/modfetch/cache.go
libgo/go/cmd/go/internal/modfetch/codehost/git.go
libgo/go/cmd/go/internal/modfetch/codehost/git_test.go
libgo/go/cmd/go/internal/modfetch/codehost/shell.go
libgo/go/cmd/go/internal/modfetch/coderepo.go
libgo/go/cmd/go/internal/modfetch/fetch.go
libgo/go/cmd/go/internal/modfetch/insecure.go [deleted file]
libgo/go/cmd/go/internal/modfetch/proxy.go
libgo/go/cmd/go/internal/modfetch/pseudo_test.go [deleted file]
libgo/go/cmd/go/internal/modfetch/repo.go
libgo/go/cmd/go/internal/modfetch/sumdb.go
libgo/go/cmd/go/internal/modget/get.go
libgo/go/cmd/go/internal/modinfo/info.go
libgo/go/cmd/go/internal/modload/build.go
libgo/go/cmd/go/internal/modload/buildlist.go
libgo/go/cmd/go/internal/modload/edit.go [new file with mode: 0644]
libgo/go/cmd/go/internal/modload/help.go
libgo/go/cmd/go/internal/modload/import.go
libgo/go/cmd/go/internal/modload/import_test.go
libgo/go/cmd/go/internal/modload/init.go
libgo/go/cmd/go/internal/modload/list.go
libgo/go/cmd/go/internal/modload/load.go
libgo/go/cmd/go/internal/modload/modfile.go
libgo/go/cmd/go/internal/modload/mvs.go
libgo/go/cmd/go/internal/modload/query.go
libgo/go/cmd/go/internal/modload/query_test.go
libgo/go/cmd/go/internal/modload/search.go
libgo/go/cmd/go/internal/modload/stat_openfile.go
libgo/go/cmd/go/internal/modload/stat_unix.go
libgo/go/cmd/go/internal/modload/stat_windows.go
libgo/go/cmd/go/internal/modload/vendor.go
libgo/go/cmd/go/internal/mvs/errors.go
libgo/go/cmd/go/internal/mvs/graph.go [new file with mode: 0644]
libgo/go/cmd/go/internal/mvs/mvs.go
libgo/go/cmd/go/internal/mvs/mvs_test.go
libgo/go/cmd/go/internal/renameio/renameio.go [deleted file]
libgo/go/cmd/go/internal/renameio/renameio_test.go [deleted file]
libgo/go/cmd/go/internal/renameio/umask_test.go [deleted file]
libgo/go/cmd/go/internal/robustio/robustio_flaky.go
libgo/go/cmd/go/internal/robustio/robustio_other.go
libgo/go/cmd/go/internal/run/run.go
libgo/go/cmd/go/internal/search/search.go
libgo/go/cmd/go/internal/test/cover.go
libgo/go/cmd/go/internal/test/flagdefs.go
libgo/go/cmd/go/internal/test/genflags.go
libgo/go/cmd/go/internal/test/test.go
libgo/go/cmd/go/internal/test/testflag.go
libgo/go/cmd/go/internal/vcs/vcs.go
libgo/go/cmd/go/internal/vet/vet.go
libgo/go/cmd/go/internal/web/bootstrap.go
libgo/go/cmd/go/internal/web/http.go
libgo/go/cmd/go/internal/web/url_other.go
libgo/go/cmd/go/internal/web/url_other_test.go
libgo/go/cmd/go/internal/work/action.go
libgo/go/cmd/go/internal/work/build.go
libgo/go/cmd/go/internal/work/build_test.go
libgo/go/cmd/go/internal/work/buildid.go
libgo/go/cmd/go/internal/work/exec.go
libgo/go/cmd/go/internal/work/gc.go
libgo/go/cmd/go/internal/work/gccgo.go
libgo/go/cmd/go/internal/work/init.go
libgo/go/cmd/go/internal/work/security.go
libgo/go/cmd/go/internal/work/security_test.go
libgo/go/cmd/go/internal/work/testgo.go
libgo/go/cmd/go/main.go
libgo/go/cmd/go/mkalldocs.sh
libgo/go/cmd/go/proxy_test.go
libgo/go/cmd/go/script_test.go
libgo/go/cmd/go/stop_other_test.go [new file with mode: 0644]
libgo/go/cmd/go/stop_unix_test.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/addmod.go
libgo/go/cmd/go/testdata/mod/example.com_ambiguous_a_b_v0.0.0-empty.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_ambiguous_a_v1.0.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0-exclude.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0-newerself.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0-replace.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.9.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_deprecated_a_v1.0.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_deprecated_a_v1.9.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_deprecated_b_v1.0.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_deprecated_b_v1.9.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_dotname_v1.0.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_incompatiblewithsub_v1.0.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_incompatiblewithsub_v2.0.0+incompatible.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_quote_v1.5.2.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_ambiguous_nested_v1.9.0-bad.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_ambiguous_other_v1.0.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_ambiguous_v1.0.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_incompatible_v1.0.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_incompatible_v2.0.0+incompatible.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_missingmod_v1.0.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_missingmod_v1.9.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-block.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-blockwithcomment.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-empty.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-long.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-multiline1.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-multiline2.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-order.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-unprintable.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.1-order.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.9.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_rename_v1.0.0-bad.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_rename_v1.9.0-new.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_self_all_v1.9.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_self_prerelease_v1.0.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_self_prerelease_v1.9.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_self_prerelease_v1.9.1-pre.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_self_prev_v1.0.0-bad.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_self_prev_v1.1.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_self_prev_v1.9.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_self_pseudo_v0.0.0-20200325131415-0123456789ab [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_self_pseudo_v1.0.0-bad.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_self_pseudo_v1.9.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_v1.0.0-bad.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_v1.0.0-good.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_v1.0.0-unused.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_retract_v1.1.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_split-incompatible_subpkg_v0.1.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_split-incompatible_v2.0.0+incompatible.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_split-incompatible_v2.1.0-pre+incompatible.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_undeprecated_v1.0.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.com_undeprecated_v1.0.1.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.net_ambiguous_nested_v0.1.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.net_ambiguous_v0.1.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.net_ambiguous_v0.2.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.net_pkgadded_v1.0.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.net_pkgadded_v1.1.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/mod/example.net_pkgadded_v1.2.0.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/README
libgo/go/cmd/go/testdata/script/badgo.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/bug.txt
libgo/go/cmd/go/testdata/script/build_arm.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_cache_arch_mode.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_cache_disabled.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_cd_gopath_different.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_cgo_consistent_results.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_darwin_cc_arch.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_dash_n_cgo.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_dash_o_dev_null.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_dash_x.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_exe.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_gopath_order.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_i_deprecate.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_ignore_leading_bom.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_import_comment.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_import_cycle.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_internal.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_issue6480.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_link_x_import_path_escape.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_n_cgo.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_no_go.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_output.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_overlay.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_patterns_outside_gopath.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_plugin_non_main.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_tag_goexperiment.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_tags_no_comma.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_test_only.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_trimpath_cgo.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_unsupported_goos.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/build_vendor.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cgo_asm_error.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cgo_bad_directives.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cgo_depends_on_syscall.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cgo_flag_contains_space.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cgo_path.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cgo_path_space.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cgo_stale.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/clean_binary.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/clean_cache_n.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cover_asm.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cover_blank_func_decl.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cover_cgo.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cover_cgo_extra_file.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cover_cgo_extra_test.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cover_cgo_xtest.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cover_dash_c.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cover_dep_loop.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cover_dot_import.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cover_error.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cover_import_main_loop.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cover_pattern.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cover_pkgall_imports.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cover_runs.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cover_statements.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/cover_sync_atomic_import.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/doc.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/embed.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/embed_fmt.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/env_cross_build.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/env_exp.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/env_unset.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/env_write.txt
libgo/go/cmd/go/testdata/script/fmt_load_errors.txt
libgo/go/cmd/go/testdata/script/gccgo_link_c.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/generate.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/generate_bad_imports.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/generate_env.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/generate_invalid.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_404_meta.txt
libgo/go/cmd/go/testdata/script/get_custom_domain_wildcard.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_dash_t.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_domain_root.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_dot_slash_download.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_go_file.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_goroot.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_insecure.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_insecure_custom_domain.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_insecure_env.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_insecure_no_longer_supported.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_insecure_redirect.txt
libgo/go/cmd/go/testdata/script/get_insecure_update.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_internal_wildcard.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_issue11307.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_legacy.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_non_pkg.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_race.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_test_only.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_update.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_update_all.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_update_unknown_protocol.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_update_wildcard.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_vcs_error_message.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/get_vendor.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/gopath_vendor_dup_err.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/goroot_executable.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/govcs.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/import_cycle.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/import_ignore.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/install_cgo_excluded.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/install_msan_and_race_require_cgo.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/install_relative_gobin_fail.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/install_shadow_gopath.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/issue36000.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/ldflag.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/link_matching_actionid.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_case_collision.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_cgo_compiled_importmap.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_dedup_packages.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_err_cycle.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_err_stack.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_find_nodeps.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_gofile_in_goroot.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_gomod_in_gopath.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_json_with_f.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_load_err.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_module_when_error.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_overlay.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_permissions.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_shadow.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_std_vendor.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_swigcxx.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_symlink.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_symlink_internal.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_symlink_issue35941.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_symlink_vendor_issue14054.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_symlink_vendor_issue15201.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_test_simple.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/list_wildcard_skip_nonmatching.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/load_test_pkg_err.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_all.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_cache_dir.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_convert.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_convert_tsv_insecure.txt
libgo/go/cmd/go/testdata/script/mod_deprecate_message.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_download_concurrent_read.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_download_partial.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_e.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_edit.txt
libgo/go/cmd/go/testdata/script/mod_edit_no_modcache.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_empty_err.txt
libgo/go/cmd/go/testdata/script/mod_get_ambiguous_arg.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_ambiguous_import.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_ambiguous_pkg.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_changes.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_deprecate_install.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_deprecated.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_downadd_indirect.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_downgrade.txt
libgo/go/cmd/go/testdata/script/mod_get_downgrade_missing.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_downup_artifact.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_downup_indirect.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_downup_pseudo_artifact.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_errors.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_extra.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_fossil.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_go_file.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_insecure_redirect.txt
libgo/go/cmd/go/testdata/script/mod_get_issue37438.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_lazy_indirect.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_missing_ziphash.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_nopkgs.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_patch.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_patchbound.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_patchcycle.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_patchmod.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_pkgtags.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_prefer_incompatible.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_private_vcs.txt
libgo/go/cmd/go/testdata/script/mod_get_promote_implicit.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_replaced.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_retract.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_retract_ambiguous.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_split.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_sum_noroot.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_too_many_redirects.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_update_unrelated_sum.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_get_wild.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_go_version_missing.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_gomodcache.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_graph_version.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_import_cycle.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_import_issue41113.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_import_issue42891.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_import_meta.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_indirect_nospace.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_init_dep.txt
libgo/go/cmd/go/testdata/script/mod_init_glide.txt
libgo/go/cmd/go/testdata/script/mod_init_path.txt
libgo/go/cmd/go/testdata/script/mod_init_tidy.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_install_hint.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_install_pkg_version.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_invalid_path.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_invalid_path_dotname.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_invalid_path_plus.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_invalid_version.txt
libgo/go/cmd/go/testdata/script/mod_lazy_consistency.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_lazy_downgrade.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_lazy_import_allmod.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_lazy_new_import.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_lazy_test_horizon.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_lazy_test_of_test_dep.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_list.txt
libgo/go/cmd/go/testdata/script/mod_list_deprecated.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_list_deprecated_replace.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_list_retract.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_list_std.txt
libgo/go/cmd/go/testdata/script/mod_list_sums.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_list_test_cycle.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_list_update_nolatest.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_load_badchain.txt
libgo/go/cmd/go/testdata/script/mod_load_replace_mismatch.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_notall.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_outside.txt
libgo/go/cmd/go/testdata/script/mod_overlay.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_prefer_compatible.txt
libgo/go/cmd/go/testdata/script/mod_proxy_https.txt
libgo/go/cmd/go/testdata/script/mod_proxy_invalid.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_query_main.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_replace.txt
libgo/go/cmd/go/testdata/script/mod_replace_gopkgin.txt
libgo/go/cmd/go/testdata/script/mod_replace_readonly.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_require_exclude.txt
libgo/go/cmd/go/testdata/script/mod_retention.txt
libgo/go/cmd/go/testdata/script/mod_retract.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_retract_fix_version.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_retract_incompatible.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_retract_pseudo_base.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_retract_rationale.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_retract_rename.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_retract_replace.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_retract_versions.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_run_nonmain.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_run_pkg_version.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_run_pkgerror.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_std_vendor.txt
libgo/go/cmd/go/testdata/script/mod_sum_ambiguous.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_sum_lookup.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_sum_readonly.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_sumdb.txt
libgo/go/cmd/go/testdata/script/mod_sumdb_cache.txt
libgo/go/cmd/go/testdata/script/mod_sumdb_golang.txt
libgo/go/cmd/go/testdata/script/mod_symlink_dotgo.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_tagged_import_cycle.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_test.txt
libgo/go/cmd/go/testdata/script/mod_tidy_compat.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_tidy_compat_added.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_tidy_compat_deleted.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_tidy_compat_implicit.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_tidy_compat_incompatible.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_tidy_compat_irrelevant.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_tidy_convergence.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_tidy_convergence_loop.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_tidy_indirect.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_tidy_lazy_self.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_tidy_newroot.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_tidy_old.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_tidy_oldgo.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_tidy_replace.txt
libgo/go/cmd/go/testdata/script/mod_tidy_replace_old.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_tidy_symlink_issue35941.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_tidy_too_new.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_tidy_version.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_update_sum_readonly.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_vendor_embed.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_vendor_gomod.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_vendor_goversion.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_vendor_issue46867.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_vendor_trimpath.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/mod_vendor_unused_only.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/run_dirs.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/run_hello_pkg.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/run_internal.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/run_issue11709.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/run_vendor.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_benchmark_chatty_fail.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_benchmark_chatty_success.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_benchmark_fatal.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_benchmark_labels.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_benchmark_timeout.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_build_failure.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_cache_inputs.txt
libgo/go/cmd/go/testdata/script/test_chatty_fail.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_chatty_parallel_fail.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_chatty_parallel_success.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_chatty_parallel_success_sleepy.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_chatty_success.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_cleanup_failnow.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_deadline.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_empty.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_env_term.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_example_goexit.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_exit.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_fail_fast.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_finished_subtest_goroutines.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_flag.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_import_error_stack.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_json.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_json_exit.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_json_interleaved.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_json_panic_exit.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_main.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_main_panic.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_main_twice.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_match_benchmark_labels.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_match_no_benchmarks.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_match_no_subtests.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_match_no_subtests_failure.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_match_no_subtests_parallel.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_match_no_tests.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_match_no_tests_build_failure.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_match_no_tests_with_subtests.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_match_only_benchmarks.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_match_only_example.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_match_only_subtests.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_match_only_subtests_parallel.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_match_only_tests.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_minus_n.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_no_run_example.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_no_tests.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_overlay.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_parallel_number.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_profile.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_race.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_race_cover_mode_issue20435.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_race_install.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_race_install_cgo.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_regexps.txt [moved from libgo/go/cmd/go/testdata/test_regexps.txt with 96% similarity]
libgo/go/cmd/go/testdata/script/test_relative_cmdline.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_relative_import.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_relative_import_dash_i.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_script_cmdcd.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_shuffle.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_source_order.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_syntax_error_says_fail.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_trimpath.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_trimpath_main.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_trimpath_test_suffix.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_vendor.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_vet.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_write_profiles_on_timeout.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/test_xtestonly_works.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/testing_issue40908.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/toolexec.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/vendor_gopath_issue11409.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/vendor_import.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/vendor_import_missing.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/vendor_import_wrong.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/vendor_issue12156.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/vendor_list_issue11977.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/vendor_resolve.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/vendor_test_issue11864.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/vendor_test_issue14613.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/version_goexperiment.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/version_replace.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/vet.txt [new file with mode: 0644]
libgo/go/cmd/go/testdata/script/vet_internal.txt [new file with mode: 0644]
libgo/go/cmd/gofmt/gofmt.go
libgo/go/cmd/gofmt/gofmt_test.go
libgo/go/cmd/gofmt/gofmt_typeparams_test.go [new file with mode: 0644]
libgo/go/cmd/internal/objabi/flag.go
libgo/go/cmd/internal/objabi/funcdata.go
libgo/go/cmd/internal/objabi/funcid.go
libgo/go/cmd/internal/objabi/line.go
libgo/go/cmd/internal/objabi/path.go
libgo/go/cmd/internal/objabi/reloctype.go
libgo/go/cmd/internal/objabi/reloctype_string.go
libgo/go/cmd/internal/objabi/stack.go
libgo/go/cmd/internal/objabi/util.go
libgo/go/cmd/internal/sys/arch.go
libgo/go/cmd/internal/sys/supported.go
libgo/go/cmd/vendor/modules.txt
libgo/go/cmd/vet/main.go
libgo/go/cmd/vet/testdata/asm/asm1.s
libgo/go/cmd/vet/testdata/buildtag/buildtag.go
libgo/go/cmd/vet/testdata/buildtag/buildtag2.go [new file with mode: 0644]
libgo/go/cmd/vet/testdata/buildtag/buildtag3.go [new file with mode: 0644]
libgo/go/cmd/vet/testdata/buildtag/buildtag4.go [new file with mode: 0644]
libgo/go/cmd/vet/testdata/buildtag/buildtag5.go [new file with mode: 0644]
libgo/go/cmd/vet/testdata/buildtag/buildtag6.s [moved from libgo/go/io/ioutil/export_test.go with 66% similarity]
libgo/go/cmd/vet/testdata/buildtag/buildtag7.s [new file with mode: 0644]
libgo/go/cmd/vet/testdata/copylock/copylock.go
libgo/go/cmd/vet/testdata/httpresponse/httpresponse.go
libgo/go/cmd/vet/testdata/tagtest/file1.go
libgo/go/cmd/vet/testdata/tagtest/file2.go
libgo/go/cmd/vet/testdata/testingpkg/tests.go
libgo/go/cmd/vet/testdata/testingpkg/tests_test.go
libgo/go/cmd/vet/vet_test.go
libgo/go/compress/lzw/reader.go
libgo/go/compress/lzw/reader_test.go
libgo/go/compress/lzw/writer.go
libgo/go/compress/lzw/writer_test.go
libgo/go/context/benchmark_test.go
libgo/go/context/context.go
libgo/go/context/context_test.go
libgo/go/crypto/aes/aes_gcm.go
libgo/go/crypto/aes/cipher_asm.go
libgo/go/crypto/aes/cipher_generic.go
libgo/go/crypto/aes/gcm_ppc64le.go
libgo/go/crypto/cipher/benchmark_test.go
libgo/go/crypto/cipher/xor_generic.go
libgo/go/crypto/cipher/xor_ppc64x.go
libgo/go/crypto/ecdsa/ecdsa.go
libgo/go/crypto/ecdsa/ecdsa_noasm.go
libgo/go/crypto/ecdsa/ecdsa_s390x.go
libgo/go/crypto/ecdsa/ecdsa_s390x_test.go
libgo/go/crypto/ecdsa/ecdsa_test.go
libgo/go/crypto/ed25519/ed25519.go
libgo/go/crypto/ed25519/ed25519_test.go
libgo/go/crypto/ed25519/ed25519vectors_test.go [new file with mode: 0644]
libgo/go/crypto/ed25519/internal/edwards25519/const.go [deleted file]
libgo/go/crypto/ed25519/internal/edwards25519/doc.go [new file with mode: 0644]
libgo/go/crypto/ed25519/internal/edwards25519/edwards25519.go
libgo/go/crypto/ed25519/internal/edwards25519/edwards25519_test.go [new file with mode: 0644]
libgo/go/crypto/ed25519/internal/edwards25519/field/_asm/fe_amd64_asm.go [new file with mode: 0644]
libgo/go/crypto/ed25519/internal/edwards25519/field/_asm/go.mod [new file with mode: 0644]
libgo/go/crypto/ed25519/internal/edwards25519/field/fe.go [new file with mode: 0644]
libgo/go/crypto/ed25519/internal/edwards25519/field/fe_alias_test.go [new file with mode: 0644]
libgo/go/crypto/ed25519/internal/edwards25519/field/fe_amd64.go [new file with mode: 0644]
libgo/go/crypto/ed25519/internal/edwards25519/field/fe_amd64_noasm.go [new file with mode: 0644]
libgo/go/crypto/ed25519/internal/edwards25519/field/fe_arm64.go [new file with mode: 0644]
libgo/go/crypto/ed25519/internal/edwards25519/field/fe_arm64_noasm.go [new file with mode: 0644]
libgo/go/crypto/ed25519/internal/edwards25519/field/fe_bench_test.go [new file with mode: 0644]
libgo/go/crypto/ed25519/internal/edwards25519/field/fe_generic.go [new file with mode: 0644]
libgo/go/crypto/ed25519/internal/edwards25519/field/fe_test.go [new file with mode: 0644]
libgo/go/crypto/ed25519/internal/edwards25519/scalar.go [new file with mode: 0644]
libgo/go/crypto/ed25519/internal/edwards25519/scalar_alias_test.go [new file with mode: 0644]
libgo/go/crypto/ed25519/internal/edwards25519/scalar_test.go [new file with mode: 0644]
libgo/go/crypto/ed25519/internal/edwards25519/scalarmult.go [new file with mode: 0644]
libgo/go/crypto/ed25519/internal/edwards25519/scalarmult_test.go [new file with mode: 0644]
libgo/go/crypto/ed25519/internal/edwards25519/tables.go [new file with mode: 0644]
libgo/go/crypto/ed25519/internal/edwards25519/tables_test.go [new file with mode: 0644]
libgo/go/crypto/elliptic/elliptic.go
libgo/go/crypto/elliptic/elliptic_test.go
libgo/go/crypto/elliptic/fuzz_test.go
libgo/go/crypto/elliptic/internal/fiat/p521.go [new file with mode: 0644]
libgo/go/crypto/elliptic/internal/fiat/p521_fiat64.go [new file with mode: 0644]
libgo/go/crypto/elliptic/internal/fiat/p521_test.go [new file with mode: 0644]
libgo/go/crypto/elliptic/p224_test.go
libgo/go/crypto/elliptic/p256.go
libgo/go/crypto/elliptic/p256_asm.go
libgo/go/crypto/elliptic/p256_asm_table.go [new file with mode: 0644]
libgo/go/crypto/elliptic/p256_asm_table_test.go [new file with mode: 0644]
libgo/go/crypto/elliptic/p256_generic.go
libgo/go/crypto/elliptic/p256_ppc64le.go
libgo/go/crypto/elliptic/p256_s390x.go
libgo/go/crypto/elliptic/p256_test.go [new file with mode: 0644]
libgo/go/crypto/elliptic/p521.go [new file with mode: 0644]
libgo/go/crypto/internal/subtle/aliasing.go
libgo/go/crypto/internal/subtle/aliasing_appengine.go
libgo/go/crypto/md5/gen.go
libgo/go/crypto/md5/md5_test.go
libgo/go/crypto/md5/md5block_decl.go
libgo/go/crypto/md5/md5block_generic.go
libgo/go/crypto/rand/eagain.go
libgo/go/crypto/rand/rand_batched.go
libgo/go/crypto/rand/rand_batched_test.go
libgo/go/crypto/rand/rand_dragonfly.go [new file with mode: 0644]
libgo/go/crypto/rand/rand_getentropy.go [moved from libgo/go/crypto/rand/rand_openbsd.go with 79% similarity]
libgo/go/crypto/rand/rand_js.go
libgo/go/crypto/rand/rand_solaris.go [new file with mode: 0644]
libgo/go/crypto/rand/rand_unix.go
libgo/go/crypto/rsa/pss.go
libgo/go/crypto/rsa/pss_test.go
libgo/go/crypto/rsa/rsa.go
libgo/go/crypto/sha1/fallback_test.go
libgo/go/crypto/sha1/issue15617_test.go
libgo/go/crypto/sha1/sha1_test.go
libgo/go/crypto/sha1/sha1block_decl.go
libgo/go/crypto/sha1/sha1block_generic.go
libgo/go/crypto/sha256/fallback_test.go
libgo/go/crypto/sha256/sha256_test.go
libgo/go/crypto/sha256/sha256block_decl.go
libgo/go/crypto/sha256/sha256block_generic.go
libgo/go/crypto/sha512/fallback_test.go
libgo/go/crypto/sha512/sha512_test.go
libgo/go/crypto/sha512/sha512block_amd64.go
libgo/go/crypto/sha512/sha512block_decl.go
libgo/go/crypto/sha512/sha512block_generic.go
libgo/go/crypto/tls/cipher_suites.go
libgo/go/crypto/tls/common.go
libgo/go/crypto/tls/conn.go
libgo/go/crypto/tls/generate_cert.go
libgo/go/crypto/tls/handshake_client.go
libgo/go/crypto/tls/handshake_client_test.go
libgo/go/crypto/tls/handshake_client_tls13.go
libgo/go/crypto/tls/handshake_server.go
libgo/go/crypto/tls/handshake_server_test.go
libgo/go/crypto/tls/handshake_server_tls13.go
libgo/go/crypto/tls/handshake_test.go
libgo/go/crypto/tls/handshake_unix_test.go
libgo/go/crypto/tls/key_agreement.go
libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA
libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA
libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA
libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA
libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES
libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES
libgo/go/crypto/tls/testdata/Client-TLSv10-ExportKeyingMaterial
libgo/go/crypto/tls/testdata/Client-TLSv10-RSA-RC4
libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES
libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES
libgo/go/crypto/tls/testdata/Client-TLSv11-RSA-RC4
libgo/go/crypto/tls/testdata/Client-TLSv12-AES128-GCM-SHA256
libgo/go/crypto/tls/testdata/Client-TLSv12-AES128-SHA256
libgo/go/crypto/tls/testdata/Client-TLSv12-AES256-GCM-SHA384
libgo/go/crypto/tls/testdata/Client-TLSv12-ALPN
libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA
libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA
libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-Ed25519
libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384
libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA
libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA
libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPKCS1v15
libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPSS
libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES
libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM
libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES128-SHA256
libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384
libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-CHACHA20-POLY1305
libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES
libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES128-SHA256
libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-CHACHA20-POLY1305
libgo/go/crypto/tls/testdata/Client-TLSv12-Ed25519
libgo/go/crypto/tls/testdata/Client-TLSv12-ExportKeyingMaterial
libgo/go/crypto/tls/testdata/Client-TLSv12-P256-ECDHE
libgo/go/crypto/tls/testdata/Client-TLSv12-RSA-RC4
libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateOnce
libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwice
libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwiceRejected
libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiationRejected
libgo/go/crypto/tls/testdata/Client-TLSv12-SCT
libgo/go/crypto/tls/testdata/Client-TLSv12-X25519-ECDHE
libgo/go/crypto/tls/testdata/Client-TLSv13-AES128-SHA256
libgo/go/crypto/tls/testdata/Client-TLSv13-AES256-SHA384
libgo/go/crypto/tls/testdata/Client-TLSv13-ALPN
libgo/go/crypto/tls/testdata/Client-TLSv13-CHACHA20-SHA256
libgo/go/crypto/tls/testdata/Client-TLSv13-ClientCert-ECDSA-RSA
libgo/go/crypto/tls/testdata/Client-TLSv13-ClientCert-Ed25519
libgo/go/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-ECDSA
libgo/go/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-RSAPSS
libgo/go/crypto/tls/testdata/Client-TLSv13-ECDSA
libgo/go/crypto/tls/testdata/Client-TLSv13-Ed25519
libgo/go/crypto/tls/testdata/Client-TLSv13-ExportKeyingMaterial
libgo/go/crypto/tls/testdata/Client-TLSv13-HelloRetryRequest
libgo/go/crypto/tls/testdata/Client-TLSv13-KeyUpdate
libgo/go/crypto/tls/testdata/Client-TLSv13-P256-ECDHE
libgo/go/crypto/tls/testdata/Client-TLSv13-X25519-ECDHE
libgo/go/crypto/tls/testdata/Server-TLSv10-ExportKeyingMaterial
libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-Fallback [new file with mode: 0644]
libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch
libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-NotConfigured [new file with mode: 0644]
libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA [deleted file]
libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA [deleted file]
libgo/go/crypto/tls/testdata/Server-TLSv13-ALPN-Fallback [new file with mode: 0644]
libgo/go/crypto/tls/testdata/Server-TLSv13-ALPN-NoMatch
libgo/go/crypto/tls/testdata/Server-TLSv13-ALPN-NotConfigured [new file with mode: 0644]
libgo/go/crypto/tls/tls.go
libgo/go/crypto/tls/tls_test.go
libgo/go/crypto/x509/internal/macos/corefoundation.go
libgo/go/crypto/x509/internal/macos/security.go
libgo/go/crypto/x509/name_constraints_test.go
libgo/go/crypto/x509/parser.go [new file with mode: 0644]
libgo/go/crypto/x509/root.go
libgo/go/crypto/x509/root_bsd.go
libgo/go/crypto/x509/root_darwin.go
libgo/go/crypto/x509/root_ios.go
libgo/go/crypto/x509/root_ios_gen.go
libgo/go/crypto/x509/root_js.go
libgo/go/crypto/x509/root_omit.go
libgo/go/crypto/x509/root_omit_test.go
libgo/go/crypto/x509/root_plan9.go
libgo/go/crypto/x509/root_unix.go
libgo/go/crypto/x509/root_unix_test.go
libgo/go/crypto/x509/verify.go
libgo/go/crypto/x509/verify_test.go
libgo/go/crypto/x509/x509.go
libgo/go/crypto/x509/x509_test.go
libgo/go/crypto/x509/x509_test_import.go
libgo/go/database/sql/driver/driver.go
libgo/go/database/sql/fakedb_test.go
libgo/go/database/sql/sql.go
libgo/go/database/sql/sql_test.go
libgo/go/debug/dwarf/const.go
libgo/go/debug/dwarf/entry.go
libgo/go/debug/dwarf/entry_test.go
libgo/go/debug/dwarf/line_test.go
libgo/go/debug/dwarf/testdata/rnglistx.c [new file with mode: 0644]
libgo/go/debug/dwarf/testdata/rnglistx.elf [new file with mode: 0755]
libgo/go/debug/dwarf/type.go
libgo/go/debug/dwarf/unit.go
libgo/go/debug/elf/elf.go
libgo/go/debug/elf/file.go
libgo/go/debug/macho/macho.go
libgo/go/debug/pe/file.go
libgo/go/debug/pe/file_cgo_test.go
libgo/go/debug/pe/file_test.go
libgo/go/embed/embed.go
libgo/go/embed/internal/embedtest/embed_test.go
libgo/go/embed/internal/embedtest/testdata/-not-hidden/fortune.txt [new file with mode: 0644]
libgo/go/encoding/asn1/asn1.go
libgo/go/encoding/asn1/marshal.go
libgo/go/encoding/asn1/marshal_test.go
libgo/go/encoding/binary/varint.go
libgo/go/encoding/binary/varint_test.go
libgo/go/encoding/csv/fuzz.go
libgo/go/encoding/csv/reader.go
libgo/go/encoding/csv/reader_test.go
libgo/go/encoding/gob/debug.go
libgo/go/encoding/gob/decgen.go
libgo/go/encoding/gob/decoder.go
libgo/go/encoding/gob/dump.go
libgo/go/encoding/gob/encgen.go
libgo/go/encoding/gob/encoder_test.go
libgo/go/encoding/json/decode.go
libgo/go/encoding/json/encode.go
libgo/go/encoding/json/encode_test.go
libgo/go/encoding/json/fuzz.go
libgo/go/encoding/xml/typeinfo.go
libgo/go/encoding/xml/xml.go
libgo/go/encoding/xml/xml_test.go
libgo/go/errors/wrap.go
libgo/go/flag/flag.go
libgo/go/flag/flag_test.go
libgo/go/fmt/doc.go
libgo/go/fmt/format.go
libgo/go/go.mod
libgo/go/go/ast/ast.go
libgo/go/go/ast/ast_notypeparams.go [new file with mode: 0644]
libgo/go/go/ast/ast_typeparams.go [new file with mode: 0644]
libgo/go/go/ast/commentmap.go
libgo/go/go/ast/walk.go
libgo/go/go/ast/walk_notypeparams.go [new file with mode: 0644]
libgo/go/go/ast/walk_typeparams.go [new file with mode: 0644]
libgo/go/go/build/build.go
libgo/go/go/build/build_test.go
libgo/go/go/build/constraint/expr.go
libgo/go/go/build/constraint/expr_test.go
libgo/go/go/build/deps_test.go
libgo/go/go/build/doc.go
libgo/go/go/build/gc.go
libgo/go/go/build/gccgo.go
libgo/go/go/build/read.go
libgo/go/go/build/read_test.go
libgo/go/go/build/syslist.go
libgo/go/go/constant/value.go
libgo/go/go/constant/value_test.go
libgo/go/go/doc/example.go
libgo/go/go/doc/example_test.go
libgo/go/go/doc/headscan.go
libgo/go/go/format/format_test.go
libgo/go/go/internal/gccgoimporter/gccgoinstallation_test.go
libgo/go/go/internal/gccgoimporter/importer_test.go
libgo/go/go/internal/gcimporter/gcimporter.go
libgo/go/go/internal/gcimporter/iimport.go
libgo/go/go/internal/srcimporter/srcimporter.go
libgo/go/go/internal/typeparams/common.go [new file with mode: 0644]
libgo/go/go/internal/typeparams/notypeparams.go [new file with mode: 0644]
libgo/go/go/internal/typeparams/typeparams.go [new file with mode: 0644]
libgo/go/go/parser/error_test.go
libgo/go/go/parser/interface.go
libgo/go/go/parser/parser.go
libgo/go/go/parser/performance_test.go
libgo/go/go/parser/resolver.go [new file with mode: 0644]
libgo/go/go/parser/resolver_test.go [new file with mode: 0644]
libgo/go/go/parser/short_test.go
libgo/go/go/parser/testdata/chans.go2 [new file with mode: 0644]
libgo/go/go/parser/testdata/issue11377.src [new file with mode: 0644]
libgo/go/go/parser/testdata/issue23434.src [new file with mode: 0644]
libgo/go/go/parser/testdata/issue34946.src [new file with mode: 0644]
libgo/go/go/parser/testdata/issue44504.src [new file with mode: 0644]
libgo/go/go/parser/testdata/linalg.go2 [new file with mode: 0644]
libgo/go/go/parser/testdata/map.go2 [new file with mode: 0644]
libgo/go/go/parser/testdata/metrics.go2 [new file with mode: 0644]
libgo/go/go/parser/testdata/resolution/issue45136.src [new file with mode: 0644]
libgo/go/go/parser/testdata/resolution/issue45160.src [new file with mode: 0644]
libgo/go/go/parser/testdata/resolution/resolution.src [new file with mode: 0644]
libgo/go/go/parser/testdata/resolution/typeparams.go2 [new file with mode: 0644]
libgo/go/go/parser/testdata/set.go2 [new file with mode: 0644]
libgo/go/go/parser/testdata/slices.go2 [new file with mode: 0644]
libgo/go/go/parser/testdata/sort.go2 [new file with mode: 0644]
libgo/go/go/parser/testdata/typeparams.src [new file with mode: 0644]
libgo/go/go/printer/gobuild.go [new file with mode: 0644]
libgo/go/go/printer/nodes.go
libgo/go/go/printer/printer.go
libgo/go/go/printer/printer_test.go
libgo/go/go/printer/testdata/declarations.input
libgo/go/go/printer/testdata/generics.golden [new file with mode: 0644]
libgo/go/go/printer/testdata/generics.input [new file with mode: 0644]
libgo/go/go/printer/testdata/gobuild1.golden [new file with mode: 0644]
libgo/go/go/printer/testdata/gobuild1.input [new file with mode: 0644]
libgo/go/go/printer/testdata/gobuild2.golden [new file with mode: 0644]
libgo/go/go/printer/testdata/gobuild2.input [new file with mode: 0644]
libgo/go/go/printer/testdata/gobuild3.golden [new file with mode: 0644]
libgo/go/go/printer/testdata/gobuild3.input [new file with mode: 0644]
libgo/go/go/printer/testdata/gobuild4.golden [new file with mode: 0644]
libgo/go/go/printer/testdata/gobuild4.input [new file with mode: 0644]
libgo/go/go/printer/testdata/gobuild5.golden [new file with mode: 0644]
libgo/go/go/printer/testdata/gobuild5.input [new file with mode: 0644]
libgo/go/go/printer/testdata/gobuild6.golden [new file with mode: 0644]
libgo/go/go/printer/testdata/gobuild6.input [new file with mode: 0644]
libgo/go/go/printer/testdata/gobuild7.golden [new file with mode: 0644]
libgo/go/go/printer/testdata/gobuild7.input [new file with mode: 0644]
libgo/go/go/printer/testdata/parser.go
libgo/go/go/scanner/errors.go
libgo/go/go/scanner/scanner.go
libgo/go/go/scanner/scanner_test.go
libgo/go/go/token/position.go
libgo/go/go/token/position_bench_test.go [new file with mode: 0644]
libgo/go/go/types/api.go
libgo/go/go/types/api_notypeparams.go [new file with mode: 0644]
libgo/go/go/types/api_test.go
libgo/go/go/types/api_typeparams.go [new file with mode: 0644]
libgo/go/go/types/api_typeparams_test.go [new file with mode: 0644]
libgo/go/go/types/assignments.go
libgo/go/go/types/builtins.go
libgo/go/go/types/builtins_test.go
libgo/go/go/types/call.go
libgo/go/go/types/check.go
libgo/go/go/types/check_test.go
libgo/go/go/types/conversions.go
libgo/go/go/types/decl.go
libgo/go/go/types/errorcodes.go
libgo/go/go/types/errors.go
libgo/go/go/types/errors_test.go [new file with mode: 0644]
libgo/go/go/types/eval_test.go
libgo/go/go/types/example_test.go
libgo/go/go/types/expr.go
libgo/go/go/types/exprstring.go
libgo/go/go/types/gotype.go
libgo/go/go/types/index.go [new file with mode: 0644]
libgo/go/go/types/infer.go [new file with mode: 0644]
libgo/go/go/types/issues_test.go
libgo/go/go/types/lookup.go
libgo/go/go/types/methodset.go
libgo/go/go/types/methodset_test.go [new file with mode: 0644]
libgo/go/go/types/object.go
libgo/go/go/types/operand.go
libgo/go/go/types/predicates.go
libgo/go/go/types/resolver.go
libgo/go/go/types/sanitize.go [new file with mode: 0644]
libgo/go/go/types/scope.go
libgo/go/go/types/sizeof_test.go [new file with mode: 0644]
libgo/go/go/types/sizes.go
libgo/go/go/types/stdlib_test.go
libgo/go/go/types/stmt.go
libgo/go/go/types/subst.go [new file with mode: 0644]
libgo/go/go/types/testdata/check/blank.src [moved from libgo/go/go/types/testdata/blank.src with 100% similarity]
libgo/go/go/types/testdata/check/builtins.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/check/builtins.src [moved from libgo/go/go/types/testdata/builtins.src with 97% similarity]
libgo/go/go/types/testdata/check/chans.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/check/const0.src [moved from libgo/go/go/types/testdata/const0.src with 93% similarity]
libgo/go/go/types/testdata/check/const1.src [moved from libgo/go/go/types/testdata/const1.src with 92% similarity]
libgo/go/go/types/testdata/check/constdecl.src [moved from libgo/go/go/types/testdata/constdecl.src with 100% similarity]
libgo/go/go/types/testdata/check/conversions.src [moved from libgo/go/go/types/testdata/conversions.src with 100% similarity]
libgo/go/go/types/testdata/check/conversions2.src [moved from libgo/go/go/types/testdata/conversions2.src with 100% similarity]
libgo/go/go/types/testdata/check/cycles.src [moved from libgo/go/go/types/testdata/cycles.src with 100% similarity]
libgo/go/go/types/testdata/check/cycles1.src [moved from libgo/go/go/types/testdata/cycles1.src with 100% similarity]
libgo/go/go/types/testdata/check/cycles2.src [moved from libgo/go/go/types/testdata/cycles2.src with 100% similarity]
libgo/go/go/types/testdata/check/cycles3.src [moved from libgo/go/go/types/testdata/cycles3.src with 100% similarity]
libgo/go/go/types/testdata/check/cycles4.src [moved from libgo/go/go/types/testdata/cycles4.src with 100% similarity]
libgo/go/go/types/testdata/check/cycles5.src [moved from libgo/go/go/types/testdata/cycles5.src with 100% similarity]
libgo/go/go/types/testdata/check/decls0.src [moved from libgo/go/go/types/testdata/decls0.src with 90% similarity]
libgo/go/go/types/testdata/check/decls1.src [moved from libgo/go/go/types/testdata/decls1.src with 100% similarity]
libgo/go/go/types/testdata/check/decls2/decls2a.src [moved from libgo/go/go/types/testdata/decls2a.src with 100% similarity]
libgo/go/go/types/testdata/check/decls2/decls2b.src [moved from libgo/go/go/types/testdata/decls2b.src with 100% similarity]
libgo/go/go/types/testdata/check/decls3.src [moved from libgo/go/go/types/testdata/decls3.src with 100% similarity]
libgo/go/go/types/testdata/check/decls4.src [moved from libgo/go/go/types/testdata/decls4.src with 100% similarity]
libgo/go/go/types/testdata/check/decls5.src [moved from libgo/go/go/types/testdata/decls5.src with 100% similarity]
libgo/go/go/types/testdata/check/errors.src [moved from libgo/go/go/types/testdata/errors.src with 100% similarity]
libgo/go/go/types/testdata/check/expr0.src [moved from libgo/go/go/types/testdata/expr0.src with 100% similarity]
libgo/go/go/types/testdata/check/expr1.src [moved from libgo/go/go/types/testdata/expr1.src with 100% similarity]
libgo/go/go/types/testdata/check/expr2.src [moved from libgo/go/go/types/testdata/expr2.src with 100% similarity]
libgo/go/go/types/testdata/check/expr3.src [moved from libgo/go/go/types/testdata/expr3.src with 95% similarity]
libgo/go/go/types/testdata/check/go1_12.src [new file with mode: 0644]
libgo/go/go/types/testdata/check/go1_13.src [new file with mode: 0644]
libgo/go/go/types/testdata/check/go1_16.src [new file with mode: 0644]
libgo/go/go/types/testdata/check/go1_8.src [new file with mode: 0644]
libgo/go/go/types/testdata/check/gotos.src [moved from libgo/go/go/types/testdata/gotos.src with 100% similarity]
libgo/go/go/types/testdata/check/importC.src [moved from libgo/go/go/types/testdata/importC.src with 100% similarity]
libgo/go/go/types/testdata/check/importdecl0/importdecl0a.src [moved from libgo/go/go/types/testdata/importdecl0a.src with 95% similarity]
libgo/go/go/types/testdata/check/importdecl0/importdecl0b.src [moved from libgo/go/go/types/testdata/importdecl0b.src with 93% similarity]
libgo/go/go/types/testdata/check/importdecl1/importdecl1a.src [moved from libgo/go/go/types/testdata/importdecl1a.src with 100% similarity]
libgo/go/go/types/testdata/check/importdecl1/importdecl1b.src [moved from libgo/go/go/types/testdata/importdecl1b.src with 77% similarity]
libgo/go/go/types/testdata/check/init0.src [moved from libgo/go/go/types/testdata/init0.src with 100% similarity]
libgo/go/go/types/testdata/check/init1.src [moved from libgo/go/go/types/testdata/init1.src with 100% similarity]
libgo/go/go/types/testdata/check/init2.src [moved from libgo/go/go/types/testdata/init2.src with 100% similarity]
libgo/go/go/types/testdata/check/issue25008/issue25008a.src [moved from libgo/go/go/types/testdata/issue25008a.src with 100% similarity]
libgo/go/go/types/testdata/check/issue25008/issue25008b.src [moved from libgo/go/go/types/testdata/issue25008b.src with 100% similarity]
libgo/go/go/types/testdata/check/issues.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/check/issues.src [moved from libgo/go/go/types/testdata/issues.src with 94% similarity]
libgo/go/go/types/testdata/check/labels.src [moved from libgo/go/go/types/testdata/labels.src with 100% similarity]
libgo/go/go/types/testdata/check/linalg.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/check/literals.src [moved from libgo/go/go/types/testdata/literals.src with 100% similarity]
libgo/go/go/types/testdata/check/main.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/check/main.src [new file with mode: 0644]
libgo/go/go/types/testdata/check/map.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/check/map2.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/check/methodsets.src [moved from libgo/go/go/types/testdata/methodsets.src with 100% similarity]
libgo/go/go/types/testdata/check/shifts.src [moved from libgo/go/go/types/testdata/shifts.src with 98% similarity]
libgo/go/go/types/testdata/check/slices.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/check/stmt0.src [moved from libgo/go/go/types/testdata/stmt0.src with 98% similarity]
libgo/go/go/types/testdata/check/stmt1.src [moved from libgo/go/go/types/testdata/stmt1.src with 100% similarity]
libgo/go/go/types/testdata/check/tinference.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/check/tmp.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/check/todos.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/check/typeinst.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/check/typeinst2.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/check/typeparams.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/check/vardecl.src [moved from libgo/go/go/types/testdata/vardecl.src with 100% similarity]
libgo/go/go/types/testdata/examples/functions.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/examples/inference.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/examples/methods.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/examples/types.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue20583.src [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue23203a.src [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue23203b.src [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue26390.src [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue28251.src [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue39634.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue39664.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue39680.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue39693.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue39699.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue39711.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue39723.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue39725.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue39754.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue39755.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue39768.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue39938.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue39948.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue39976.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue39982.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue40038.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue40056.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue40057.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue40301.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue40684.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue41124.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue42695.src [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue42758.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue42987.src [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue43087.src [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue43110.src [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue43124.src [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue43125.src [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue43190.src [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue44688.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue44799.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue45548.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue45635.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue45985.go2 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue46403.src [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue46404.go1 [new file with mode: 0644]
libgo/go/go/types/testdata/fixedbugs/issue6977.src [new file with mode: 0644]
libgo/go/go/types/type.go
libgo/go/go/types/types_test.go [new file with mode: 0644]
libgo/go/go/types/typestring.go
libgo/go/go/types/typestring_test.go
libgo/go/go/types/typexpr.go
libgo/go/go/types/unify.go [new file with mode: 0644]
libgo/go/go/types/universe.go
libgo/go/go/types/version.go [new file with mode: 0644]
libgo/go/golang.org/x/crypto/chacha20/chacha_arm64.go
libgo/go/golang.org/x/crypto/chacha20/chacha_noasm.go
libgo/go/golang.org/x/crypto/chacha20/chacha_ppc64le.go
libgo/go/golang.org/x/crypto/chacha20/chacha_s390x.go
libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go
libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go
libgo/go/golang.org/x/crypto/cryptobyte/asn1.go
libgo/go/golang.org/x/crypto/curve25519/curve25519_amd64.go
libgo/go/golang.org/x/crypto/curve25519/curve25519_noasm.go
libgo/go/golang.org/x/crypto/internal/subtle/aliasing.go
libgo/go/golang.org/x/crypto/internal/subtle/aliasing_purego.go [new file with mode: 0644]
libgo/go/golang.org/x/crypto/poly1305/bits_compat.go
libgo/go/golang.org/x/crypto/poly1305/bits_go1.13.go
libgo/go/golang.org/x/crypto/poly1305/mac_noasm.go
libgo/go/golang.org/x/crypto/poly1305/sum_amd64.go
libgo/go/golang.org/x/crypto/poly1305/sum_ppc64le.go
libgo/go/golang.org/x/crypto/poly1305/sum_s390x.go
libgo/go/golang.org/x/mod/modfile/read.go
libgo/go/golang.org/x/mod/modfile/rule.go
libgo/go/golang.org/x/mod/module/module.go
libgo/go/golang.org/x/mod/module/pseudo.go [moved from libgo/go/cmd/go/internal/modfetch/pseudo.go with 95% similarity]
libgo/go/golang.org/x/mod/semver/semver.go
libgo/go/golang.org/x/net/dns/dnsmessage/message.go
libgo/go/golang.org/x/net/idna/idna10.0.0.go
libgo/go/golang.org/x/net/idna/idna9.0.0.go
libgo/go/golang.org/x/net/idna/tables10.0.0.go
libgo/go/golang.org/x/net/idna/tables11.0.0.go
libgo/go/golang.org/x/net/idna/tables12.0.0.go
libgo/go/golang.org/x/net/idna/tables13.0.0.go
libgo/go/golang.org/x/net/idna/tables9.0.0.go
libgo/go/golang.org/x/net/nettest/nettest_stub.go
libgo/go/golang.org/x/net/nettest/nettest_unix.go
libgo/go/golang.org/x/net/route/address.go
libgo/go/golang.org/x/net/route/binary.go
libgo/go/golang.org/x/net/route/interface.go
libgo/go/golang.org/x/net/route/interface_announce.go
libgo/go/golang.org/x/net/route/interface_classic.go
libgo/go/golang.org/x/net/route/interface_multicast.go
libgo/go/golang.org/x/net/route/message.go
libgo/go/golang.org/x/net/route/route.go
libgo/go/golang.org/x/net/route/route_classic.go
libgo/go/golang.org/x/net/route/sys.go
libgo/go/golang.org/x/net/route/syscall.go
libgo/go/golang.org/x/net/route/syscall_go1_12_darwin.go
libgo/go/golang.org/x/sys/cpu/cpu.go
libgo/go/golang.org/x/sys/cpu/cpu_aix.go
libgo/go/golang.org/x/sys/cpu/cpu_gc_arm64.go
libgo/go/golang.org/x/sys/cpu/cpu_gc_s390x.go
libgo/go/golang.org/x/sys/cpu/cpu_gc_x86.go
libgo/go/golang.org/x/sys/cpu/cpu_gccgo_arm64.go
libgo/go/golang.org/x/sys/cpu/cpu_gccgo_s390x.go
libgo/go/golang.org/x/sys/cpu/cpu_gccgo_x86.go
libgo/go/golang.org/x/sys/cpu/cpu_linux.go
libgo/go/golang.org/x/sys/cpu/cpu_linux_mips64x.go
libgo/go/golang.org/x/sys/cpu/cpu_linux_noinit.go
libgo/go/golang.org/x/sys/cpu/cpu_linux_ppc64x.go
libgo/go/golang.org/x/sys/cpu/cpu_mips64x.go
libgo/go/golang.org/x/sys/cpu/cpu_mipsx.go
libgo/go/golang.org/x/sys/cpu/cpu_other_arm.go
libgo/go/golang.org/x/sys/cpu/cpu_other_arm64.go
libgo/go/golang.org/x/sys/cpu/cpu_other_mips64x.go
libgo/go/golang.org/x/sys/cpu/cpu_ppc64x.go
libgo/go/golang.org/x/sys/cpu/cpu_riscv64.go
libgo/go/golang.org/x/sys/cpu/cpu_wasm.go
libgo/go/golang.org/x/sys/cpu/cpu_x86.go
libgo/go/golang.org/x/sys/cpu/syscall_aix_gccgo.go
libgo/go/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go
libgo/go/golang.org/x/text/secure/bidirule/bidirule10.0.0.go
libgo/go/golang.org/x/text/secure/bidirule/bidirule9.0.0.go
libgo/go/golang.org/x/text/unicode/bidi/bidi.go
libgo/go/golang.org/x/text/unicode/bidi/core.go
libgo/go/golang.org/x/text/unicode/bidi/tables10.0.0.go
libgo/go/golang.org/x/text/unicode/bidi/tables11.0.0.go
libgo/go/golang.org/x/text/unicode/bidi/tables12.0.0.go
libgo/go/golang.org/x/text/unicode/bidi/tables13.0.0.go
libgo/go/golang.org/x/text/unicode/bidi/tables9.0.0.go
libgo/go/golang.org/x/text/unicode/norm/tables10.0.0.go
libgo/go/golang.org/x/text/unicode/norm/tables11.0.0.go
libgo/go/golang.org/x/text/unicode/norm/tables12.0.0.go
libgo/go/golang.org/x/text/unicode/norm/tables13.0.0.go
libgo/go/golang.org/x/text/unicode/norm/tables9.0.0.go
libgo/go/golang.org/x/tools/cover/profile.go [new file with mode: 0644]
libgo/go/golang.org/x/tools/go/analysis/passes/buildtag/buildtag.go
libgo/go/golang.org/x/tools/go/analysis/passes/buildtag/buildtag_old.go [new file with mode: 0644]
libgo/go/golang.org/x/tools/go/analysis/passes/inspect/inspect.go
libgo/go/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go
libgo/go/golang.org/x/tools/go/analysis/passes/printf/printf.go
libgo/go/golang.org/x/tools/go/analysis/passes/sigchanyzer/sigchanyzer.go [new file with mode: 0644]
libgo/go/golang.org/x/tools/go/analysis/passes/stdmethods/stdmethods.go
libgo/go/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go
libgo/go/golang.org/x/tools/go/analysis/unitchecker/unitchecker112.go
libgo/go/hash/crc32/crc32_otherarch.go
libgo/go/hash/crc32/gen_const_ppc64le.go
libgo/go/hash/maphash/maphash.go
libgo/go/hash/maphash/maphash_test.go
libgo/go/html/fuzz.go
libgo/go/html/template/exec_test.go
libgo/go/image/color/palette/gen.go
libgo/go/image/draw/draw.go
libgo/go/image/geom.go
libgo/go/image/gif/reader.go
libgo/go/image/image.go
libgo/go/image/image_test.go
libgo/go/image/internal/imageutil/gen.go
libgo/go/image/jpeg/reader.go
libgo/go/image/names.go
libgo/go/image/png/fuzz.go
libgo/go/image/png/writer.go
libgo/go/image/ycbcr.go
libgo/go/index/suffixarray/gen.go
libgo/go/internal/buildcfg/cfg.go [new file with mode: 0644]
libgo/go/internal/buildcfg/exp.go [new file with mode: 0644]
libgo/go/internal/bytealg/bytealg.go
libgo/go/internal/bytealg/compare_generic.go
libgo/go/internal/bytealg/compare_native.go
libgo/go/internal/bytealg/count_generic.go
libgo/go/internal/bytealg/count_native.go
libgo/go/internal/bytealg/index_amd64.go
libgo/go/internal/bytealg/index_generic.go
libgo/go/internal/bytealg/index_native.go
libgo/go/internal/bytealg/index_ppc64x.go [new file with mode: 0644]
libgo/go/internal/bytealg/indexbyte_generic.go
libgo/go/internal/bytealg/indexbyte_native.go
libgo/go/internal/cfg/cfg.go
libgo/go/internal/cpu/cpu_arm64_android.go
libgo/go/internal/cpu/cpu_arm64_darwin.go
libgo/go/internal/cpu/cpu_arm64_freebsd.go
libgo/go/internal/cpu/cpu_arm64_hwcap.go
libgo/go/internal/cpu/cpu_arm64_linux.go
libgo/go/internal/cpu/cpu_arm64_other.go
libgo/go/internal/cpu/cpu_mips64x.go
libgo/go/internal/cpu/cpu_no_name.go
libgo/go/internal/cpu/cpu_ppc64x.go
libgo/go/internal/cpu/cpu_ppc64x_aix.go
libgo/go/internal/cpu/cpu_ppc64x_linux.go
libgo/go/internal/cpu/cpu_x86.go
libgo/go/internal/cpu/cpu_x86_test.go
libgo/go/internal/execabs/execabs_test.go
libgo/go/internal/goexperiment/exp_fieldtrack_off.go [new file with mode: 0644]
libgo/go/internal/goexperiment/exp_fieldtrack_on.go [new file with mode: 0644]
libgo/go/internal/goexperiment/exp_preemptibleloops_off.go [new file with mode: 0644]
libgo/go/internal/goexperiment/exp_preemptibleloops_on.go [new file with mode: 0644]
libgo/go/internal/goexperiment/exp_regabi_off.go [new file with mode: 0644]
libgo/go/internal/goexperiment/exp_regabi_on.go [new file with mode: 0644]
libgo/go/internal/goexperiment/exp_regabiargs_off.go [new file with mode: 0644]
libgo/go/internal/goexperiment/exp_regabiargs_on.go [new file with mode: 0644]
libgo/go/internal/goexperiment/exp_regabidefer_off.go [new file with mode: 0644]
libgo/go/internal/goexperiment/exp_regabidefer_on.go [new file with mode: 0644]
libgo/go/internal/goexperiment/exp_regabig_off.go [new file with mode: 0644]
libgo/go/internal/goexperiment/exp_regabig_on.go [new file with mode: 0644]
libgo/go/internal/goexperiment/exp_regabireflect_off.go [new file with mode: 0644]
libgo/go/internal/goexperiment/exp_regabireflect_on.go [new file with mode: 0644]
libgo/go/internal/goexperiment/exp_regabiwrappers_off.go [new file with mode: 0644]
libgo/go/internal/goexperiment/exp_regabiwrappers_on.go [new file with mode: 0644]
libgo/go/internal/goexperiment/exp_staticlockranking_off.go [new file with mode: 0644]
libgo/go/internal/goexperiment/exp_staticlockranking_on.go [new file with mode: 0644]
libgo/go/internal/goexperiment/flags.go [new file with mode: 0644]
libgo/go/internal/goexperiment/mkconsts.go [new file with mode: 0644]
libgo/go/internal/goroot/gc.go
libgo/go/internal/goroot/gccgo.go
libgo/go/internal/goversion/goversion.go
libgo/go/internal/itoa/itoa.go [new file with mode: 0644]
libgo/go/internal/itoa/itoa_test.go [new file with mode: 0644]
libgo/go/internal/poll/copy_file_range_linux.go
libgo/go/internal/poll/errno_unix.go
libgo/go/internal/poll/errno_windows.go
libgo/go/internal/poll/error_stub_test.go
libgo/go/internal/poll/export_linux_test.go [new file with mode: 0644]
libgo/go/internal/poll/export_posix_test.go
libgo/go/internal/poll/export_test.go
libgo/go/internal/poll/fcntl_js.go
libgo/go/internal/poll/fcntl_libc.go
libgo/go/internal/poll/fcntl_syscall.go
libgo/go/internal/poll/fd.go
libgo/go/internal/poll/fd_fsync_posix.go
libgo/go/internal/poll/fd_io_plan9.go
libgo/go/internal/poll/fd_poll_js.go
libgo/go/internal/poll/fd_poll_runtime.go
libgo/go/internal/poll/fd_posix.go
libgo/go/internal/poll/fd_posix_test.go
libgo/go/internal/poll/fd_unix.go
libgo/go/internal/poll/fd_windows.go
libgo/go/internal/poll/fd_writev_darwin.go
libgo/go/internal/poll/fd_writev_illumos.go
libgo/go/internal/poll/fd_writev_unix.go
libgo/go/internal/poll/hook_cloexec.go
libgo/go/internal/poll/hook_unix.go
libgo/go/internal/poll/iovec_illumos.go
libgo/go/internal/poll/iovec_unix.go
libgo/go/internal/poll/sendfile_bsd.go
libgo/go/internal/poll/sendfile_solaris.go
libgo/go/internal/poll/sock_cloexec.go
libgo/go/internal/poll/sockopt.go
libgo/go/internal/poll/sockopt_unix.go
libgo/go/internal/poll/sockoptip.go
libgo/go/internal/poll/splice_linux.go
libgo/go/internal/poll/splice_linux_test.go [new file with mode: 0644]
libgo/go/internal/poll/strconv.go
libgo/go/internal/poll/sys_cloexec.go
libgo/go/internal/poll/writev.go
libgo/go/internal/race/norace.go
libgo/go/internal/race/race.go
libgo/go/internal/reflectlite/all_test.go
libgo/go/internal/reflectlite/type.go
libgo/go/internal/syscall/execenv/execenv_default.go
libgo/go/internal/syscall/execenv/execenv_windows.go
libgo/go/internal/syscall/unix/at.go
libgo/go/internal/syscall/unix/getentropy_darwin.go [new file with mode: 0644]
libgo/go/internal/syscall/unix/getrandom.go [new file with mode: 0644]
libgo/go/internal/syscall/unix/getrandom_dragonfly.go [new file with mode: 0644]
libgo/go/internal/syscall/unix/getrandom_freebsd.go
libgo/go/internal/syscall/unix/getrandom_linux.go
libgo/go/internal/syscall/unix/getrandom_solaris.go [new file with mode: 0644]
libgo/go/internal/syscall/unix/nonblocking.go
libgo/go/internal/syscall/unix/nonblocking_js.go
libgo/go/internal/syscall/unix/nonblocking_libc.go
libgo/go/internal/syscall/unix/sysnum_linux_generic.go
libgo/go/internal/syscall/unix/sysnum_linux_mips64x.go
libgo/go/internal/syscall/unix/sysnum_linux_mipsx.go
libgo/go/internal/syscall/unix/sysnum_linux_ppc64x.go
libgo/go/internal/testenv/testenv_cgo.go
libgo/go/internal/testenv/testenv_notwin.go
libgo/go/internal/trace/parser.go
libgo/go/io/example_test.go
libgo/go/io/fs/example_test.go [new file with mode: 0644]
libgo/go/io/fs/fs.go
libgo/go/io/fs/readdir.go
libgo/go/io/fs/readdir_test.go
libgo/go/io/fs/readfile.go
libgo/go/io/fs/sub.go
libgo/go/io/fs/walk_test.go
libgo/go/io/io.go
libgo/go/io/ioutil/tempfile.go
libgo/go/io/ioutil/tempfile_test.go
libgo/go/log/syslog/example_test.go
libgo/go/log/syslog/syslog.go
libgo/go/log/syslog/syslog_test.go
libgo/go/log/syslog/syslog_unix.go
libgo/go/math/all_test.go
libgo/go/math/arith_s390x.go
libgo/go/math/asin.go
libgo/go/math/atan.go
libgo/go/math/big/arith.go
libgo/go/math/big/arith_amd64.go
libgo/go/math/big/arith_decl.go
libgo/go/math/big/arith_decl_pure.go
libgo/go/math/big/arith_decl_s390x.go
libgo/go/math/big/arith_s390x_test.go
libgo/go/math/big/arith_test.go
libgo/go/math/big/int.go
libgo/go/math/big/link_test.go
libgo/go/math/big/nat.go
libgo/go/math/big/natdiv.go [new file with mode: 0644]
libgo/go/math/bits/bits.go
libgo/go/math/bits/bits_errors.go
libgo/go/math/bits/bits_errors_bootstrap.go
libgo/go/math/bits/bits_tables.go
libgo/go/math/bits/make_examples.go
libgo/go/math/bits/make_tables.go
libgo/go/math/cmplx/huge_test.go
libgo/go/math/const.go
libgo/go/math/const_test.go [new file with mode: 0644]
libgo/go/math/dim.go
libgo/go/math/dim_noasm.go [new file with mode: 0644]
libgo/go/math/exp.go
libgo/go/math/exp2_noasm.go [new file with mode: 0644]
libgo/go/math/exp_amd64.go [moved from libgo/go/math/exp_asm.go with 93% similarity]
libgo/go/math/exp_noasm.go [new file with mode: 0644]
libgo/go/math/expm1.go
libgo/go/math/floor.go
libgo/go/math/floor_noasm.go [new file with mode: 0644]
libgo/go/math/fma.go
libgo/go/math/frexp.go
libgo/go/math/huge_test.go
libgo/go/math/log.go
libgo/go/math/mod.go
libgo/go/math/modf.go
libgo/go/math/modf_noasm.go [new file with mode: 0644]
libgo/go/math/rand/export_test.go [new file with mode: 0644]
libgo/go/math/rand/gen_cooked.go
libgo/go/math/rand/race_test.go
libgo/go/math/rand/rand.go
libgo/go/math/rand/rand_test.go
libgo/go/math/remainder.go
libgo/go/math/sin.go
libgo/go/math/sinh.go
libgo/go/math/stubs.go [new file with mode: 0644]
libgo/go/math/tan.go
libgo/go/math/tanh.go
libgo/go/mime/multipart/multipart.go
libgo/go/mime/testdata/test.types.globs2 [new file with mode: 0644]
libgo/go/mime/type.go
libgo/go/mime/type_unix.go
libgo/go/mime/type_unix_test.go [new file with mode: 0644]
libgo/go/net/addrselect.go
libgo/go/net/addrselect_test.go
libgo/go/net/cgo_aix.go
libgo/go/net/cgo_android.go
libgo/go/net/cgo_bsd.go
libgo/go/net/cgo_linux.go
libgo/go/net/cgo_netbsd.go
libgo/go/net/cgo_openbsd.go
libgo/go/net/cgo_resnew.go
libgo/go/net/cgo_resold.go
libgo/go/net/cgo_socknew.go
libgo/go/net/cgo_sockold.go
libgo/go/net/cgo_solaris.go
libgo/go/net/cgo_stub.go
libgo/go/net/cgo_unix.go
libgo/go/net/cgo_unix_test.go
libgo/go/net/cgo_windows.go
libgo/go/net/conf.go
libgo/go/net/conf_netcgo.go
libgo/go/net/conf_test.go
libgo/go/net/conn_test.go
libgo/go/net/dial.go
libgo/go/net/dial_test.go
libgo/go/net/dial_unix_test.go
libgo/go/net/dnsclient.go
libgo/go/net/dnsclient_unix.go
libgo/go/net/dnsclient_unix_test.go
libgo/go/net/dnsconfig_unix.go
libgo/go/net/dnsconfig_unix_test.go
libgo/go/net/dnsname_test.go
libgo/go/net/error_posix.go
libgo/go/net/error_posix_test.go
libgo/go/net/error_test.go
libgo/go/net/error_unix.go
libgo/go/net/error_unix_test.go
libgo/go/net/external_test.go
libgo/go/net/fcntl_libc_test.go [new file with mode: 0644]
libgo/go/net/fcntl_syscall_test.go [new file with mode: 0644]
libgo/go/net/fd_posix.go
libgo/go/net/fd_unix.go
libgo/go/net/file_stub.go
libgo/go/net/file_test.go
libgo/go/net/file_unix.go
libgo/go/net/hook_unix.go
libgo/go/net/hosts_test.go
libgo/go/net/http/cgi/integration_test.go
libgo/go/net/http/cgi/posix_test.go
libgo/go/net/http/client.go
libgo/go/net/http/client_test.go
libgo/go/net/http/cookie.go
libgo/go/net/http/cookiejar/jar.go
libgo/go/net/http/cookiejar/punycode.go
libgo/go/net/http/example_test.go
libgo/go/net/http/fcgi/child.go
libgo/go/net/http/fcgi/fcgi_test.go
libgo/go/net/http/filetransport_test.go
libgo/go/net/http/fs.go
libgo/go/net/http/fs_test.go
libgo/go/net/http/h2_bundle.go
libgo/go/net/http/header.go
libgo/go/net/http/http.go
libgo/go/net/http/http_test.go
libgo/go/net/http/httptest/recorder.go
libgo/go/net/http/httptest/recorder_test.go
libgo/go/net/http/httptest/server.go
libgo/go/net/http/httptrace/trace.go
libgo/go/net/http/httputil/dump_test.go
libgo/go/net/http/httputil/reverseproxy.go
libgo/go/net/http/httputil/reverseproxy_test.go
libgo/go/net/http/internal/ascii/print.go [new file with mode: 0644]
libgo/go/net/http/internal/ascii/print_test.go [new file with mode: 0644]
libgo/go/net/http/internal/testcert/testcert.go [moved from libgo/go/net/http/internal/testcert.go with 94% similarity]
libgo/go/net/http/omithttp2.go
libgo/go/net/http/pprof/pprof.go
libgo/go/net/http/request.go
libgo/go/net/http/request_test.go
libgo/go/net/http/roundtrip.go
libgo/go/net/http/roundtrip_js.go
libgo/go/net/http/serve_test.go
libgo/go/net/http/server.go
libgo/go/net/http/sniff_test.go
libgo/go/net/http/transfer.go
libgo/go/net/http/transport.go
libgo/go/net/http/transport_internal_test.go
libgo/go/net/http/transport_test.go
libgo/go/net/http/triv.go
libgo/go/net/interface.go
libgo/go/net/interface_bsd.go
libgo/go/net/interface_bsd_test.go
libgo/go/net/interface_bsdvar.go
libgo/go/net/interface_freebsd.go
libgo/go/net/interface_plan9.go
libgo/go/net/interface_stub.go
libgo/go/net/interface_test.go
libgo/go/net/interface_unix_test.go
libgo/go/net/internal/socktest/main_test.go
libgo/go/net/internal/socktest/main_unix_test.go
libgo/go/net/internal/socktest/switch_posix.go
libgo/go/net/internal/socktest/switch_stub.go
libgo/go/net/internal/socktest/switch_unix.go
libgo/go/net/internal/socktest/sys_cloexec.go
libgo/go/net/internal/socktest/sys_unix.go
libgo/go/net/ip.go
libgo/go/net/ip_test.go
libgo/go/net/iprawsock_posix.go
libgo/go/net/iprawsock_test.go
libgo/go/net/ipsock.go
libgo/go/net/ipsock_plan9.go
libgo/go/net/ipsock_posix.go
libgo/go/net/listen_test.go
libgo/go/net/lookup.go
libgo/go/net/lookup_fake.go
libgo/go/net/lookup_plan9.go
libgo/go/net/lookup_test.go
libgo/go/net/lookup_unix.go
libgo/go/net/lookup_windows_test.go
libgo/go/net/main_cloexec_test.go
libgo/go/net/main_conf_test.go
libgo/go/net/main_noconf_test.go
libgo/go/net/main_posix_test.go
libgo/go/net/main_test.go
libgo/go/net/main_unix_test.go
libgo/go/net/mockserver_test.go
libgo/go/net/net.go
libgo/go/net/net_fake.go
libgo/go/net/net_test.go
libgo/go/net/nss.go
libgo/go/net/nss_test.go
libgo/go/net/packetconn_test.go
libgo/go/net/parse.go
libgo/go/net/port_unix.go
libgo/go/net/protoconn_test.go
libgo/go/net/rawconn_stub_test.go
libgo/go/net/rawconn_test.go
libgo/go/net/rawconn_unix_test.go
libgo/go/net/rpc/server.go
libgo/go/net/sendfile_stub.go
libgo/go/net/sendfile_test.go
libgo/go/net/sendfile_unix_alt.go
libgo/go/net/server_test.go
libgo/go/net/sock_bsd.go
libgo/go/net/sock_cloexec.go
libgo/go/net/sock_posix.go
libgo/go/net/sock_stub.go
libgo/go/net/sockaddr_posix.go
libgo/go/net/sockopt_bsd.go
libgo/go/net/sockopt_posix.go
libgo/go/net/sockopt_stub.go
libgo/go/net/sockoptip_bsdvar.go
libgo/go/net/sockoptip_posix.go
libgo/go/net/sockoptip_stub.go
libgo/go/net/splice_stub.go
libgo/go/net/splice_test.go
libgo/go/net/sys_cloexec.go
libgo/go/net/tcpsock.go
libgo/go/net/tcpsock_posix.go
libgo/go/net/tcpsock_test.go
libgo/go/net/tcpsock_unix_test.go
libgo/go/net/tcpsockopt_plan9.go
libgo/go/net/tcpsockopt_posix.go
libgo/go/net/tcpsockopt_stub.go
libgo/go/net/tcpsockopt_unix.go
libgo/go/net/testdata/ipv4-hosts
libgo/go/net/timeout_test.go
libgo/go/net/udpsock.go
libgo/go/net/udpsock_plan9.go
libgo/go/net/udpsock_posix.go
libgo/go/net/udpsock_test.go
libgo/go/net/unixsock_posix.go
libgo/go/net/unixsock_readmsg_cloexec.go [new file with mode: 0644]
libgo/go/net/unixsock_readmsg_cmsg_cloexec.go [new file with mode: 0644]
libgo/go/net/unixsock_readmsg_other.go [new file with mode: 0644]
libgo/go/net/unixsock_readmsg_test.go [new file with mode: 0644]
libgo/go/net/unixsock_test.go
libgo/go/net/unixsock_windows_test.go
libgo/go/net/url/url.go
libgo/go/net/url/url_test.go
libgo/go/net/write_unix_test.go
libgo/go/net/writev_test.go
libgo/go/net/writev_unix.go
libgo/go/os/env_unix_test.go
libgo/go/os/error.go
libgo/go/os/error_errno.go
libgo/go/os/error_posix.go
libgo/go/os/error_test.go
libgo/go/os/error_unix_test.go
libgo/go/os/error_windows_test.go
libgo/go/os/example_test.go
libgo/go/os/exec.go
libgo/go/os/exec/exec_linux_test.go
libgo/go/os/exec/exec_posix_test.go
libgo/go/os/exec/exec_test.go
libgo/go/os/exec/exec_unix.go
libgo/go/os/exec/exec_windows_test.go [new file with mode: 0644]
libgo/go/os/exec/lp_js.go
libgo/go/os/exec/lp_unix.go
libgo/go/os/exec/lp_unix_test.go
libgo/go/os/exec/read3.go
libgo/go/os/exec_plan9.go
libgo/go/os/exec_posix.go
libgo/go/os/exec_unix.go
libgo/go/os/exec_unix_test.go
libgo/go/os/exec_windows.go
libgo/go/os/executable_path.go
libgo/go/os/executable_plan9.go
libgo/go/os/executable_procfs.go
libgo/go/os/executable_sysctl.go
libgo/go/os/executable_test.go
libgo/go/os/export_unix_test.go
libgo/go/os/export_windows_test.go
libgo/go/os/fifo_test.go
libgo/go/os/file.go
libgo/go/os/file_plan9.go
libgo/go/os/file_posix.go
libgo/go/os/file_unix.go
libgo/go/os/os_test.go
libgo/go/os/os_unix_test.go
libgo/go/os/os_windows_test.go
libgo/go/os/path_test.go
libgo/go/os/path_unix.go
libgo/go/os/path_windows.go
libgo/go/os/path_windows_test.go
libgo/go/os/pipe2_bsd.go
libgo/go/os/pipe2_illumos.go
libgo/go/os/pipe_bsd.go
libgo/go/os/pipe_test.go
libgo/go/os/rawconn.go
libgo/go/os/rawconn_test.go
libgo/go/os/readfrom_linux_test.go
libgo/go/os/readfrom_stub.go
libgo/go/os/removeall_at.go
libgo/go/os/removeall_noat.go
libgo/go/os/removeall_test.go
libgo/go/os/signal/doc.go
libgo/go/os/signal/example_unix_test.go
libgo/go/os/signal/internal/pty/pty.go
libgo/go/os/signal/signal_cgo_test.go
libgo/go/os/signal/signal_linux_test.go
libgo/go/os/signal/signal_plan9_test.go
libgo/go/os/signal/signal_test.go
libgo/go/os/signal/signal_unix.go
libgo/go/os/stat_js.go
libgo/go/os/stat_test.go
libgo/go/os/stat_unix.go
libgo/go/os/sticky_bsd.go
libgo/go/os/sticky_notbsd.go
libgo/go/os/str.go
libgo/go/os/sys_bsd.go
libgo/go/os/sys_js.go
libgo/go/os/sys_unix.go
libgo/go/os/tempfile.go
libgo/go/os/timeout_test.go
libgo/go/os/types_unix.go
libgo/go/os/user/cgo_lookup_unix.go
libgo/go/os/user/cgo_unix_test.go
libgo/go/os/user/listgroups_aix.go
libgo/go/os/user/listgroups_illumos.go [moved from libgo/go/os/user/listgroups_solaris.go with 70% similarity]
libgo/go/os/user/listgroups_unix.go
libgo/go/os/user/lookup_android.go
libgo/go/os/user/lookup_stubs.go
libgo/go/os/user/lookup_unix.go
libgo/go/os/user/lookup_unix_test.go
libgo/go/os/user/user_test.go
libgo/go/os/wait_unimp.go
libgo/go/os/wait_wait6.go
libgo/go/os/wait_waitid.go
libgo/go/path/filepath/example_unix_test.go
libgo/go/path/filepath/example_unix_walk_test.go
libgo/go/path/filepath/match_test.go
libgo/go/path/filepath/path.go
libgo/go/path/filepath/path_test.go
libgo/go/path/filepath/path_unix.go
libgo/go/path/filepath/symlink_unix.go
libgo/go/plugin/plugin_dlopen.go
libgo/go/plugin/plugin_stubs.go
libgo/go/plugin/plugin_test.go
libgo/go/reflect/all_test.go
libgo/go/reflect/internal/example1/example.go [new file with mode: 0644]
libgo/go/reflect/internal/example2/example.go [new file with mode: 0644]
libgo/go/reflect/type.go
libgo/go/reflect/value.go
libgo/go/reflect/visiblefields.go [new file with mode: 0644]
libgo/go/reflect/visiblefields_test.go [new file with mode: 0644]
libgo/go/regexp/exec2_test.go
libgo/go/regexp/find_test.go
libgo/go/regexp/onepass_test.go
libgo/go/regexp/syntax/compile.go
libgo/go/regexp/syntax/prog_test.go
libgo/go/regexp/testdata/basic.dat
libgo/go/regexp/testdata/nullsubexpr.dat
libgo/go/regexp/testdata/re2-exhaustive.txt.bz2
libgo/go/regexp/testdata/re2-search.txt
libgo/go/runtime/abi_test.go [new file with mode: 0644]
libgo/go/runtime/alg.go
libgo/go/runtime/auxv_none.go
libgo/go/runtime/cgo/handle.go [new file with mode: 0644]
libgo/go/runtime/cgo/handle_test.go [new file with mode: 0644]
libgo/go/runtime/cgocall.go
libgo/go/runtime/chan_test.go
libgo/go/runtime/checkptr.go
libgo/go/runtime/checkptr_test.go
libgo/go/runtime/cpuprof.go
libgo/go/runtime/cputicks.go
libgo/go/runtime/crash_cgo_test.go
libgo/go/runtime/crash_nonunix_test.go
libgo/go/runtime/crash_test.go
libgo/go/runtime/crash_unix_test.go
libgo/go/runtime/debug.go
libgo/go/runtime/debug/panic_test.go
libgo/go/runtime/debug_test.go [deleted file]
libgo/go/runtime/debuglog_off.go
libgo/go/runtime/debuglog_on.go
libgo/go/runtime/defer_test.go
libgo/go/runtime/defs_windows_arm64.go [new file with mode: 0644]
libgo/go/runtime/env_posix.go
libgo/go/runtime/example_test.go
libgo/go/runtime/export_debug_test.go [deleted file]
libgo/go/runtime/export_mmap_test.go
libgo/go/runtime/export_pipe2_test.go
libgo/go/runtime/export_pipe_test.go
libgo/go/runtime/export_test.go
libgo/go/runtime/export_unix_test.go
libgo/go/runtime/extern.go
libgo/go/runtime/gc_test.go
libgo/go/runtime/hash32.go
libgo/go/runtime/hash64.go
libgo/go/runtime/hash_test.go
libgo/go/runtime/heapdump.go
libgo/go/runtime/histogram.go
libgo/go/runtime/internal/math/math.go
libgo/go/runtime/internal/sys/arch.go [new file with mode: 0644]
libgo/go/runtime/internal/sys/stubs.go [deleted file]
libgo/go/runtime/lfstack_32bit.go
libgo/go/runtime/lfstack_64bit.go
libgo/go/runtime/libfuzzer.go
libgo/go/runtime/lock_futex.go
libgo/go/runtime/lock_js.go
libgo/go/runtime/lock_sema.go
libgo/go/runtime/lockrank.go
libgo/go/runtime/lockrank_off.go
libgo/go/runtime/lockrank_on.go
libgo/go/runtime/lockrank_test.go [new file with mode: 0644]
libgo/go/runtime/malloc.go
libgo/go/runtime/malloc_test.go
libgo/go/runtime/map.go
libgo/go/runtime/map_faststr.go
libgo/go/runtime/mbitmap.go
libgo/go/runtime/mcache.go
libgo/go/runtime/mcentral.go
libgo/go/runtime/metrics.go
libgo/go/runtime/metrics/description.go
libgo/go/runtime/metrics/doc.go
libgo/go/runtime/metrics_test.go
libgo/go/runtime/mgc.go
libgo/go/runtime/mgcmark.go
libgo/go/runtime/mgcpacer.go [new file with mode: 0644]
libgo/go/runtime/mgcscavenge.go
libgo/go/runtime/mgcscavenge_test.go
libgo/go/runtime/mgcsweep.go
libgo/go/runtime/mgcwork.go
libgo/go/runtime/mheap.go
libgo/go/runtime/mkfastlog2table.go
libgo/go/runtime/mkpreempt.go
libgo/go/runtime/mksizeclasses.go
libgo/go/runtime/mpagealloc.go
libgo/go/runtime/mpagealloc_32bit.go
libgo/go/runtime/mpagealloc_64bit.go
libgo/go/runtime/mprof.go
libgo/go/runtime/msan0.go
libgo/go/runtime/mstats.go
libgo/go/runtime/nbpipe_pipe.go
libgo/go/runtime/nbpipe_pipe2.go
libgo/go/runtime/nbpipe_test.go
libgo/go/runtime/netpoll.go
libgo/go/runtime/netpoll_epoll.go
libgo/go/runtime/netpoll_fake.go
libgo/go/runtime/netpoll_kqueue.go
libgo/go/runtime/netpoll_stub.go
libgo/go/runtime/norace_test.go
libgo/go/runtime/os_aix.go
libgo/go/runtime/os_darwin.go
libgo/go/runtime/os_gccgo.go
libgo/go/runtime/os_js.go
libgo/go/runtime/os_linux_arm64.go
libgo/go/runtime/os_linux_mips64x.go
libgo/go/runtime/os_linux_mipsx.go
libgo/go/runtime/os_linux_noauxv.go
libgo/go/runtime/os_linux_ppc64x.go
libgo/go/runtime/os_only_solaris.go
libgo/go/runtime/os_windows_arm64.go [new file with mode: 0644]
libgo/go/runtime/panic32.go
libgo/go/runtime/pprof/mprof_test.go
libgo/go/runtime/pprof/pprof.go
libgo/go/runtime/pprof/pprof_norusage.go
libgo/go/runtime/pprof/pprof_rusage.go
libgo/go/runtime/pprof/pprof_test.go
libgo/go/runtime/preempt_nonwindows.go
libgo/go/runtime/print.go
libgo/go/runtime/proc.go
libgo/go/runtime/proc_test.go
libgo/go/runtime/race0.go
libgo/go/runtime/relax_stub.go
libgo/go/runtime/runtime-lldb_test.go
libgo/go/runtime/runtime1.go
libgo/go/runtime/runtime2.go
libgo/go/runtime/runtime_mmap_test.go
libgo/go/runtime/runtime_test.go
libgo/go/runtime/runtime_unix_test.go
libgo/go/runtime/select.go
libgo/go/runtime/semasleep_test.go
libgo/go/runtime/signal_unix.go
libgo/go/runtime/signal_windows_test.go
libgo/go/runtime/sigqueue.go
libgo/go/runtime/sigqueue_note.go
libgo/go/runtime/sizeclasses.go
libgo/go/runtime/sizeof_test.go
libgo/go/runtime/slice.go
libgo/go/runtime/stubs.go
libgo/go/runtime/stubs2.go
libgo/go/runtime/stubs3.go
libgo/go/runtime/stubs_linux.go
libgo/go/runtime/stubs_nonlinux.go
libgo/go/runtime/symtab.go
libgo/go/runtime/sys_wasm.go
libgo/go/runtime/testdata/testprog/checkptr.go
libgo/go/runtime/testdata/testprog/crashdump.go [new file with mode: 0644]
libgo/go/runtime/testdata/testprogcgo/aprof.go
libgo/go/runtime/testdata/testprogcgo/aprof_c.c [new file with mode: 0644]
libgo/go/runtime/testdata/testprogcgo/bigstack1_windows.c [new file with mode: 0644]
libgo/go/runtime/testdata/testprogcgo/bigstack_windows.go
libgo/go/runtime/testdata/testprogcgo/lockosthread.c
libgo/go/runtime/testdata/testprogcgo/pprof.go
libgo/go/runtime/testdata/testprogcgo/raceprof.go
libgo/go/runtime/testdata/testprogcgo/threadpprof.go
libgo/go/runtime/testdata/testprogcgo/traceback.go
libgo/go/runtime/testdata/testprogcgo/traceback_c.c [new file with mode: 0644]
libgo/go/runtime/testdata/testprogcgo/traceback_gccgo.go
libgo/go/runtime/testdata/testprogcgo/tracebackctxt.go
libgo/go/runtime/testdata/testprogcgo/tracebackctxt_c.c
libgo/go/runtime/testdata/testprogcgo/windows/win.go
libgo/go/runtime/testdata/testwinlibsignal/dummy.go
libgo/go/runtime/testdata/testwinlibsignal/main.c [new file with mode: 0644]
libgo/go/runtime/time.go
libgo/go/runtime/time_fake.go
libgo/go/runtime/time_nofake.go
libgo/go/runtime/timeasm.go
libgo/go/runtime/timestub.go
libgo/go/runtime/timestub2.go
libgo/go/runtime/tls_stub.go [new file with mode: 0644]
libgo/go/runtime/tls_windows_amd64.go [new file with mode: 0644]
libgo/go/runtime/trace.go
libgo/go/runtime/traceback_test.go [new file with mode: 0644]
libgo/go/runtime/type.go
libgo/go/runtime/write_err.go
libgo/go/runtime/write_err_android.go
libgo/go/sort/example_search_test.go
libgo/go/sort/genzfunc.go
libgo/go/sort/slice_go113.go
libgo/go/sort/slice_go14.go
libgo/go/sort/slice_go18.go
libgo/go/strconv/atof.go
libgo/go/strconv/atof_test.go
libgo/go/strconv/atoi.go
libgo/go/strconv/atoi_test.go
libgo/go/strconv/bytealg.go [new file with mode: 0644]
libgo/go/strconv/bytealg_bootstrap.go [new file with mode: 0644]
libgo/go/strconv/eisel_lemire.go
libgo/go/strconv/extfloat.go [deleted file]
libgo/go/strconv/ftoa.go
libgo/go/strconv/ftoa_test.go
libgo/go/strconv/ftoaryu.go [new file with mode: 0644]
libgo/go/strconv/ftoaryu_test.go [new file with mode: 0644]
libgo/go/strconv/internal_test.go
libgo/go/strconv/makeisprint.go
libgo/go/strconv/quote.go
libgo/go/strconv/quote_test.go
libgo/go/strings/builder.go
libgo/go/strings/builder_test.go
libgo/go/sync/atomic/value.go
libgo/go/sync/atomic/value_test.go
libgo/go/sync/map.go
libgo/go/sync/pool_test.go
libgo/go/sync/runtime2.go
libgo/go/sync/runtime2_lockrank.go
libgo/go/syscall/bpf_bsd.go
libgo/go/syscall/creds_test.go
libgo/go/syscall/dirent.go
libgo/go/syscall/dirent_test.go
libgo/go/syscall/endian_big.go
libgo/go/syscall/endian_little.go
libgo/go/syscall/env_unix.go
libgo/go/syscall/exec_bsd.go
libgo/go/syscall/exec_linux.go
libgo/go/syscall/exec_linux_test.go
libgo/go/syscall/exec_unix.go
libgo/go/syscall/exec_unix_test.go
libgo/go/syscall/exec_windows.go
libgo/go/syscall/exec_windows_test.go
libgo/go/syscall/export_unix_test.go
libgo/go/syscall/export_windows_test.go [new file with mode: 0644]
libgo/go/syscall/forkpipe.go
libgo/go/syscall/forkpipe2.go
libgo/go/syscall/fs_js.go
libgo/go/syscall/getdirentries_test.go
libgo/go/syscall/libcall_glibc.go
libgo/go/syscall/mkasm.go
libgo/go/syscall/mmap_unix_test.go
libgo/go/syscall/msan0.go
libgo/go/syscall/net_js.go
libgo/go/syscall/route_bsd.go
libgo/go/syscall/route_freebsd_32bit.go
libgo/go/syscall/route_freebsd_64bit.go
libgo/go/syscall/setuidgid_32_linux.go
libgo/go/syscall/setuidgid_linux.go
libgo/go/syscall/sockcmsg_unix.go
libgo/go/syscall/sockcmsg_unix_other.go
libgo/go/syscall/str.go [deleted file]
libgo/go/syscall/syscall_darwin.go
libgo/go/syscall/syscall_freebsd_test.go
libgo/go/syscall/syscall_js.go
libgo/go/syscall/syscall_linux_386.go
libgo/go/syscall/syscall_linux_mipsx.go
libgo/go/syscall/syscall_linux_test.go
libgo/go/syscall/syscall_ptrace_test.go
libgo/go/syscall/syscall_test.go
libgo/go/syscall/syscall_unix.go
libgo/go/syscall/syscall_unix_test.go
libgo/go/syscall/tables_js.go
libgo/go/syscall/time_fake.go
libgo/go/syscall/time_nofake.go
libgo/go/syscall/timestruct.go
libgo/go/syscall/types_windows_arm64.go [new file with mode: 0644]
libgo/go/testing/benchmark.go
libgo/go/testing/benchmark_test.go
libgo/go/testing/fstest/mapfs.go
libgo/go/testing/fstest/testfs.go
libgo/go/testing/fstest/testfs_test.go
libgo/go/testing/run_example.go
libgo/go/testing/run_example_js.go
libgo/go/testing/sub_test.go
libgo/go/testing/testing.go
libgo/go/testing/testing_test.go
libgo/go/text/scanner/scanner.go
libgo/go/text/template/exec.go
libgo/go/text/template/exec_test.go
libgo/go/text/template/funcs.go
libgo/go/text/template/link_test.go
libgo/go/text/template/parse/parse.go
libgo/go/text/template/parse/parse_test.go
libgo/go/text/template/template.go
libgo/go/time/embed.go
libgo/go/time/export_test.go
libgo/go/time/format.go
libgo/go/time/format_test.go
libgo/go/time/genzabbrs.go
libgo/go/time/internal_test.go
libgo/go/time/sleep_test.go
libgo/go/time/sys_plan9.go
libgo/go/time/sys_unix.go
libgo/go/time/testdata/2020b_Europe_Berlin [new file with mode: 0644]
libgo/go/time/testdata/2021a_America_Nuuk [new file with mode: 0644]
libgo/go/time/testdata/2021a_Asia_Gaza [new file with mode: 0644]
libgo/go/time/testdata/2021a_Europe_Dublin [new file with mode: 0644]
libgo/go/time/tick_test.go
libgo/go/time/time.go
libgo/go/time/time_test.go
libgo/go/time/tzdata/generate_zipdata.go
libgo/go/time/zoneinfo.go
libgo/go/time/zoneinfo_ios.go
libgo/go/time/zoneinfo_js.go
libgo/go/time/zoneinfo_test.go
libgo/go/time/zoneinfo_unix.go
libgo/go/time/zoneinfo_unix_test.go
libgo/go/unicode/letter.go
libgo/go/unicode/letter_test.go
libgo/go/vendor/modules.txt
libgo/goarch.sh
libgo/gotool-packages.txt
libgo/libgo-packages.txt
libgo/match.sh
libgo/misc/cgo/errors/argposition_test.go [new file with mode: 0644]
libgo/misc/cgo/errors/badsym_test.go
libgo/misc/cgo/errors/errors_test.go
libgo/misc/cgo/errors/ptr_test.go
libgo/misc/cgo/errors/testdata/err2.go
libgo/misc/cgo/errors/testdata/issue42580.go [new file with mode: 0644]
libgo/misc/cgo/life/life_test.go
libgo/misc/cgo/stdio/stdio_test.go
libgo/misc/cgo/test/callback.go
libgo/misc/cgo/test/cgo_test.go
libgo/misc/cgo/test/issue1435.go
libgo/misc/cgo/test/issue6997_linux.go
libgo/misc/cgo/test/issue8148.c [moved from libgo/go/syscall/export_test.go with 62% similarity]
libgo/misc/cgo/test/issue8148.go
libgo/misc/cgo/test/pkg_test.go
libgo/misc/cgo/test/setgid_linux.go
libgo/misc/cgo/test/test.go
libgo/misc/cgo/test/testdata/issue9400/asm_386.s
libgo/misc/cgo/test/testdata/issue9400/asm_amd64x.s
libgo/misc/cgo/test/testdata/issue9400/asm_arm.s
libgo/misc/cgo/test/testdata/issue9400/asm_arm64.s
libgo/misc/cgo/test/testdata/issue9400/asm_mips64x.s
libgo/misc/cgo/test/testdata/issue9400/asm_mipsx.s
libgo/misc/cgo/test/testdata/issue9400/asm_ppc64x.s
libgo/misc/cgo/test/testdata/issue9400/asm_riscv64.s
libgo/misc/cgo/test/testdata/issue9400/asm_s390x.s
libgo/misc/cgo/test/testx.c [new file with mode: 0644]
libgo/misc/cgo/test/testx.go
libgo/misc/cgo/testcarchive/carchive_test.go
libgo/misc/cgo/testcarchive/testdata/libgo6/sigprof.go
libgo/misc/cgo/testcshared/cshared_test.go
libgo/misc/cgo/testgodefs/testgodefs_test.go
libgo/misc/cgo/testplugin/plugin_test.go
libgo/misc/cgo/testplugin/testdata/method2/main.go
libgo/misc/cgo/testsanitizers/cc_test.go
libgo/misc/cgo/testsanitizers/cshared_test.go
libgo/misc/cgo/testsanitizers/msan_test.go
libgo/misc/cgo/testsanitizers/testdata/tsan9.go
libgo/misc/cgo/testshared/shared_test.go
libgo/misc/cgo/testshared/testdata/depBase/asm.s
libgo/misc/cgo/testshared/testdata/depBase/stubs.go
libgo/misc/cgo/testso/so_test.go
libgo/misc/cgo/testso/testdata/cgoso.go
libgo/misc/cgo/testsovar/so_test.go
libgo/misc/cgo/testsovar/testdata/cgoso.go
libgo/runtime/go-now.c
libgo/runtime/runtime_c.c
libgo/runtime/stack.c
libgo/testsuite/gotest

index 539d886b08f6afc4bb46dc622c3371cd371c93fb..bcbe1d93018cd3f148cddcd14033ee1c94c6a75f 100644 (file)
@@ -1,4 +1,4 @@
-5edbb624b2595d644eb6842c952a292c41f7d6fa
+33f65dce43bd01c1fa38cd90a78c9aea6ca6dd59
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index ac842716022809916900094eafcd04f95df9630c..4286d5c5433db0f482c6eacd6267c824f5c3302a 100644 (file)
@@ -1,4 +1,4 @@
-7677616a263e8ded606cc8297cb67ddc667a876e
+72ab3ff68b1ec894fe5599ec82b8849f3baa9d94
 
 The first line of this file holds the git revision number of the
 last merge done from the master library sources.
index dec987566732b2143093b44d4b4b85aff1cfd8c1..92fedcf6eb8dc3bf81ab25c6a4e1fc1c3228e69c 100644 (file)
@@ -366,6 +366,7 @@ toolexeclibgoregexp_DATA = \
 toolexeclibgoruntimedir = $(toolexeclibgodir)/runtime
 
 toolexeclibgoruntime_DATA = \
+       runtime/cgo.gox \
        runtime/debug.gox \
        runtime/metrics.gox \
        runtime/pprof.gox \
@@ -428,7 +429,9 @@ noinst_DATA = \
        internal/testenv.gox \
        internal/trace.gox \
        net/internal/socktest.gox \
-       os/signal/internal/pty.gox
+       os/signal/internal/pty.gox \
+       reflect/internal/example1.gox \
+       reflect/internal/example2.gox
 
 if LIBGO_IS_RTEMS
 rtems_task_variable_add_file = runtime/rtems-task-variable-add.c
@@ -480,14 +483,10 @@ version.go: s-version; @true
 s-version: Makefile
        rm -f version.go.tmp
        echo "package sys" > version.go.tmp
-       echo 'func init() { DefaultGoroot = "$(prefix)" }' >> version.go.tmp
-       echo 'const TheVersion = "'`cat $(srcdir)/VERSION | sed 1q`' '`$(GOC) --version | sed 1q`'"' >> version.go.tmp
-       echo 'const Goexperiment = ``' >> version.go.tmp
        echo 'const GOARCH = "'$(GOARCH)'"' >> version.go.tmp
        echo 'const GOOS = "'$(GOOS)'"' >> version.go.tmp
        echo 'const GccgoToolDir = "$(libexecsubdir)"' >> version.go.tmp
-       echo >> version.go.tmp
-       echo "type ArchFamilyType int" >> version.go.tmp
+       echo 'const StackGuardMultiplierDefault = 1' >> version.go.tmp
        echo >> version.go.tmp
        echo "const (" >> version.go.tmp
        echo "  UNKNOWN ArchFamilyType = iota" >> version.go.tmp
@@ -507,13 +506,13 @@ s-version: Makefile
        done
        echo >> version.go.tmp
        echo "const (" >> version.go.tmp
-       echo "  ArchFamily = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) family`" >> version.go.tmp
-       echo "  BigEndian = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) bigendian`" >> version.go.tmp
-       echo "  CacheLineSize = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) cachelinesize`" >> version.go.tmp
-       echo "  DefaultPhysPageSize = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) defaultphyspagesize`" >> version.go.tmp
-       echo "  Int64Align = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) int64align`" >> version.go.tmp
-       echo "  MinFrameSize = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) minframesize`" >> version.go.tmp
-       echo "  PCQuantum = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) pcquantum`" >> version.go.tmp
+       echo "  _ArchFamily = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) family`" >> version.go.tmp
+       echo "  _BigEndian = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) bigendian`" >> version.go.tmp
+       echo "  _DefaultPhysPageSize = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) defaultphyspagesize`" >> version.go.tmp
+       echo "  _Int64Align = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) int64align`" >> version.go.tmp
+       echo "  _MinFrameSize = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) minframesize`" >> version.go.tmp
+       echo "  _PCQuantum = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) pcquantum`" >> version.go.tmp
+       echo "  _StackAlign = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) stackalign`" >> version.go.tmp
        echo ")" >> version.go.tmp
        echo >> version.go.tmp
        for a in $(ALLGOOS); do \
@@ -526,7 +525,6 @@ s-version: Makefile
          fi; \
        done
        echo >> version.go.tmp
-       echo "type Uintreg uintptr" >> version.go.tmp
        $(SHELL) $(srcdir)/mvifdiff.sh version.go.tmp version.go
        $(STAMP) $@
 
@@ -547,24 +545,31 @@ s-gcpu: Makefile
        $(SHELL) $(srcdir)/mvifdiff.sh gcpugen.go.tmp gcpugen.go
        $(STAMP) $@
 
+buildcfg.go: s-buildcfg; @true
+s-buildcfg: Makefile
+       rm -f buildcfg.go.tmp
+       echo "package buildcfg" > buildcfg.go.tmp
+       echo "import \"runtime\"" >> buildcfg.go.tmp
+       echo 'func defaultGOROOTValue() string { return `$(prefix)` }' >> buildcfg.go.tmp
+       echo 'const defaultGO386 = `sse2`' >> buildcfg.go.tmp
+       echo 'const defaultGOARM = `5`' >> buildcfg.go.tmp
+       echo 'const defaultGOMIPS = `hardfloat`' >> buildcfg.go.tmp
+       echo 'const defaultGOMIPS64 = `hardfloat`' >> buildcfg.go.tmp
+       echo 'const defaultGOPPC64 = `power8`' >> buildcfg.go.tmp
+       echo 'const defaultGOEXPERIMENT = `fieldtrack`' >> buildcfg.go.tmp
+       echo 'const defaultGO_EXTLINK_ENABLED = ``' >> buildcfg.go.tmp
+       echo 'const defaultGO_LDSO = ``' >> buildcfg.go.tmp
+       echo 'const version = `'`cat $(srcdir)/VERSION | sed 1q`' '`$(GOC) --version | sed 1q`'`' >> buildcfg.go.tmp
+       echo 'const defaultGOOS = runtime.GOOS' >> buildcfg.go.tmp
+       echo 'const defaultGOARCH = runtime.GOARCH' >> buildcfg.go.tmp
+       $(SHELL) $(srcdir)/mvifdiff.sh buildcfg.go.tmp buildcfg.go
+       $(STAMP) $@
+
 objabi.go: s-objabi; @true
 s-objabi: Makefile
        rm -f objabi.go.tmp
        echo "package objabi" > objabi.go.tmp
-       echo "import \"runtime\"" >> objabi.go.tmp
-       echo 'func defaultGOROOTValue() string { return `$(prefix)` }' >> objabi.go.tmp
-       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 defaultGOPPC64 = `power8`' >> 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
-       echo 'const defaultGO_LDSO = ``' >> objabi.go.tmp
-       echo 'const version = `'`cat $(srcdir)/VERSION | sed 1q`' '`$(GOC) --version | sed 1q`'`' >> objabi.go.tmp
        echo 'const stackGuardMultiplierDefault = 1' >> objabi.go.tmp
-       echo 'const goexperiment = ``' >> objabi.go.tmp
        $(SHELL) $(srcdir)/mvifdiff.sh objabi.go.tmp objabi.go
        $(STAMP) $@
 
@@ -671,7 +676,7 @@ s-zstdpkglist: Makefile libgo-packages.txt
        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|golang\.org/[a-z0-9_./]*\.lo||g' | sed 's|\([a-z0-9_./]*\)\.lo|"\1": true,|g' >> zstdpkglist.go.tmp
+       echo $(libgo_go_objs) 'unsafe.lo' | sed 's|[a-z0-9_./]*_c\.lo||g' | sed 's|golang\.org/[a-z0-9_./]*\.lo||g' | sed 's|\([a-z0-9_./]*\)\.lo|"\1": true,|g' >> zstdpkglist.go.tmp
        echo '}' >> zstdpkglist.go.tmp
        $(SHELL) $(srcdir)/mvifdiff.sh zstdpkglist.go.tmp zstdpkglist.go
        $(STAMP) $@
@@ -1054,6 +1059,9 @@ internal/cpu.lo.dep: $(extra_go_files_internal_cpu)
 extra_go_files_golang_org_x_sys_cpu = gcpugen.go
 golang.org/x/sys/cpu.lo.dep: $(extra_go_files_golang_org_x_sys_cpu)
 
+extra_go_files_internal_buildcfg = buildcfg.go
+cmd/internal/buildcfg.lo.dep: $(extra_go_files_internal_buildcfg)
+
 extra_go_files_internal_goroot = zstdpkglist.go
 internal/goroot.lo.dep: $(extra_go_files_internal_goroot)
 
index da72149badf41f8a60fa738ac0ef1904a173f094..3b2bdf99027c2e5e21d04cb501c0847fae1c30d9 100644 (file)
@@ -839,6 +839,7 @@ toolexeclibgoregexp_DATA = \
 
 toolexeclibgoruntimedir = $(toolexeclibgodir)/runtime
 toolexeclibgoruntime_DATA = \
+       runtime/cgo.gox \
        runtime/debug.gox \
        runtime/metrics.gox \
        runtime/pprof.gox \
@@ -892,6 +893,7 @@ noinst_DATA = golang.org/x/net/nettest.gox internal/cfg.gox \
        internal/obscuretestdata.gox internal/profile.gox \
        internal/testenv.gox internal/trace.gox \
        net/internal/socktest.gox os/signal/internal/pty.gox \
+       reflect/internal/example1.gox reflect/internal/example2.gox \
        zdefaultcc.go
 @LIBGO_IS_RTEMS_FALSE@rtems_task_variable_add_file = 
 @LIBGO_IS_RTEMS_TRUE@rtems_task_variable_add_file = runtime/rtems-task-variable-add.c
@@ -1135,6 +1137,7 @@ runtime_pprof_check_GOCFLAGS = -static-libgo -fno-inline
 extra_go_files_runtime_internal_sys = version.go
 extra_go_files_internal_cpu = cpugen.go
 extra_go_files_golang_org_x_sys_cpu = gcpugen.go
+extra_go_files_internal_buildcfg = buildcfg.go
 extra_go_files_internal_goroot = zstdpkglist.go
 extra_go_files_go_types = gccgosizes.go
 extra_go_files_cmd_internal_objabi = objabi.go
@@ -2687,14 +2690,10 @@ version.go: s-version; @true
 s-version: Makefile
        rm -f version.go.tmp
        echo "package sys" > version.go.tmp
-       echo 'func init() { DefaultGoroot = "$(prefix)" }' >> version.go.tmp
-       echo 'const TheVersion = "'`cat $(srcdir)/VERSION | sed 1q`' '`$(GOC) --version | sed 1q`'"' >> version.go.tmp
-       echo 'const Goexperiment = ``' >> version.go.tmp
        echo 'const GOARCH = "'$(GOARCH)'"' >> version.go.tmp
        echo 'const GOOS = "'$(GOOS)'"' >> version.go.tmp
        echo 'const GccgoToolDir = "$(libexecsubdir)"' >> version.go.tmp
-       echo >> version.go.tmp
-       echo "type ArchFamilyType int" >> version.go.tmp
+       echo 'const StackGuardMultiplierDefault = 1' >> version.go.tmp
        echo >> version.go.tmp
        echo "const (" >> version.go.tmp
        echo "  UNKNOWN ArchFamilyType = iota" >> version.go.tmp
@@ -2714,13 +2713,13 @@ s-version: Makefile
        done
        echo >> version.go.tmp
        echo "const (" >> version.go.tmp
-       echo "  ArchFamily = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) family`" >> version.go.tmp
-       echo "  BigEndian = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) bigendian`" >> version.go.tmp
-       echo "  CacheLineSize = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) cachelinesize`" >> version.go.tmp
-       echo "  DefaultPhysPageSize = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) defaultphyspagesize`" >> version.go.tmp
-       echo "  Int64Align = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) int64align`" >> version.go.tmp
-       echo "  MinFrameSize = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) minframesize`" >> version.go.tmp
-       echo "  PCQuantum = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) pcquantum`" >> version.go.tmp
+       echo "  _ArchFamily = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) family`" >> version.go.tmp
+       echo "  _BigEndian = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) bigendian`" >> version.go.tmp
+       echo "  _DefaultPhysPageSize = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) defaultphyspagesize`" >> version.go.tmp
+       echo "  _Int64Align = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) int64align`" >> version.go.tmp
+       echo "  _MinFrameSize = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) minframesize`" >> version.go.tmp
+       echo "  _PCQuantum = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) pcquantum`" >> version.go.tmp
+       echo "  _StackAlign = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) stackalign`" >> version.go.tmp
        echo ")" >> version.go.tmp
        echo >> version.go.tmp
        for a in $(ALLGOOS); do \
@@ -2733,7 +2732,6 @@ s-version: Makefile
          fi; \
        done
        echo >> version.go.tmp
-       echo "type Uintreg uintptr" >> version.go.tmp
        $(SHELL) $(srcdir)/mvifdiff.sh version.go.tmp version.go
        $(STAMP) $@
 
@@ -2754,24 +2752,31 @@ s-gcpu: Makefile
        $(SHELL) $(srcdir)/mvifdiff.sh gcpugen.go.tmp gcpugen.go
        $(STAMP) $@
 
+buildcfg.go: s-buildcfg; @true
+s-buildcfg: Makefile
+       rm -f buildcfg.go.tmp
+       echo "package buildcfg" > buildcfg.go.tmp
+       echo "import \"runtime\"" >> buildcfg.go.tmp
+       echo 'func defaultGOROOTValue() string { return `$(prefix)` }' >> buildcfg.go.tmp
+       echo 'const defaultGO386 = `sse2`' >> buildcfg.go.tmp
+       echo 'const defaultGOARM = `5`' >> buildcfg.go.tmp
+       echo 'const defaultGOMIPS = `hardfloat`' >> buildcfg.go.tmp
+       echo 'const defaultGOMIPS64 = `hardfloat`' >> buildcfg.go.tmp
+       echo 'const defaultGOPPC64 = `power8`' >> buildcfg.go.tmp
+       echo 'const defaultGOEXPERIMENT = `fieldtrack`' >> buildcfg.go.tmp
+       echo 'const defaultGO_EXTLINK_ENABLED = ``' >> buildcfg.go.tmp
+       echo 'const defaultGO_LDSO = ``' >> buildcfg.go.tmp
+       echo 'const version = `'`cat $(srcdir)/VERSION | sed 1q`' '`$(GOC) --version | sed 1q`'`' >> buildcfg.go.tmp
+       echo 'const defaultGOOS = runtime.GOOS' >> buildcfg.go.tmp
+       echo 'const defaultGOARCH = runtime.GOARCH' >> buildcfg.go.tmp
+       $(SHELL) $(srcdir)/mvifdiff.sh buildcfg.go.tmp buildcfg.go
+       $(STAMP) $@
+
 objabi.go: s-objabi; @true
 s-objabi: Makefile
        rm -f objabi.go.tmp
        echo "package objabi" > objabi.go.tmp
-       echo "import \"runtime\"" >> objabi.go.tmp
-       echo 'func defaultGOROOTValue() string { return `$(prefix)` }' >> objabi.go.tmp
-       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 defaultGOPPC64 = `power8`' >> 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
-       echo 'const defaultGO_LDSO = ``' >> objabi.go.tmp
-       echo 'const version = `'`cat $(srcdir)/VERSION | sed 1q`' '`$(GOC) --version | sed 1q`'`' >> objabi.go.tmp
        echo 'const stackGuardMultiplierDefault = 1' >> objabi.go.tmp
-       echo 'const goexperiment = ``' >> objabi.go.tmp
        $(SHELL) $(srcdir)/mvifdiff.sh objabi.go.tmp objabi.go
        $(STAMP) $@
 
@@ -2872,7 +2877,7 @@ s-zstdpkglist: Makefile libgo-packages.txt
        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|golang\.org/[a-z0-9_./]*\.lo||g' | sed 's|\([a-z0-9_./]*\)\.lo|"\1": true,|g' >> zstdpkglist.go.tmp
+       echo $(libgo_go_objs) 'unsafe.lo' | sed 's|[a-z0-9_./]*_c\.lo||g' | sed 's|golang\.org/[a-z0-9_./]*\.lo||g' | sed 's|\([a-z0-9_./]*\)\.lo|"\1": true,|g' >> zstdpkglist.go.tmp
        echo '}' >> zstdpkglist.go.tmp
        $(SHELL) $(srcdir)/mvifdiff.sh zstdpkglist.go.tmp zstdpkglist.go
        $(STAMP) $@
@@ -3005,6 +3010,7 @@ syscall.lo.dep: $(extra_go_files_syscall)
 runtime/internal/sys.lo.dep: $(extra_go_files_runtime_internal_sys)
 internal/cpu.lo.dep: $(extra_go_files_internal_cpu)
 golang.org/x/sys/cpu.lo.dep: $(extra_go_files_golang_org_x_sys_cpu)
+cmd/internal/buildcfg.lo.dep: $(extra_go_files_internal_buildcfg)
 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)
index e336ec201bfc2a52e2a1b0e0d07364842c8da603..904eb73bd5cf6e17793ac92874e56c656c282d18 100644 (file)
@@ -1 +1 @@
-go1.16.5
+go1.17rc2
index 1e549cae4b0fa7e3d57f0a808d2458a77a19cfe0..dd8990f10e2c7b5a0ded85b3c75d9b0d8fa85009 100644 (file)
@@ -43,7 +43,10 @@ crypto/des
 crypto/dsa
 crypto/ecdsa
 crypto/ed25519
+crypto/ed25519/internal/edwards25519
+crypto/ed25519/internal/edwards25519/field
 crypto/elliptic
+crypto/elliptic/internal/fiat
 crypto/hmac
 crypto/internal/subtle
 crypto/md5
@@ -110,6 +113,7 @@ index/suffixarray
 internal/cpu
 internal/execabs
 internal/fmtsort
+internal/itoa
 internal/poll
 internal/profile
 internal/reflectlite
@@ -139,6 +143,7 @@ net/http/httptest
 net/http/httptrace
 net/http/httputil
 net/http/internal
+net/http/internal/ascii
 net/http/pprof
 net/internal/socktest
 net/mail
@@ -157,6 +162,7 @@ reflect
 regexp
 regexp/syntax
 runtime
+runtime/cgo
 runtime/debug
 runtime/internal/atomic
 runtime/internal/math
index 915eeaf050b81366fe60488da4d67162f67eacca..57ceeb2baa7ba7ccc5b3864fb956542f480c704c 100755 (executable)
@@ -2608,7 +2608,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 ac_config_headers="$ac_config_headers config.h"
 
 
-libtool_VERSION=19:0:0
+libtool_VERSION=20:0:0
 
 
 # Default to --enable-multilib
index ebab9d9de3e2d50695929f8ba7a8672919715909..1f4f32dae2b4c9e633f21ac15a6afbe435b1c614 100644 (file)
@@ -10,7 +10,7 @@ AC_INIT(package-unused, version-unused,, libgo)
 AC_CONFIG_SRCDIR(Makefile.am)
 AC_CONFIG_HEADER(config.h)
 
-libtool_VERSION=19:0:0
+libtool_VERSION=20:0:0
 AC_SUBST(libtool_VERSION)
 
 AM_ENABLE_MULTILIB(, ..)
index 2a7f7f36ab0a29fe1772fa7781b7f2fc5028d690..71cece5793a4c4d3fb3392451beaced08db150dc 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || hurd || linux || dragonfly || openbsd || solaris
 // +build aix hurd linux dragonfly openbsd solaris
 
 package tar
index 6f17dbe30725c120218885cc662587b8c7dcb4d2..5a9a35cbb4e22d9df42f307843730032d7e0b392 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || freebsd || netbsd
 // +build darwin freebsd netbsd
 
 package tar
index 93a3fcd60e972c7a9c1bba686fb8dbab9a206fc8..f27df67eedc1af73d29aee80c54e5d320925581f 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || hurd || linux || darwin || dragonfly || freebsd || openbsd || netbsd || solaris
 // +build aix hurd linux darwin dragonfly freebsd openbsd netbsd solaris
 
 package tar
index 91b38401b6c1030f05b81caabb5ac19faa271d25..e9fafc7cc70df5cd5f6308f42c87c6d577f6dabf 100644 (file)
@@ -262,16 +262,11 @@ func TestFileInfoHeaderDir(t *testing.T) {
 func TestFileInfoHeaderSymlink(t *testing.T) {
        testenv.MustHaveSymlink(t)
 
-       tmpdir, err := os.MkdirTemp("", "TestFileInfoHeaderSymlink")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(tmpdir)
+       tmpdir := t.TempDir()
 
        link := filepath.Join(tmpdir, "link")
        target := tmpdir
-       err = os.Symlink(target, link)
-       if err != nil {
+       if err := os.Symlink(target, link); err != nil {
                t.Fatal(err)
        }
        fi, err := os.Lstat(link)
index ddef2b7b5a5176e1785c9e400407b85d4dfd1c0f..2d53f4c7231653d651b4f3b5bb1a15325b4a33ac 100644 (file)
@@ -52,12 +52,9 @@ type File struct {
        FileHeader
        zip          *Reader
        zipr         io.ReaderAt
-       zipsize      int64
        headerOffset int64
-}
-
-func (f *File) hasDataDescriptor() bool {
-       return f.Flags&0x8 != 0
+       zip64        bool  // zip64 extended information extra field presence
+       descErr      error // error reading the data descriptor during init
 }
 
 // OpenReader will open the Zip file specified by name and return a ReadCloser.
@@ -120,7 +117,7 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
        // a bad one, and then only report an ErrFormat or UnexpectedEOF if
        // the file count modulo 65536 is incorrect.
        for {
-               f := &File{zip: z, zipr: r, zipsize: size}
+               f := &File{zip: z, zipr: r}
                err = readDirectoryHeader(f, buf)
                if err == ErrFormat || err == io.ErrUnexpectedEOF {
                        break
@@ -128,6 +125,7 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
                if err != nil {
                        return err
                }
+               f.readDataDescriptor()
                z.File = append(z.File, f)
        }
        if uint16(len(z.File)) != uint16(end.directoryRecords) { // only compare 16 bits here
@@ -188,26 +186,68 @@ func (f *File) Open() (io.ReadCloser, error) {
                return nil, ErrAlgorithm
        }
        var rc io.ReadCloser = dcomp(r)
-       var desr io.Reader
-       if f.hasDataDescriptor() {
-               desr = io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset+size, dataDescriptorLen)
-       }
        rc = &checksumReader{
                rc:   rc,
                hash: crc32.NewIEEE(),
                f:    f,
-               desr: desr,
        }
        return rc, nil
 }
 
+// OpenRaw returns a Reader that provides access to the File's contents without
+// decompression.
+func (f *File) OpenRaw() (io.Reader, error) {
+       bodyOffset, err := f.findBodyOffset()
+       if err != nil {
+               return nil, err
+       }
+       r := io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset, int64(f.CompressedSize64))
+       return r, nil
+}
+
+func (f *File) readDataDescriptor() {
+       if !f.hasDataDescriptor() {
+               return
+       }
+
+       bodyOffset, err := f.findBodyOffset()
+       if err != nil {
+               f.descErr = err
+               return
+       }
+
+       // In section 4.3.9.2 of the spec: "However ZIP64 format MAY be used
+       // regardless of the size of a file.  When extracting, if the zip64
+       // extended information extra field is present for the file the
+       // compressed and uncompressed sizes will be 8 byte values."
+       //
+       // Historically, this package has used the compressed and uncompressed
+       // sizes from the central directory to determine if the package is
+       // zip64.
+       //
+       // For this case we allow either the extra field or sizes to determine
+       // the data descriptor length.
+       zip64 := f.zip64 || f.isZip64()
+       n := int64(dataDescriptorLen)
+       if zip64 {
+               n = dataDescriptor64Len
+       }
+       size := int64(f.CompressedSize64)
+       r := io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset+size, n)
+       dd, err := readDataDescriptor(r, zip64)
+       if err != nil {
+               f.descErr = err
+               return
+       }
+       f.CRC32 = dd.crc32
+}
+
 type checksumReader struct {
        rc    io.ReadCloser
        hash  hash.Hash32
        nread uint64 // number of bytes read so far
        f     *File
-       desr  io.Reader // if non-nil, where to read the data descriptor
-       err   error     // sticky error
+       err   error // sticky error
 }
 
 func (r *checksumReader) Stat() (fs.FileInfo, error) {
@@ -228,12 +268,12 @@ func (r *checksumReader) Read(b []byte) (n int, err error) {
                if r.nread != r.f.UncompressedSize64 {
                        return 0, io.ErrUnexpectedEOF
                }
-               if r.desr != nil {
-                       if err1 := readDataDescriptor(r.desr, r.f); err1 != nil {
-                               if err1 == io.EOF {
+               if r.f.hasDataDescriptor() {
+                       if r.f.descErr != nil {
+                               if r.f.descErr == io.EOF {
                                        err = io.ErrUnexpectedEOF
                                } else {
-                                       err = err1
+                                       err = r.f.descErr
                                }
                        } else if r.hash.Sum32() != r.f.CRC32 {
                                err = ErrChecksum
@@ -344,6 +384,8 @@ parseExtras:
 
                switch fieldTag {
                case zip64ExtraID:
+                       f.zip64 = true
+
                        // update directory values from the zip64 extra block.
                        // They should only be consulted if the sizes read earlier
                        // are maxed out.
@@ -443,8 +485,9 @@ parseExtras:
        return nil
 }
 
-func readDataDescriptor(r io.Reader, f *File) error {
-       var buf [dataDescriptorLen]byte
+func readDataDescriptor(r io.Reader, zip64 bool) (*dataDescriptor, error) {
+       // Create enough space for the largest possible size
+       var buf [dataDescriptor64Len]byte
 
        // The spec says: "Although not originally assigned a
        // signature, the value 0x08074b50 has commonly been adopted
@@ -454,10 +497,9 @@ func readDataDescriptor(r io.Reader, f *File) error {
        // descriptors and should account for either case when reading
        // ZIP files to ensure compatibility."
        //
-       // dataDescriptorLen includes the size of the signature but
-       // first read just those 4 bytes to see if it exists.
+       // First read just those 4 bytes to see if the signature exists.
        if _, err := io.ReadFull(r, buf[:4]); err != nil {
-               return err
+               return nil, err
        }
        off := 0
        maybeSig := readBuf(buf[:4])
@@ -466,21 +508,28 @@ func readDataDescriptor(r io.Reader, f *File) error {
                // bytes.
                off += 4
        }
-       if _, err := io.ReadFull(r, buf[off:12]); err != nil {
-               return err
+
+       end := dataDescriptorLen - 4
+       if zip64 {
+               end = dataDescriptor64Len - 4
        }
-       b := readBuf(buf[:12])
-       if b.uint32() != f.CRC32 {
-               return ErrChecksum
+       if _, err := io.ReadFull(r, buf[off:end]); err != nil {
+               return nil, err
        }
+       b := readBuf(buf[:end])
 
-       // The two sizes that follow here can be either 32 bits or 64 bits
-       // but the spec is not very clear on this and different
-       // interpretations has been made causing incompatibilities. We
-       // already have the sizes from the central directory so we can
-       // just ignore these.
+       out := &dataDescriptor{
+               crc32: b.uint32(),
+       }
 
-       return nil
+       if zip64 {
+               out.compressedSize = b.uint64()
+               out.uncompressedSize = b.uint64()
+       } else {
+               out.compressedSize = uint64(b.uint32())
+               out.uncompressedSize = uint64(b.uint32())
+       }
+       return out, nil
 }
 
 func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err error) {
index 471be27bb1004f698c071196f2d63da617377a34..37dafe6c8e7c448c8fa28359e07fc2cdbb73560f 100644 (file)
@@ -499,9 +499,15 @@ func TestReader(t *testing.T) {
 func readTestZip(t *testing.T, zt ZipTest) {
        var z *Reader
        var err error
+       var raw []byte
        if zt.Source != nil {
                rat, size := zt.Source()
                z, err = NewReader(rat, size)
+               raw = make([]byte, size)
+               if _, err := rat.ReadAt(raw, 0); err != nil {
+                       t.Errorf("ReadAt error=%v", err)
+                       return
+               }
        } else {
                path := filepath.Join("testdata", zt.Name)
                if zt.Obscured {
@@ -519,6 +525,12 @@ func readTestZip(t *testing.T, zt ZipTest) {
                        defer rc.Close()
                        z = &rc.Reader
                }
+               var err2 error
+               raw, err2 = os.ReadFile(path)
+               if err2 != nil {
+                       t.Errorf("ReadFile(%s) error=%v", path, err2)
+                       return
+               }
        }
        if err != zt.Error {
                t.Errorf("error=%v, want %v", err, zt.Error)
@@ -545,7 +557,7 @@ func readTestZip(t *testing.T, zt ZipTest) {
 
        // test read of each file
        for i, ft := range zt.File {
-               readTestFile(t, zt, ft, z.File[i])
+               readTestFile(t, zt, ft, z.File[i], raw)
        }
        if t.Failed() {
                return
@@ -557,7 +569,7 @@ func readTestZip(t *testing.T, zt ZipTest) {
        for i := 0; i < 5; i++ {
                for j, ft := range zt.File {
                        go func(j int, ft ZipTestFile) {
-                               readTestFile(t, zt, ft, z.File[j])
+                               readTestFile(t, zt, ft, z.File[j], raw)
                                done <- true
                        }(j, ft)
                        n++
@@ -574,7 +586,7 @@ func equalTimeAndZone(t1, t2 time.Time) bool {
        return t1.Equal(t2) && name1 == name2 && offset1 == offset2
 }
 
-func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) {
+func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File, raw []byte) {
        if f.Name != ft.Name {
                t.Errorf("name=%q, want %q", f.Name, ft.Name)
        }
@@ -594,6 +606,31 @@ func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) {
                t.Errorf("%v: UncompressedSize=%#x does not match UncompressedSize64=%#x", f.Name, size, f.UncompressedSize64)
        }
 
+       // Check that OpenRaw returns the correct byte segment
+       rw, err := f.OpenRaw()
+       if err != nil {
+               t.Errorf("%v: OpenRaw error=%v", f.Name, err)
+               return
+       }
+       start, err := f.DataOffset()
+       if err != nil {
+               t.Errorf("%v: DataOffset error=%v", f.Name, err)
+               return
+       }
+       got, err := io.ReadAll(rw)
+       if err != nil {
+               t.Errorf("%v: OpenRaw ReadAll error=%v", f.Name, err)
+               return
+       }
+       end := uint64(start) + f.CompressedSize64
+       want := raw[start:end]
+       if !bytes.Equal(got, want) {
+               t.Logf("got %q", got)
+               t.Logf("want %q", want)
+               t.Errorf("%v: OpenRaw returned unexpected bytes", f.Name)
+               return
+       }
+
        r, err := f.Open()
        if err != nil {
                t.Errorf("%v", err)
@@ -776,8 +813,8 @@ func returnRecursiveZip() (r io.ReaderAt, size int64) {
 //             "archive/zip"
 //             "bytes"
 //             "io"
-//             "io/ioutil"
 //             "log"
+//             "os"
 //     )
 //
 //     type zeros struct{}
@@ -1167,6 +1204,128 @@ func TestCVE202127919(t *testing.T) {
        }
 }
 
+func TestReadDataDescriptor(t *testing.T) {
+       tests := []struct {
+               desc    string
+               in      []byte
+               zip64   bool
+               want    *dataDescriptor
+               wantErr error
+       }{{
+               desc: "valid 32 bit with signature",
+               in: []byte{
+                       0x50, 0x4b, 0x07, 0x08, // signature
+                       0x00, 0x01, 0x02, 0x03, // crc32
+                       0x04, 0x05, 0x06, 0x07, // compressed size
+                       0x08, 0x09, 0x0a, 0x0b, // uncompressed size
+               },
+               want: &dataDescriptor{
+                       crc32:            0x03020100,
+                       compressedSize:   0x07060504,
+                       uncompressedSize: 0x0b0a0908,
+               },
+       }, {
+               desc: "valid 32 bit without signature",
+               in: []byte{
+                       0x00, 0x01, 0x02, 0x03, // crc32
+                       0x04, 0x05, 0x06, 0x07, // compressed size
+                       0x08, 0x09, 0x0a, 0x0b, // uncompressed size
+               },
+               want: &dataDescriptor{
+                       crc32:            0x03020100,
+                       compressedSize:   0x07060504,
+                       uncompressedSize: 0x0b0a0908,
+               },
+       }, {
+               desc: "valid 64 bit with signature",
+               in: []byte{
+                       0x50, 0x4b, 0x07, 0x08, // signature
+                       0x00, 0x01, 0x02, 0x03, // crc32
+                       0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // compressed size
+                       0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, // uncompressed size
+               },
+               zip64: true,
+               want: &dataDescriptor{
+                       crc32:            0x03020100,
+                       compressedSize:   0x0b0a090807060504,
+                       uncompressedSize: 0x131211100f0e0d0c,
+               },
+       }, {
+               desc: "valid 64 bit without signature",
+               in: []byte{
+                       0x00, 0x01, 0x02, 0x03, // crc32
+                       0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // compressed size
+                       0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, // uncompressed size
+               },
+               zip64: true,
+               want: &dataDescriptor{
+                       crc32:            0x03020100,
+                       compressedSize:   0x0b0a090807060504,
+                       uncompressedSize: 0x131211100f0e0d0c,
+               },
+       }, {
+               desc: "invalid 32 bit with signature",
+               in: []byte{
+                       0x50, 0x4b, 0x07, 0x08, // signature
+                       0x00, 0x01, 0x02, 0x03, // crc32
+                       0x04, 0x05, // unexpected end
+               },
+               wantErr: io.ErrUnexpectedEOF,
+       }, {
+               desc: "invalid 32 bit without signature",
+               in: []byte{
+                       0x00, 0x01, 0x02, 0x03, // crc32
+                       0x04, 0x05, // unexpected end
+               },
+               wantErr: io.ErrUnexpectedEOF,
+       }, {
+               desc: "invalid 64 bit with signature",
+               in: []byte{
+                       0x50, 0x4b, 0x07, 0x08, // signature
+                       0x00, 0x01, 0x02, 0x03, // crc32
+                       0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // compressed size
+                       0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, // unexpected end
+               },
+               zip64:   true,
+               wantErr: io.ErrUnexpectedEOF,
+       }, {
+               desc: "invalid 64 bit without signature",
+               in: []byte{
+                       0x00, 0x01, 0x02, 0x03, // crc32
+                       0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // compressed size
+                       0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, // unexpected end
+               },
+               zip64:   true,
+               wantErr: io.ErrUnexpectedEOF,
+       }}
+
+       for _, test := range tests {
+               t.Run(test.desc, func(t *testing.T) {
+                       r := bytes.NewReader(test.in)
+
+                       desc, err := readDataDescriptor(r, test.zip64)
+                       if err != test.wantErr {
+                               t.Fatalf("got err %v; want nil", err)
+                       }
+                       if test.want == nil {
+                               return
+                       }
+                       if desc == nil {
+                               t.Fatalf("got nil DataDescriptor; want non-nil")
+                       }
+                       if desc.crc32 != test.want.crc32 {
+                               t.Errorf("got CRC32 %#x; want %#x", desc.crc32, test.want.crc32)
+                       }
+                       if desc.compressedSize != test.want.compressedSize {
+                               t.Errorf("got CompressedSize %#x; want %#x", desc.compressedSize, test.want.compressedSize)
+                       }
+                       if desc.uncompressedSize != test.want.uncompressedSize {
+                               t.Errorf("got UncompressedSize %#x; want %#x", desc.uncompressedSize, test.want.uncompressedSize)
+                       }
+               })
+       }
+}
+
 func TestCVE202133196(t *testing.T) {
        // Archive that indicates it has 1 << 128 -1 files,
        // this would previously cause a panic due to attempting
index 4dd29f35fa63f6e8d898ab2b55faa46b3611d918..ff9f605eb697eec319602d455917953b70b906e6 100644 (file)
@@ -42,7 +42,7 @@ const (
        directoryHeaderLen       = 46         // + filename + extra + comment
        directoryEndLen          = 22         // + comment
        dataDescriptorLen        = 16         // four uint32: descriptor signature, crc32, compressed size, size
-       dataDescriptor64Len      = 24         // descriptor with 8 byte sizes
+       dataDescriptor64Len      = 24         // two uint32: signature, crc32 | two uint64: compressed size, size
        directory64LocLen        = 20         //
        directory64EndLen        = 56         // + extra
 
@@ -315,6 +315,10 @@ func (h *FileHeader) isZip64() bool {
        return h.CompressedSize64 >= uint32max || h.UncompressedSize64 >= uint32max
 }
 
+func (f *FileHeader) hasDataDescriptor() bool {
+       return f.Flags&0x8 != 0
+}
+
 func msdosModeToFileMode(m uint32) (mode fs.FileMode) {
        if m&msdosDir != 0 {
                mode = fs.ModeDir | 0777
@@ -341,11 +345,9 @@ func fileModeToUnixMode(mode fs.FileMode) uint32 {
        case fs.ModeSocket:
                m = s_IFSOCK
        case fs.ModeDevice:
-               if mode&fs.ModeCharDevice != 0 {
-                       m = s_IFCHR
-               } else {
-                       m = s_IFBLK
-               }
+               m = s_IFBLK
+       case fs.ModeDevice | fs.ModeCharDevice:
+               m = s_IFCHR
        }
        if mode&fs.ModeSetuid != 0 {
                m |= s_ISUID
@@ -388,3 +390,11 @@ func unixModeToFileMode(m uint32) fs.FileMode {
        }
        return mode
 }
+
+// dataDescriptor holds the data descriptor that optionally follows the file
+// contents in the zip file.
+type dataDescriptor struct {
+       crc32            uint32
+       compressedSize   uint64
+       uncompressedSize uint64
+}
index cdc534eaf01922df345eb4a44b372ef4c8fbc1bc..3b23cc3391d9e676a6735266fa8bb76a73ace755 100644 (file)
@@ -37,6 +37,7 @@ type Writer struct {
 type header struct {
        *FileHeader
        offset uint64
+       raw    bool
 }
 
 // NewWriter returns a new Writer writing a zip file to w.
@@ -245,22 +246,31 @@ func detectUTF8(s string) (valid, require bool) {
        return true, require
 }
 
+// prepare performs the bookkeeping operations required at the start of
+// CreateHeader and CreateRaw.
+func (w *Writer) prepare(fh *FileHeader) error {
+       if w.last != nil && !w.last.closed {
+               if err := w.last.close(); err != nil {
+                       return err
+               }
+       }
+       if len(w.dir) > 0 && w.dir[len(w.dir)-1].FileHeader == fh {
+               // See https://golang.org/issue/11144 confusion.
+               return errors.New("archive/zip: invalid duplicate FileHeader")
+       }
+       return nil
+}
+
 // CreateHeader adds a file to the zip archive using the provided FileHeader
 // for the file metadata. Writer takes ownership of fh and may mutate
 // its fields. The caller must not modify fh after calling CreateHeader.
 //
 // This returns a Writer to which the file contents should be written.
 // The file's contents must be written to the io.Writer before the next
-// call to Create, CreateHeader, or Close.
+// call to Create, CreateHeader, CreateRaw, or Close.
 func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
-       if w.last != nil && !w.last.closed {
-               if err := w.last.close(); err != nil {
-                       return nil, err
-               }
-       }
-       if len(w.dir) > 0 && w.dir[len(w.dir)-1].FileHeader == fh {
-               // See https://golang.org/issue/11144 confusion.
-               return nil, errors.New("archive/zip: invalid duplicate FileHeader")
+       if err := w.prepare(fh); err != nil {
+               return nil, err
        }
 
        // The ZIP format has a sad state of affairs regarding character encoding.
@@ -365,7 +375,7 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
                ow = fw
        }
        w.dir = append(w.dir, h)
-       if err := writeHeader(w.cw, fh); err != nil {
+       if err := writeHeader(w.cw, h); err != nil {
                return nil, err
        }
        // If we're creating a directory, fw is nil.
@@ -373,7 +383,7 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
        return ow, nil
 }
 
-func writeHeader(w io.Writer, h *FileHeader) error {
+func writeHeader(w io.Writer, h *header) error {
        const maxUint16 = 1<<16 - 1
        if len(h.Name) > maxUint16 {
                return errLongName
@@ -390,9 +400,20 @@ func writeHeader(w io.Writer, h *FileHeader) error {
        b.uint16(h.Method)
        b.uint16(h.ModifiedTime)
        b.uint16(h.ModifiedDate)
-       b.uint32(0) // since we are writing a data descriptor crc32,
-       b.uint32(0) // compressed size,
-       b.uint32(0) // and uncompressed size should be zero
+       // In raw mode (caller does the compression), the values are either
+       // written here or in the trailing data descriptor based on the header
+       // flags.
+       if h.raw && !h.hasDataDescriptor() {
+               b.uint32(h.CRC32)
+               b.uint32(uint32(min64(h.CompressedSize64, uint32max)))
+               b.uint32(uint32(min64(h.UncompressedSize64, uint32max)))
+       } else {
+               // When this package handle the compression, these values are
+               // always written to the trailing data descriptor.
+               b.uint32(0) // crc32
+               b.uint32(0) // compressed size
+               b.uint32(0) // uncompressed size
+       }
        b.uint16(uint16(len(h.Name)))
        b.uint16(uint16(len(h.Extra)))
        if _, err := w.Write(buf[:]); err != nil {
@@ -405,6 +426,65 @@ func writeHeader(w io.Writer, h *FileHeader) error {
        return err
 }
 
+func min64(x, y uint64) uint64 {
+       if x < y {
+               return x
+       }
+       return y
+}
+
+// CreateRaw adds a file to the zip archive using the provided FileHeader and
+// returns a Writer to which the file contents should be written. The file's
+// contents must be written to the io.Writer before the next call to Create,
+// CreateHeader, CreateRaw, or Close.
+//
+// In contrast to CreateHeader, the bytes passed to Writer are not compressed.
+func (w *Writer) CreateRaw(fh *FileHeader) (io.Writer, error) {
+       if err := w.prepare(fh); err != nil {
+               return nil, err
+       }
+
+       fh.CompressedSize = uint32(min64(fh.CompressedSize64, uint32max))
+       fh.UncompressedSize = uint32(min64(fh.UncompressedSize64, uint32max))
+
+       h := &header{
+               FileHeader: fh,
+               offset:     uint64(w.cw.count),
+               raw:        true,
+       }
+       w.dir = append(w.dir, h)
+       if err := writeHeader(w.cw, h); err != nil {
+               return nil, err
+       }
+
+       if strings.HasSuffix(fh.Name, "/") {
+               w.last = nil
+               return dirWriter{}, nil
+       }
+
+       fw := &fileWriter{
+               header: h,
+               zipw:   w.cw,
+       }
+       w.last = fw
+       return fw, nil
+}
+
+// Copy copies the file f (obtained from a Reader) into w. It copies the raw
+// form directly bypassing decompression, compression, and validation.
+func (w *Writer) Copy(f *File) error {
+       r, err := f.OpenRaw()
+       if err != nil {
+               return err
+       }
+       fw, err := w.CreateRaw(&f.FileHeader)
+       if err != nil {
+               return err
+       }
+       _, err = io.Copy(fw, r)
+       return err
+}
+
 // RegisterCompressor registers or overrides a custom compressor for a specific
 // method ID. If a compressor for a given method is not found, Writer will
 // default to looking up the compressor at the package level.
@@ -446,6 +526,9 @@ func (w *fileWriter) Write(p []byte) (int, error) {
        if w.closed {
                return 0, errors.New("zip: write to closed file")
        }
+       if w.raw {
+               return w.zipw.Write(p)
+       }
        w.crc32.Write(p)
        return w.rawCount.Write(p)
 }
@@ -455,6 +538,9 @@ func (w *fileWriter) close() error {
                return errors.New("zip: file closed twice")
        }
        w.closed = true
+       if w.raw {
+               return w.writeDataDescriptor()
+       }
        if err := w.comp.Close(); err != nil {
                return err
        }
@@ -474,26 +560,33 @@ func (w *fileWriter) close() error {
                fh.UncompressedSize = uint32(fh.UncompressedSize64)
        }
 
+       return w.writeDataDescriptor()
+}
+
+func (w *fileWriter) writeDataDescriptor() error {
+       if !w.hasDataDescriptor() {
+               return nil
+       }
        // Write data descriptor. This is more complicated than one would
        // think, see e.g. comments in zipfile.c:putextended() and
        // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7073588.
        // The approach here is to write 8 byte sizes if needed without
        // adding a zip64 extra in the local header (too late anyway).
        var buf []byte
-       if fh.isZip64() {
+       if w.isZip64() {
                buf = make([]byte, dataDescriptor64Len)
        } else {
                buf = make([]byte, dataDescriptorLen)
        }
        b := writeBuf(buf)
        b.uint32(dataDescriptorSignature) // de-facto standard, required by OS X
-       b.uint32(fh.CRC32)
-       if fh.isZip64() {
-               b.uint64(fh.CompressedSize64)
-               b.uint64(fh.UncompressedSize64)
+       b.uint32(w.CRC32)
+       if w.isZip64() {
+               b.uint64(w.CompressedSize64)
+               b.uint64(w.UncompressedSize64)
        } else {
-               b.uint32(fh.CompressedSize)
-               b.uint32(fh.UncompressedSize)
+               b.uint32(w.CompressedSize)
+               b.uint32(w.UncompressedSize)
        }
        _, err := w.zipw.Write(buf)
        return err
index 5985144e5c2d25fb3df2fe37682fa0fd4c1b3d8a..97c6c5297994684ca7fcfc5ccc492025709d795c 100644 (file)
@@ -6,8 +6,10 @@ package zip
 
 import (
        "bytes"
+       "compress/flate"
        "encoding/binary"
        "fmt"
+       "hash/crc32"
        "io"
        "io/fs"
        "math/rand"
@@ -57,6 +59,18 @@ var writeTests = []WriteTest{
                Method: Deflate,
                Mode:   0755 | fs.ModeSymlink,
        },
+       {
+               Name:   "device",
+               Data:   []byte("device file"),
+               Method: Deflate,
+               Mode:   0755 | fs.ModeDevice,
+       },
+       {
+               Name:   "chardevice",
+               Data:   []byte("char device file"),
+               Method: Deflate,
+               Mode:   0755 | fs.ModeDevice | fs.ModeCharDevice,
+       },
 }
 
 func TestWriter(t *testing.T) {
@@ -353,6 +367,171 @@ func TestWriterDirAttributes(t *testing.T) {
        }
 }
 
+func TestWriterCopy(t *testing.T) {
+       // make a zip file
+       buf := new(bytes.Buffer)
+       w := NewWriter(buf)
+       for _, wt := range writeTests {
+               testCreate(t, w, &wt)
+       }
+       if err := w.Close(); err != nil {
+               t.Fatal(err)
+       }
+
+       // read it back
+       src, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()))
+       if err != nil {
+               t.Fatal(err)
+       }
+       for i, wt := range writeTests {
+               testReadFile(t, src.File[i], &wt)
+       }
+
+       // make a new zip file copying the old compressed data.
+       buf2 := new(bytes.Buffer)
+       dst := NewWriter(buf2)
+       for _, f := range src.File {
+               if err := dst.Copy(f); err != nil {
+                       t.Fatal(err)
+               }
+       }
+       if err := dst.Close(); err != nil {
+               t.Fatal(err)
+       }
+
+       // read the new one back
+       r, err := NewReader(bytes.NewReader(buf2.Bytes()), int64(buf2.Len()))
+       if err != nil {
+               t.Fatal(err)
+       }
+       for i, wt := range writeTests {
+               testReadFile(t, r.File[i], &wt)
+       }
+}
+
+func TestWriterCreateRaw(t *testing.T) {
+       files := []struct {
+               name             string
+               content          []byte
+               method           uint16
+               flags            uint16
+               crc32            uint32
+               uncompressedSize uint64
+               compressedSize   uint64
+       }{
+               {
+                       name:    "small store w desc",
+                       content: []byte("gophers"),
+                       method:  Store,
+                       flags:   0x8,
+               },
+               {
+                       name:    "small deflate wo desc",
+                       content: bytes.Repeat([]byte("abcdefg"), 2048),
+                       method:  Deflate,
+               },
+       }
+
+       // write a zip file
+       archive := new(bytes.Buffer)
+       w := NewWriter(archive)
+
+       for i := range files {
+               f := &files[i]
+               f.crc32 = crc32.ChecksumIEEE(f.content)
+               size := uint64(len(f.content))
+               f.uncompressedSize = size
+               f.compressedSize = size
+
+               var compressedContent []byte
+               if f.method == Deflate {
+                       var buf bytes.Buffer
+                       w, err := flate.NewWriter(&buf, flate.BestSpeed)
+                       if err != nil {
+                               t.Fatalf("flate.NewWriter err = %v", err)
+                       }
+                       _, err = w.Write(f.content)
+                       if err != nil {
+                               t.Fatalf("flate Write err = %v", err)
+                       }
+                       err = w.Close()
+                       if err != nil {
+                               t.Fatalf("flate Writer.Close err = %v", err)
+                       }
+                       compressedContent = buf.Bytes()
+                       f.compressedSize = uint64(len(compressedContent))
+               }
+
+               h := &FileHeader{
+                       Name:               f.name,
+                       Method:             f.method,
+                       Flags:              f.flags,
+                       CRC32:              f.crc32,
+                       CompressedSize64:   f.compressedSize,
+                       UncompressedSize64: f.uncompressedSize,
+               }
+               w, err := w.CreateRaw(h)
+               if err != nil {
+                       t.Fatal(err)
+               }
+               if compressedContent != nil {
+                       _, err = w.Write(compressedContent)
+               } else {
+                       _, err = w.Write(f.content)
+               }
+               if err != nil {
+                       t.Fatalf("%s Write got %v; want nil", f.name, err)
+               }
+       }
+
+       if err := w.Close(); err != nil {
+               t.Fatal(err)
+       }
+
+       // read it back
+       r, err := NewReader(bytes.NewReader(archive.Bytes()), int64(archive.Len()))
+       if err != nil {
+               t.Fatal(err)
+       }
+       for i, want := range files {
+               got := r.File[i]
+               if got.Name != want.name {
+                       t.Errorf("got Name %s; want %s", got.Name, want.name)
+               }
+               if got.Method != want.method {
+                       t.Errorf("%s: got Method %#x; want %#x", want.name, got.Method, want.method)
+               }
+               if got.Flags != want.flags {
+                       t.Errorf("%s: got Flags %#x; want %#x", want.name, got.Flags, want.flags)
+               }
+               if got.CRC32 != want.crc32 {
+                       t.Errorf("%s: got CRC32 %#x; want %#x", want.name, got.CRC32, want.crc32)
+               }
+               if got.CompressedSize64 != want.compressedSize {
+                       t.Errorf("%s: got CompressedSize64 %d; want %d", want.name, got.CompressedSize64, want.compressedSize)
+               }
+               if got.UncompressedSize64 != want.uncompressedSize {
+                       t.Errorf("%s: got UncompressedSize64 %d; want %d", want.name, got.UncompressedSize64, want.uncompressedSize)
+               }
+
+               r, err := got.Open()
+               if err != nil {
+                       t.Errorf("%s: Open err = %v", got.Name, err)
+                       continue
+               }
+
+               buf, err := io.ReadAll(r)
+               if err != nil {
+                       t.Errorf("%s: ReadAll err = %v", got.Name, err)
+                       continue
+               }
+
+               if !bytes.Equal(buf, want.content) {
+                       t.Errorf("%v: ReadAll returned unexpected bytes", got.Name)
+               }
+       }
+}
+
 func testCreate(t *testing.T, w *Writer, wt *WriteTest) {
        header := &FileHeader{
                Name:   wt.Name,
@@ -378,15 +557,15 @@ func testReadFile(t *testing.T, f *File, wt *WriteTest) {
        testFileMode(t, f, wt.Mode)
        rc, err := f.Open()
        if err != nil {
-               t.Fatal("opening:", err)
+               t.Fatalf("opening %s: %v", f.Name, err)
        }
        b, err := io.ReadAll(rc)
        if err != nil {
-               t.Fatal("reading:", err)
+               t.Fatalf("reading %s: %v", f.Name, err)
        }
        err = rc.Close()
        if err != nil {
-               t.Fatal("closing:", err)
+               t.Fatalf("closing %s: %v", f.Name, err)
        }
        if !bytes.Equal(b, wt.Data) {
                t.Errorf("File contents %q, want %q", b, wt.Data)
index 6baf9b9e400f388c621bd8f5709d8918f1feebff..ec928e7ad69ed54d213d3a38d9efb011ff32eb82 100644 (file)
@@ -670,7 +670,8 @@ func (b *Writer) WriteByte(c byte) error {
 // WriteRune writes a single Unicode code point, returning
 // the number of bytes written and any error.
 func (b *Writer) WriteRune(r rune) (size int, err error) {
-       if r < utf8.RuneSelf {
+       // Compare as uint32 to correctly handle negative runes.
+       if uint32(r) < utf8.RuneSelf {
                err = b.WriteByte(byte(r))
                if err != nil {
                        return 0, err
index d7b34bd0d8f66b485a49ad355fce86c3a9d5f726..ebcc711db9d48cdefa44d6ec9bddd2406c13b59d 100644 (file)
@@ -534,6 +534,20 @@ func TestReadWriteRune(t *testing.T) {
        }
 }
 
+func TestWriteInvalidRune(t *testing.T) {
+       // Invalid runes, including negative ones, should be written as the
+       // replacement character.
+       for _, r := range []rune{-1, utf8.MaxRune + 1} {
+               var buf bytes.Buffer
+               w := NewWriter(&buf)
+               w.WriteRune(r)
+               w.Flush()
+               if s := buf.String(); s != "\uFFFD" {
+                       t.Errorf("WriteRune(%d) wrote %q, not replacement character", r, s)
+               }
+       }
+}
+
 func TestReadStringAllocs(t *testing.T) {
        r := strings.NewReader("       foo       foo        42        42        42        42        42        42        42        42       4.2       4.2       4.2       4.2\n")
        buf := NewReader(r)
index af46a14fbbe0ff9f34680b7e0f6467afa3e207ef..4846d4f733677777a50e24d971cdf643954d4f23 100644 (file)
@@ -48,7 +48,8 @@ type Scanner struct {
 // and the next token to return to the user, if any, plus an error, if any.
 //
 // Scanning stops if the function returns an error, in which case some of
-// the input may be discarded.
+// the input may be discarded. If that error is ErrFinalToken, scanning
+// stops with no error.
 //
 // Otherwise, the Scanner advances the input. If the token is not nil,
 // the Scanner returns it to the user. If the token is nil, the
index ea84f1e40fd856d3f2a173e83fc965c89ffcc00d..5a47526593b093678b85e0c45c2dfbd5a42d16ed 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 //
+//go:build linux
 // +build linux
 
 package bytes_test
index f19a4cfff0926c7eba61cead788062b074b1a091..549b077708f80e3742e79b0e93e29d3432d3c6c7 100644 (file)
@@ -275,7 +275,8 @@ func (b *Buffer) WriteByte(c byte) error {
 // included to match bufio.Writer's WriteRune. The buffer is grown as needed;
 // if it becomes too large, WriteRune will panic with ErrTooLarge.
 func (b *Buffer) WriteRune(r rune) (n int, err error) {
-       if r < utf8.RuneSelf {
+       // Compare as uint32 to correctly handle negative runes.
+       if uint32(r) < utf8.RuneSelf {
                b.WriteByte(byte(r))
                return 1, nil
        }
index fec5ef8a35f637dacd1c95b9ad3034b6f3559308..9c9b7440ffaa753625a365534a2c7ec30baf4ff2 100644 (file)
@@ -6,6 +6,7 @@ package bytes_test
 
 import (
        . "bytes"
+       "fmt"
        "io"
        "math/rand"
        "testing"
@@ -387,6 +388,16 @@ func TestRuneIO(t *testing.T) {
        }
 }
 
+func TestWriteInvalidRune(t *testing.T) {
+       // Invalid runes, including negative ones, should be written as
+       // utf8.RuneError.
+       for _, r := range []rune{-1, utf8.MaxRune + 1} {
+               var buf Buffer
+               buf.WriteRune(r)
+               check(t, fmt.Sprintf("TestWriteInvalidRune (%d)", r), &buf, "\uFFFD")
+       }
+}
+
 func TestNext(t *testing.T) {
        b := []byte{0, 1, 2, 3, 4}
        tmp := make([]byte, 5)
index e782c866ac771640c365ad97e5055b7cabdceaa3..a6787f640501133173e82804d1a2c1fc289504a5 100644 (file)
@@ -387,6 +387,9 @@ and of course there is nothing stopping the C code from doing anything
 it likes. However, programs that break these rules are likely to fail
 in unexpected and unpredictable ways.
 
+The runtime/cgo.Handle type can be used to safely pass Go values
+between Go and C. See the runtime/cgo package documentation for details.
+
 Note: the current implementation has a bug. While Go code is permitted
 to write nil or a C pointer (but not a Go pointer) to C memory, the
 current implementation may sometimes cause a runtime error if the
index fa24567d9bc32f00b959f4bd3df393781dd70558..de64a75f710485894d543ba761277eb963b12ebe 100644 (file)
@@ -927,7 +927,7 @@ func (p *Package) rewriteCall(f *File, call *Call) (string, bool) {
        var sbCheck bytes.Buffer
        for i, param := range params {
                origArg := args[i]
-               arg, nu := p.mangle(f, &args[i])
+               arg, nu := p.mangle(f, &args[i], true)
                if nu {
                        needsUnsafe = true
                }
@@ -970,7 +970,7 @@ func (p *Package) rewriteCall(f *File, call *Call) (string, bool) {
                sb.WriteString("return ")
        }
 
-       m, nu := p.mangle(f, &call.Call.Fun)
+       m, nu := p.mangle(f, &call.Call.Fun, false)
        if nu {
                needsUnsafe = true
        }
@@ -1104,7 +1104,8 @@ func (p *Package) hasPointer(f *File, t ast.Expr, top bool) bool {
 // rewriting calls when it finds them.
 // It removes the corresponding references in f.Ref and f.Calls, so that we
 // don't try to do the replacement again in rewriteRef or rewriteCall.
-func (p *Package) mangle(f *File, arg *ast.Expr) (ast.Expr, bool) {
+// If addPosition is true, add position info to the idents of C names in arg.
+func (p *Package) mangle(f *File, arg *ast.Expr, addPosition bool) (ast.Expr, bool) {
        needsUnsafe := false
        f.walk(arg, ctxExpr, func(f *File, arg interface{}, context astContext) {
                px, ok := arg.(*ast.Expr)
@@ -1119,7 +1120,7 @@ func (p *Package) mangle(f *File, arg *ast.Expr) (ast.Expr, bool) {
 
                        for _, r := range f.Ref {
                                if r.Expr == px {
-                                       *px = p.rewriteName(f, r)
+                                       *px = p.rewriteName(f, r, addPosition)
                                        r.Done = true
                                        break
                                }
@@ -1379,7 +1380,7 @@ func (p *Package) rewriteRef(f *File) {
                        }
                }
 
-               expr := p.rewriteName(f, r)
+               expr := p.rewriteName(f, r, false)
 
                if *godefs {
                        // Substitute definition for mangled type name.
@@ -1442,8 +1443,23 @@ func (p *Package) rewriteRef(f *File) {
 }
 
 // rewriteName returns the expression used to rewrite a reference.
-func (p *Package) rewriteName(f *File, r *Ref) ast.Expr {
-       var expr ast.Expr = ast.NewIdent(r.Name.Mangle) // default
+// If addPosition is true, add position info in the ident name.
+func (p *Package) rewriteName(f *File, r *Ref, addPosition bool) ast.Expr {
+       getNewIdent := ast.NewIdent
+       if addPosition {
+               getNewIdent = func(newName string) *ast.Ident {
+                       mangledIdent := ast.NewIdent(newName)
+                       if len(newName) == len(r.Name.Go) {
+                               return mangledIdent
+                       }
+                       p := fset.Position((*r.Expr).End())
+                       if p.Column == 0 {
+                               return mangledIdent
+                       }
+                       return ast.NewIdent(fmt.Sprintf("%s /*line :%d:%d*/", newName, p.Line, p.Column))
+               }
+       }
+       var expr ast.Expr = getNewIdent(r.Name.Mangle) // default
        switch r.Context {
        case ctxCall, ctxCall2:
                if r.Name.Kind != "func" {
@@ -1471,7 +1487,7 @@ func (p *Package) rewriteName(f *File, r *Ref) ast.Expr {
                                n.Mangle = "_C2func_" + n.Go
                                f.Name["2"+r.Name.Go] = n
                        }
-                       expr = ast.NewIdent(n.Mangle)
+                       expr = getNewIdent(n.Mangle)
                        r.Name = n
                        break
                }
@@ -1502,7 +1518,7 @@ func (p *Package) rewriteName(f *File, r *Ref) ast.Expr {
                        // issue 7757.
                        expr = &ast.CallExpr{
                                Fun:  &ast.Ident{NamePos: (*r.Expr).Pos(), Name: "_Cgo_ptr"},
-                               Args: []ast.Expr{ast.NewIdent(name.Mangle)},
+                               Args: []ast.Expr{getNewIdent(name.Mangle)},
                        }
                case "type":
                        // Okay - might be new(T)
@@ -1584,9 +1600,17 @@ func (p *Package) gccMachine() []string {
        case "s390x":
                return []string{"-m64"}
        case "mips64", "mips64le":
-               return []string{"-mabi=64"}
+               if gomips64 == "hardfloat" {
+                       return []string{"-mabi=64", "-mhard-float"}
+               } else if gomips64 == "softfloat" {
+                       return []string{"-mabi=64", "-msoft-float"}
+               }
        case "mips", "mipsle":
-               return []string{"-mabi=32"}
+               if gomips == "hardfloat" {
+                       return []string{"-mabi=32", "-mfp32", "-mhard-float", "-mno-odd-spreg"}
+               } else if gomips == "softfloat" {
+                       return []string{"-mabi=32", "-msoft-float"}
+               }
        case "ppc64":
                if goos == "aix" {
                        return []string{"-maix64"}
@@ -1639,6 +1663,8 @@ func (p *Package) gccCmd() []string {
        if goos == "aix" {
                c = append(c, "-mcmodel=large")
        }
+       // disable LTO so we get an object whose symbols we can read
+       c = append(c, "-fno-lto")
        c = append(c, "-") //read input from standard input
        return c
 }
index c47e99170c0ff5f48e14c36302fef8ef2cd953f1..40dc6d2562d0e36707894e29c72f644eba688938 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Cgo; see gmp.go for an overview.
+// Cgo; see doc.go for an overview.
 
 // TODO(rsc):
 //     Emit correct line number annotations.
@@ -17,9 +17,11 @@ import (
        "go/ast"
        "go/printer"
        "go/token"
+       "internal/buildcfg"
        "io"
        "io/ioutil"
        "os"
+       "os/exec"
        "path/filepath"
        "reflect"
        "runtime"
@@ -249,7 +251,7 @@ var importRuntimeCgo = flag.Bool("import_runtime_cgo", true, "import runtime/cgo
 var importSyscall = flag.Bool("import_syscall", true, "import syscall in generated code")
 var trimpath = flag.String("trimpath", "", "applies supplied rewrites or trims prefixes to recorded source file paths")
 
-var goarch, goos string
+var goarch, goos, gomips, gomips64 string
 
 func main() {
        objabi.AddVersionFlag() // -V
@@ -306,6 +308,14 @@ func main() {
 
        p := newPackage(args[:i])
 
+       // We need a C compiler to be available. Check this.
+       gccName := p.gccBaseCmd()[0]
+       _, err := exec.LookPath(gccName)
+       if err != nil {
+               fatalf("C compiler %q not found: %v", gccName, err)
+               os.Exit(2)
+       }
+
        // Record CGO_LDFLAGS from the environment for external linking.
        if ldflags := os.Getenv("CGO_LDFLAGS"); ldflags != "" {
                args, err := splitQuoted(ldflags)
@@ -409,6 +419,9 @@ func newPackage(args []string) *Package {
        if s := os.Getenv("GOOS"); s != "" {
                goos = s
        }
+       buildcfg.Check()
+       gomips = buildcfg.GOMIPS
+       gomips64 = buildcfg.GOMIPS64
        ptrSize := ptrSizeMap[goarch]
        if ptrSize == 0 {
                fatalf("unknown ptrSize for $GOARCH %q", goarch)
index b469b5fe06a089410f5d626845c5b867a477b0bb..3cf16f90f98099cfe44c7592ac6e9f12db307a89 100644 (file)
@@ -173,8 +173,18 @@ func (p *Package) writeDefs() {
                        if *gccgo {
                                fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
                        } else {
-                               fmt.Fprintf(fm, "extern char %s[];\n", n.C)
-                               fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C)
+                               // Force a reference to all symbols so that
+                               // the external linker will add DT_NEEDED
+                               // entries as needed on ELF systems.
+                               // Treat function variables differently
+                               // to avoid type confict errors from LTO
+                               // (Link Time Optimization).
+                               if n.Kind == "fpvar" {
+                                       fmt.Fprintf(fm, "extern void %s();\n", n.C)
+                               } else {
+                                       fmt.Fprintf(fm, "extern char %s[];\n", n.C)
+                                       fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C)
+                               }
                                fmt.Fprintf(fgo2, "//go:linkname __cgo_%s %s\n", n.C, n.C)
                                fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", n.C)
                                fmt.Fprintf(fgo2, "var __cgo_%s byte\n", n.C)
@@ -1026,14 +1036,28 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
                }
                fmt.Fprintf(fgcc, "}\n")
 
-               // Build the wrapper function compiled by cmd/compile.
-               // This unpacks the argument struct above and calls the Go function.
+               // In internal linking mode, the Go linker sees both
+               // the C wrapper written above and the Go wrapper it
+               // references. Hence, export the C wrapper (e.g., for
+               // if we're building a shared object). The Go linker
+               // will resolve the C wrapper's reference to the Go
+               // wrapper without a separate export.
                fmt.Fprintf(fgo2, "//go:cgo_export_dynamic %s\n", exp.ExpName)
+               // cgo_export_static refers to a symbol by its linker
+               // name, so set the linker name of the Go wrapper.
                fmt.Fprintf(fgo2, "//go:linkname _cgoexp%s_%s _cgoexp%s_%s\n", cPrefix, exp.ExpName, cPrefix, exp.ExpName)
+               // In external linking mode, the Go linker sees the Go
+               // wrapper, but not the C wrapper. For this case,
+               // export the Go wrapper so the host linker can
+               // resolve the reference from the C wrapper to the Go
+               // wrapper.
                fmt.Fprintf(fgo2, "//go:cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
+
+               // Build the wrapper function compiled by cmd/compile.
+               // This unpacks the argument struct above and calls the Go function.
                fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a *%s) {\n", cPrefix, exp.ExpName, gotype)
 
-               fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName)
+               fmt.Fprintf(fm, "void _cgoexp%s_%s(void* p){}\n", cPrefix, exp.ExpName)
 
                if gccResult != "void" {
                        // Write results back to frame.
@@ -1722,8 +1746,12 @@ typedef struct __go_open_array {
 struct __go_string __go_byte_array_to_string(const void* p, intgo len);
 struct __go_open_array __go_string_to_byte_array (struct __go_string str);
 
+extern void runtime_throw(const char *);
+
 const char *_cgoPREFIX_Cfunc_CString(struct __go_string s) {
        char *p = malloc(s.__length+1);
+       if(p == NULL)
+               runtime_throw("runtime: C malloc failed");
        memmove(p, s.__data, s.__length);
        p[s.__length] = 0;
        return p;
@@ -1731,6 +1759,8 @@ const char *_cgoPREFIX_Cfunc_CString(struct __go_string s) {
 
 void *_cgoPREFIX_Cfunc_CBytes(struct __go_open_array b) {
        char *p = malloc(b.__count);
+       if(p == NULL)
+               runtime_throw("runtime: C malloc failed");
        memmove(p, b.__values, b.__count);
        return p;
 }
@@ -1749,14 +1779,13 @@ Slice _cgoPREFIX_Cfunc_GoBytes(char *p, int32_t n) {
        return __go_string_to_byte_array(s);
 }
 
-extern void runtime_throw(const char *);
 void *_cgoPREFIX_Cfunc__CMalloc(size_t n) {
-        void *p = malloc(n);
-        if(p == NULL && n == 0)
-                p = malloc(1);
-        if(p == NULL)
-                runtime_throw("runtime: C malloc failed");
-        return p;
+       void *p = malloc(n);
+       if(p == NULL && n == 0)
+               p = malloc(1);
+       if(p == NULL)
+               runtime_throw("runtime: C malloc failed");
+       return p;
 }
 
 struct __go_type_descriptor;
index 70b1b0690b38a251fe7ce8a10a97e2b6846d1d86..cd03968eedcf618d0ecef8da89ce790646dba399 100644 (file)
@@ -1,12 +1,15 @@
 module cmd
 
-go 1.16
+go 1.17
 
 require (
-       github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2
-       golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff
-       golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
-       golang.org/x/mod v0.4.2-0.20210325185522-dbbbf8a3c6ea
-       golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect
-       golang.org/x/tools v0.0.0-20210107193943-4ed967dd8eff
+       github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a
+       github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 // indirect
+       golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e
+       golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e // indirect
+       golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a
+       golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 // indirect
+       golang.org/x/term v0.0.0-20210503060354-a79de5458b56
+       golang.org/x/tools v0.1.2-0.20210519160823-49064d2332f9
+       golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
 )
index 84f89c9d2d2be49f3911aa00121d3ba2e3869f31..7f88d3216cf080a9573026997231cc608a801589 100644 (file)
 //     -p n
 //             the number of programs, such as build commands or
 //             test binaries, that can be run in parallel.
-//             The default is the number of CPUs available.
+//             The default is GOMAXPROCS, normally the number of CPUs available.
 //     -race
 //             enable data race detection.
 //             Supported only on linux/amd64, freebsd/amd64, darwin/amd64, windows/amd64,
 //             a build will run as if the disk file path exists with the contents
 //             given by the backing file paths, or as if the disk file path does not
 //             exist if its backing file path is empty. Support for the -overlay flag
-//             has some limitations:importantly, cgo files included from outside the
-//             include path must be  in the same directory as the Go package they are
+//             has some limitations: importantly, cgo files included from outside the
+//             include path must be in the same directory as the Go package they are
 //             included from, and overlays will not appear when binaries and tests are
 //             run through go run and go test respectively.
 //     -pkgdir dir
 //             a program to use to invoke toolchain programs like vet and asm.
 //             For example, instead of running asm, the go command will run
 //             'cmd args /path/to/asm <arguments for asm>'.
+//             The TOOLEXEC_IMPORTPATH environment variable will be set,
+//             matching 'go list -f {{.ImportPath}}' for the package being built.
 //
 // The -asmflags, -gccgoflags, -gcflags, and -ldflags flags accept a
 // space-separated list of arguments to pass to an underlying tool
 //
 // Usage:
 //
-//     go doc [-u] [-c] [package|[package.]symbol[.methodOrField]]
+//     go doc [doc flags] [package|[package.]symbol[.methodOrField]]
 //
 // Doc prints the documentation comments associated with the item identified by its
 // arguments (a package, const, func, type, var, method, or struct field)
 //
 // Usage:
 //
-//     go get [-d] [-t] [-u] [-v] [-insecure] [build flags] [packages]
+//     go get [-d] [-t] [-u] [-v] [build flags] [packages]
 //
 // Get resolves its command-line arguments to packages at specific module versions,
 // updates go.mod to require those versions, downloads source code into the
 // When the -t and -u flags are used together, get will update
 // test dependencies as well.
 //
-// The -insecure flag permits fetching from repositories and resolving
-// custom domains using insecure schemes such as HTTP, and also bypassess
-// module sum validation using the checksum database. Use with caution.
-// This flag is deprecated and will be removed in a future version of go.
-// To permit the use of insecure schemes, use the GOINSECURE environment
-// variable instead. To bypass module sum validation, use GOPRIVATE or
-// GONOSUMDB. See 'go help environment' for details.
-//
 // The -d flag instructs get not to build or install packages. get will only
 // update go.mod and download source code needed to build packages.
 //
 //         UseAllFiles   bool     // use files regardless of +build lines, file names
 //         Compiler      string   // compiler to assume when computing target paths
 //         BuildTags     []string // build constraints to match in +build lines
+//         ToolTags      []string // toolchain-specific build constraints
 //         ReleaseTags   []string // releases the current release is compatible with
 //         InstallSuffix string   // suffix to use in the name of the install dir
 //     }
 //
 // Usage:
 //
-//     go mod edit [editing flags] [go.mod]
+//     go mod edit [editing flags] [-fmt|-print|-json] [go.mod]
 //
 // Edit provides a command-line interface for editing go.mod,
 // for use primarily by tools or scripts. It reads only go.mod;
 // writing it back to go.mod. The JSON output corresponds to these Go types:
 //
 //     type Module struct {
-//             Path string
+//             Path    string
 //             Version string
 //     }
 //
 //     type GoMod struct {
-//             Module  Module
+//             Module  ModPath
 //             Go      string
 //             Require []Require
 //             Exclude []Module
 //             Retract []Retract
 //     }
 //
+//     type ModPath struct {
+//             Path       string
+//             Deprecated string
+//     }
+//
 //     type Require struct {
 //             Path string
 //             Version string
 //
 // Usage:
 //
-//     go mod graph
+//     go mod graph [-go=version]
 //
 // Graph prints the module requirement graph (with replacements applied)
 // in text form. Each line in the output has two space-separated fields: a module
 // and one of its requirements. Each module is identified as a string of the form
 // path@version, except for the main module, which has no @version suffix.
 //
+// The -go flag causes graph to report the module graph as loaded by the
+// given Go version, instead of the version indicated by the 'go' directive
+// in the go.mod file.
+//
 // See https://golang.org/ref/mod#go-mod-graph for more about 'go mod graph'.
 //
 //
 //
 // Usage:
 //
-//     go mod init [module]
+//     go mod init [module-path]
 //
 // Init initializes and writes a new go.mod file in the current directory, in
 // effect creating a new module rooted at the current directory. The go.mod file
 //
 // Usage:
 //
-//     go mod tidy [-e] [-v]
+//     go mod tidy [-e] [-v] [-go=version] [-compat=version]
 //
 // Tidy makes sure go.mod matches the source code in the module.
 // It adds any missing modules necessary to build the current module's
 // The -e flag causes tidy to attempt to proceed despite errors
 // encountered while loading packages.
 //
+// The -go flag causes tidy to update the 'go' directive in the go.mod
+// file to the given version, which may change which module dependencies
+// are retained as explicit requirements in the go.mod file.
+// (Go versions 1.17 and higher retain more requirements in order to
+// support lazy module loading.)
+//
+// The -compat flag preserves any additional checksums needed for the
+// 'go' command from the indicated major Go release to successfully load
+// the module graph, and causes tidy to error out if that version of the
+// 'go' command would load any imported package from a different module
+// version. By default, tidy acts as if the -compat flag were set to the
+// version prior to the one indicated by the 'go' directive in the go.mod
+// file.
+//
 // See https://golang.org/ref/mod#go-mod-tidy for more about 'go mod tidy'.
 //
 //
 //     go run [build flags] [-exec xprog] package [arguments...]
 //
 // Run compiles and runs the named main Go package.
-// Typically the package is specified as a list of .go source files from a single directory,
-// but it may also be an import path, file system path, or pattern
+// Typically the package is specified as a list of .go source files from a single
+// directory, but it may also be an import path, file system path, or pattern
 // matching a single known package, as in 'go run .' or 'go run my/cmd'.
 //
+// If the package argument has a version suffix (like @latest or @v1.0.0),
+// "go run" builds the program in module-aware mode, ignoring the go.mod file in
+// the current directory or any parent directory, if there is one. This is useful
+// for running programs without affecting the dependencies of the main module.
+//
+// If the package argument doesn't have a version suffix, "go run" may run in
+// module-aware mode or GOPATH mode, depending on the GO111MODULE environment
+// variable and the presence of a go.mod file. See 'go help modules' for details.
+// If module-aware mode is enabled, "go run" runs in the context of the main
+// module.
+//
 // By default, 'go run' runs the compiled binary directly: 'a.out arguments...'.
 // If the -exec flag is given, 'go run' invokes the binary using xprog:
 //     'xprog a.out arguments...'.
 //
 // The rule for a match in the cache is that the run involves the same
 // test binary and the flags on the command line come entirely from a
-// restricted set of 'cacheable' test flags, defined as -cpu, -list,
-// -parallel, -run, -short, and -v. If a run of go test has any test
+// restricted set of 'cacheable' test flags, defined as -benchtime, -cpu,
+// -list, -parallel, -run, -short, and -v. If a run of go test has any test
 // or non-test flags outside this set, the result is not cached. To
 // disable test caching, use any test flag or argument other than the
 // cacheable flags. The idiomatic way to disable test caching explicitly
 //
 // A build constraint, also known as a build tag, is a line comment that begins
 //
-//     // +build
+//     //go:build
 //
 // that lists the conditions under which a file should be included in the package.
 // Constraints may appear in any kind of source file (not just Go), but
 // only by blank lines and other line comments. These rules mean that in Go
 // files a build constraint must appear before the package clause.
 //
-// To distinguish build constraints from package documentation, a series of
-// build constraints must be followed by a blank line.
-//
-// A build constraint is evaluated as the OR of space-separated options.
-// Each option evaluates as the AND of its comma-separated terms.
-// Each term consists of letters, digits, underscores, and dots.
-// A term may be negated with a preceding !.
-// For example, the build constraint:
-//
-//     // +build linux,386 darwin,!cgo
-//
-// corresponds to the boolean formula:
+// To distinguish build constraints from package documentation,
+// a build constraint should be followed by a blank line.
 //
-//     (linux AND 386) OR (darwin AND (NOT cgo))
+// A build constraint is evaluated as an expression containing options
+// combined by ||, &&, and ! operators and parentheses. Operators have
+// the same meaning as in Go.
 //
-// A file may have multiple build constraints. The overall constraint is the AND
-// of the individual constraints. That is, the build constraints:
+// For example, the following build constraint constrains a file to
+// build when the "linux" and "386" constraints are satisfied, or when
+// "darwin" is satisfied and "cgo" is not:
 //
-//     // +build linux darwin
-//     // +build amd64
+//     //go:build (linux && 386) || (darwin && !cgo)
 //
-// corresponds to the boolean formula:
-//
-//     (linux OR darwin) AND amd64
+// It is an error for a file to have more than one //go:build line.
 //
 // During a particular build, the following words are satisfied:
 //
 //
 // To keep a file from being considered for the build:
 //
-//     // +build ignore
+//     //go:build ignore
 //
 // (any other unsatisfied word will work as well, but "ignore" is conventional.)
 //
 // To build a file only when using cgo, and only on Linux and OS X:
 //
-//     // +build linux,cgo darwin,cgo
+//     //go:build cgo && (linux || darwin)
 //
 // Such a file is usually paired with another file implementing the
 // default functionality for other systems, which in this case would
 // carry the constraint:
 //
-//     // +build !linux,!darwin !cgo
+//     //go:build !(cgo && (linux || darwin))
 //
 // Naming a file dns_windows.go will cause it to be included only when
 // building the package for Windows; similarly, math_386.s will be included
 // only when building the package for 32-bit x86.
 //
+// Go versions 1.16 and earlier used a different syntax for build constraints,
+// with a "// +build" prefix. The gofmt command will add an equivalent //go:build
+// constraint when encountering the older syntax.
+//
 //
 // Build modes
 //
 //             Comma-separated list of glob patterns (in the syntax of Go's path.Match)
 //             of module path prefixes that should always be fetched in an insecure
 //             manner. Only applies to dependencies that are being fetched directly.
-//             Unlike the -insecure flag on 'go get', GOINSECURE does not disable
-//             checksum database validation. GOPRIVATE or GONOSUMDB may be used
-//             to achieve that.
+//             GOINSECURE does not disable checksum database validation. GOPRIVATE or
+//             GONOSUMDB may be used to achieve that.
 //     GOOS
 //             The operating system for which to compile code.
 //             Examples are linux, darwin, windows, netbsd.
 //     GOMIPS64
 //             For GOARCH=mips64{,le}, whether to use floating point instructions.
 //             Valid values are hardfloat (default), softfloat.
+//     GOPPC64
+//             For GOARCH=ppc64{,le}, the target ISA (Instruction Set Architecture).
+//             Valid values are power8 (default), power9.
 //     GOWASM
 //             For GOARCH=wasm, comma-separated list of experimental WebAssembly features to use.
 //             Valid values are satconv, signext.
 //     GCCGOTOOLDIR
 //             If set, where to find gccgo tools, such as cgo.
 //             The default is based on how gccgo was configured.
+//     GOEXPERIMENT
+//             Comma-separated list of toolchain experiments to enable or disable.
+//             The list of available experiments may change arbitrarily over time.
+//             See src/internal/goexperiment/flags.go for currently valid values.
+//             Warning: This variable is provided for the development and testing
+//             of the Go toolchain itself. Use beyond that purpose is unsupported.
 //     GOROOT_FINAL
 //             The root of the installed Go tree, when it is
 //             installed in a location other than where it is built.
 // The go.mod file format is described in detail at
 // https://golang.org/ref/mod#go-mod-file.
 //
-// To create a new go.mod file, use 'go help init'. For details see
+// To create a new go.mod file, use 'go mod init'. For details see
 // 'go help mod init' or https://golang.org/ref/mod#go-mod-init.
 //
 // To add missing module requirements or remove unneeded requirements,
 // This help text, accessible as 'go help gopath-get' even in module-aware mode,
 // describes 'go get' as it operates in legacy GOPATH mode.
 //
-// Usage: go get [-d] [-f] [-t] [-u] [-v] [-fix] [-insecure] [build flags] [packages]
+// Usage: go get [-d] [-f] [-t] [-u] [-v] [-fix] [build flags] [packages]
 //
 // Get downloads the packages named by the import paths, along with their
 // dependencies. It then installs the named packages, like 'go install'.
 // The -fix flag instructs get to run the fix tool on the downloaded packages
 // before resolving dependencies or building the code.
 //
-// The -insecure flag permits fetching from repositories and resolving
-// custom domains using insecure schemes such as HTTP. Use with caution.
-// This flag is deprecated and will be removed in a future version of go.
-// The GOINSECURE environment variable should be used instead, since it
-// provides control over which packages may be retrieved using an insecure
-// scheme. See 'go help environment' for details.
-//
 // The -t flag instructs get to also download the packages required to build
 // the tests for the specified packages.
 //
 // will result in the following requests:
 //
 //     https://example.org/pkg/foo?go-get=1 (preferred)
-//     http://example.org/pkg/foo?go-get=1  (fallback, only with -insecure)
+//     http://example.org/pkg/foo?go-get=1  (fallback, only with use of correctly set GOINSECURE)
 //
 // If that page contains the meta tag
 //
 //         the Go tree can run a sanity check but not spend time running
 //         exhaustive tests.
 //
+//     -shuffle off,on,N
+//             Randomize the execution order of tests and benchmarks.
+//             It is off by default. If -shuffle is set to on, then it will seed
+//             the randomizer using the system clock. If -shuffle is set to an
+//             integer N, then N will be used as the seed value. In both cases,
+//             the seed will be reported for reproducibility.
+//
 //     -timeout d
 //         If a test binary runs longer than duration d, panic.
 //         If d is 0, the timeout is disabled.
index 7e383f4b5b0e73578b623f4d07c93ef6747ebef7..a1f2727825ede1f1ead32d3e240311206a186ed5 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build go1.1
 // +build go1.1
 
 package main
index 3ce32388d05dd8785ed94e074b4dc1ef47a2c128..6ce276537babd88765937e1f7ec0f3c98cc5ac68 100644 (file)
@@ -72,7 +72,6 @@ func tooSlow(t *testing.T) {
 // (temp) directory.
 var testGOROOT string
 
-var testCC string
 var testGOCACHE string
 
 var testGo string
@@ -179,13 +178,6 @@ func TestMain(m *testing.M) {
                        os.Exit(2)
                }
 
-               out, err = exec.Command(gotool, "env", "CC").CombinedOutput()
-               if err != nil {
-                       fmt.Fprintf(os.Stderr, "could not find testing CC: %v\n%s", err, out)
-                       os.Exit(2)
-               }
-               testCC = strings.TrimSpace(string(out))
-
                cmd := exec.Command(testGo, "env", "CGO_ENABLED")
                cmd.Stderr = new(strings.Builder)
                if out, err := cmd.Output(); err != nil {
@@ -811,8 +803,10 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
        // so that we can change files.
        for _, copydir := range []string{
                "src/runtime",
+               "src/internal/abi",
                "src/internal/bytealg",
                "src/internal/cpu",
+               "src/internal/goexperiment",
                "src/math/bits",
                "src/unsafe",
                filepath.Join("pkg", runtime.GOOS+"_"+runtime.GOARCH),
@@ -2183,7 +2177,7 @@ func testBuildmodePIE(t *testing.T, useCgo, setBuildmodeToPIE bool) {
                        // See https://sourceware.org/bugzilla/show_bug.cgi?id=19011
                        section := f.Section(".edata")
                        if section == nil {
-                               t.Fatalf(".edata section is not present")
+                               t.Skip(".edata section is not present")
                        }
                        // TODO: deduplicate this struct from cmd/link/internal/ld/pe.go
                        type IMAGE_EXPORT_DIRECTORY struct {
@@ -2830,3 +2824,59 @@ func TestCoverpkgTestOnly(t *testing.T) {
        tg.grepStderrNot("no packages being tested depend on matches", "bad match message")
        tg.grepStdout("coverage: 100", "no coverage")
 }
+
+// Regression test for golang.org/issue/34499: version command should not crash
+// when executed in a deleted directory on Linux.
+func TestExecInDeletedDir(t *testing.T) {
+       switch runtime.GOOS {
+       case "windows", "plan9",
+               "aix",                // Fails with "device busy".
+               "solaris", "illumos": // Fails with "invalid argument".
+               t.Skipf("%v does not support removing the current working directory", runtime.GOOS)
+       }
+       tg := testgo(t)
+       defer tg.cleanup()
+
+       wd, err := os.Getwd()
+       tg.check(err)
+       tg.makeTempdir()
+       tg.check(os.Chdir(tg.tempdir))
+       defer func() { tg.check(os.Chdir(wd)) }()
+
+       tg.check(os.Remove(tg.tempdir))
+
+       // `go version` should not fail
+       tg.run("version")
+}
+
+// A missing C compiler should not force the net package to be stale.
+// Issue 47215.
+func TestMissingCC(t *testing.T) {
+       if !canCgo {
+               t.Skip("test is only meaningful on systems with cgo")
+       }
+       cc := os.Getenv("CC")
+       if cc == "" {
+               cc = "gcc"
+       }
+       if filepath.IsAbs(cc) {
+               t.Skipf(`"CC" (%s) is an absolute path`, cc)
+       }
+       _, err := exec.LookPath(cc)
+       if err != nil {
+               t.Skipf(`"CC" (%s) not on PATH`, cc)
+       }
+
+       tg := testgo(t)
+       defer tg.cleanup()
+       netStale, _ := tg.isStale("net")
+       if netStale {
+               t.Skip(`skipping test because "net" package is currently stale`)
+       }
+
+       tg.setenv("PATH", "") // No C compiler on PATH.
+       netStale, _ = tg.isStale("net")
+       if netStale {
+               t.Error(`clearing "PATH" causes "net" to be stale`)
+       }
+}
index 030ef793aabfb85eefb0586456ed2abdd00347e0..db992b78914923fba18e6aeacacaa09e1364aa29 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package main_test
index 7a51181c9736e9cdf8549a7192f9bdcf67f419ce..4d8715ef5fe002a349d83e956eb4493e9c698fe0 100644 (file)
@@ -8,21 +8,27 @@ import (
        "os"
        "path/filepath"
        "strings"
+       "sync"
 )
 
-func getwd() string {
-       wd, err := os.Getwd()
-       if err != nil {
-               Fatalf("cannot determine current directory: %v", err)
-       }
-       return wd
-}
+var cwd string
+var cwdOnce sync.Once
 
-var Cwd = getwd()
+// Cwd returns the current working directory at the time of the first call.
+func Cwd() string {
+       cwdOnce.Do(func() {
+               var err error
+               cwd, err = os.Getwd()
+               if err != nil {
+                       Fatalf("cannot determine current directory: %v", err)
+               }
+       })
+       return cwd
+}
 
 // ShortPath returns an absolute or relative name for path, whatever is shorter.
 func ShortPath(path string) string {
-       if rel, err := filepath.Rel(Cwd, path); err == nil && len(rel) < len(path) {
+       if rel, err := filepath.Rel(Cwd(), path); err == nil && len(rel) < len(path) {
                return rel
        }
        return path
@@ -32,10 +38,8 @@ func ShortPath(path string) string {
 // made relative to the current directory if they would be shorter.
 func RelPaths(paths []string) []string {
        var out []string
-       // TODO(rsc): Can this use Cwd from above?
-       pwd, _ := os.Getwd()
        for _, p := range paths {
-               rel, err := filepath.Rel(pwd, p)
+               rel, err := filepath.Rel(Cwd(), p)
                if err == nil && len(rel) < len(p) {
                        p = rel
                }
index 9e869b03ea8aafa10c288abfc2771b7c9616d2cd..5cc0b0f1011e5a1a0c2ff3a0eb256960d90deb7c 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build plan9 || windows
 // +build plan9 windows
 
 package base
index 2b1507be27cb982c9c91695f504077241b768304..cdb25934c2de2c8389b356ca2b78fe8689b82bc8 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || js || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd js linux netbsd openbsd solaris
 
 package base
index 4aa08b4ff6ea7ab988daa86f3243b12948f0b64f..307527c695cbededab0ae1dfa4447e2fc3161c4b 100644 (file)
@@ -20,6 +20,7 @@ import (
 
        "cmd/go/internal/base"
        "cmd/go/internal/cfg"
+       "cmd/go/internal/envcmd"
        "cmd/go/internal/web"
 )
 
@@ -81,7 +82,7 @@ func printGoVersion(w io.Writer) {
        fmt.Fprintf(w, "### What version of Go are you using (`go version`)?\n\n")
        fmt.Fprintf(w, "<pre>\n")
        fmt.Fprintf(w, "$ go version\n")
-       printCmdOut(w, "", "go", "version")
+       fmt.Fprintf(w, "go version %s %s/%s\n", runtime.Version(), runtime.GOOS, runtime.GOARCH)
        fmt.Fprintf(w, "</pre>\n")
        fmt.Fprintf(w, "\n")
 }
@@ -90,13 +91,20 @@ func printEnvDetails(w io.Writer) {
        fmt.Fprintf(w, "### What operating system and processor architecture are you using (`go env`)?\n\n")
        fmt.Fprintf(w, "<details><summary><code>go env</code> Output</summary><br><pre>\n")
        fmt.Fprintf(w, "$ go env\n")
-       printCmdOut(w, "", "go", "env")
+       printGoEnv(w)
        printGoDetails(w)
        printOSDetails(w)
        printCDetails(w)
        fmt.Fprintf(w, "</pre></details>\n\n")
 }
 
+func printGoEnv(w io.Writer) {
+       env := envcmd.MkEnv()
+       env = append(env, envcmd.ExtraEnvVars()...)
+       env = append(env, envcmd.ExtraEnvVarsCostly()...)
+       envcmd.PrintEnv(w, env)
+}
+
 func printGoDetails(w io.Writer) {
        printCmdOut(w, "GOROOT/bin/go version: ", filepath.Join(runtime.GOROOT(), "bin/go"), "version")
        printCmdOut(w, "GOROOT/bin/go tool compile -V: ", filepath.Join(runtime.GOROOT(), "bin/go"), "tool", "compile", "-V")
index 41f921641d499744a2a88224355333c4f76d2693..d592d7049786ce9d3fd5d15a67f2884327f149a0 100644 (file)
@@ -19,7 +19,7 @@ import (
        "strings"
        "time"
 
-       "cmd/go/internal/renameio"
+       "cmd/go/internal/lockedfile"
 )
 
 // An ActionID is a cache action key, the hash of a complete description of a
@@ -294,10 +294,17 @@ func (c *Cache) Trim() {
        // We maintain in dir/trim.txt the time of the last completed cache trim.
        // If the cache has been trimmed recently enough, do nothing.
        // This is the common case.
-       data, _ := renameio.ReadFile(filepath.Join(c.dir, "trim.txt"))
-       t, err := strconv.ParseInt(strings.TrimSpace(string(data)), 10, 64)
-       if err == nil && now.Sub(time.Unix(t, 0)) < trimInterval {
-               return
+       // If the trim file is corrupt, detected if the file can't be parsed, or the
+       // trim time is too far in the future, attempt the trim anyway. It's possible that
+       // the cache was full when the corruption happened. Attempting a trim on
+       // an empty cache is cheap, so there wouldn't be a big performance hit in that case.
+       if data, err := lockedfile.Read(filepath.Join(c.dir, "trim.txt")); err == nil {
+               if t, err := strconv.ParseInt(strings.TrimSpace(string(data)), 10, 64); err == nil {
+                       lastTrim := time.Unix(t, 0)
+                       if d := now.Sub(lastTrim); d < trimInterval && d > -mtimeInterval {
+                               return
+                       }
+               }
        }
 
        // Trim each of the 256 subdirectories.
@@ -311,7 +318,11 @@ func (c *Cache) Trim() {
 
        // Ignore errors from here: if we don't write the complete timestamp, the
        // cache will appear older than it is, and we'll trim it again next time.
-       renameio.WriteFile(filepath.Join(c.dir, "trim.txt"), []byte(fmt.Sprintf("%d", now.Unix())), 0666)
+       var b bytes.Buffer
+       fmt.Fprintf(&b, "%d", now.Unix())
+       if err := lockedfile.Write(filepath.Join(c.dir, "trim.txt"), &b, 0666); err != nil {
+               return
+       }
 }
 
 // trimSubdir trims a single cache subdirectory.
index e4bb2a34bb4a1a371193864fb8b24139b52bd16c..4f79c3150024492db1572271c08ffb1a3eeca082 100644 (file)
@@ -12,6 +12,7 @@ import (
        "io"
        "os"
        "runtime"
+       "strings"
        "sync"
 )
 
@@ -36,7 +37,22 @@ type Hash struct {
 // of other versions. This salt will result in additional ActionID files
 // in the cache, but not additional copies of the large output files,
 // which are still addressed by unsalted SHA256.
-var hashSalt = []byte(runtime.Version())
+//
+// We strip any GOEXPERIMENTs the go tool was built with from this
+// version string on the assumption that they shouldn't affect go tool
+// execution. This allows bootstrapping to converge faster: dist builds
+// go_bootstrap without any experiments, so by stripping experiments
+// go_bootstrap and the final go binary will use the same salt.
+var hashSalt = []byte(stripExperiment(runtime.Version()))
+
+// stripExperiment strips any GOEXPERIMENT configuration from the Go
+// version string.
+func stripExperiment(version string) string {
+       if i := strings.Index(version, " X:"); i >= 0 {
+               return version[:i]
+       }
+       return version
+}
 
 // Subkey returns an action ID corresponding to mixing a parent
 // action ID with a string description of the subkey.
index c48904eacceab90949bc12248ad82b91803a16ca..57a3c1ff6fbdc1f9f29a10a4580e8d40e4f8c908 100644 (file)
@@ -10,6 +10,7 @@ import (
        "bytes"
        "fmt"
        "go/build"
+       "internal/buildcfg"
        "internal/cfg"
        "io"
        "os"
@@ -19,8 +20,6 @@ import (
        "sync"
 
        "cmd/go/internal/fsys"
-
-       "cmd/internal/objabi"
 )
 
 // These are general "build flags" used by build and other commands.
@@ -28,18 +27,18 @@ var (
        BuildA                 bool   // -a flag
        BuildBuildmode         string // -buildmode flag
        BuildContext           = defaultContext()
-       BuildMod               string             // -mod flag
-       BuildModExplicit       bool               // whether -mod was set explicitly
-       BuildModReason         string             // reason -mod was set, if set by default
-       BuildI                 bool               // -i flag
-       BuildLinkshared        bool               // -linkshared flag
-       BuildMSan              bool               // -msan flag
-       BuildN                 bool               // -n flag
-       BuildO                 string             // -o flag
-       BuildP                 = runtime.NumCPU() // -p flag
-       BuildPkgdir            string             // -pkgdir flag
-       BuildRace              bool               // -race flag
-       BuildToolexec          []string           // -toolexec flag
+       BuildMod               string                  // -mod flag
+       BuildModExplicit       bool                    // whether -mod was set explicitly
+       BuildModReason         string                  // reason -mod was set, if set by default
+       BuildI                 bool                    // -i flag
+       BuildLinkshared        bool                    // -linkshared flag
+       BuildMSan              bool                    // -msan flag
+       BuildN                 bool                    // -n flag
+       BuildO                 string                  // -o flag
+       BuildP                 = runtime.GOMAXPROCS(0) // -p flag
+       BuildPkgdir            string                  // -pkgdir flag
+       BuildRace              bool                    // -race flag
+       BuildToolexec          []string                // -toolexec flag
        BuildToolchainName     string
        BuildToolchainCompiler func() string
        BuildToolchainLinker   func() string
@@ -51,8 +50,6 @@ var (
        ModCacheRW bool   // -modcacherw flag
        ModFile    string // -modfile flag
 
-       Insecure bool // -insecure flag
-
        CmdName string // "build", "install", "list", "mod tidy", etc.
 
        DebugActiongraph string // -debug-actiongraph flag (undocumented, unstable)
@@ -80,6 +77,14 @@ func defaultContext() build.Context {
        ctxt.GOOS = envOr("GOOS", ctxt.GOOS)
        ctxt.GOARCH = envOr("GOARCH", ctxt.GOARCH)
 
+       // The experiments flags are based on GOARCH, so they may
+       // need to change.  TODO: This should be cleaned up.
+       buildcfg.UpdateExperiments(ctxt.GOOS, ctxt.GOARCH, envOr("GOEXPERIMENT", buildcfg.DefaultGOEXPERIMENT))
+       ctxt.ToolTags = nil
+       for _, exp := range buildcfg.EnabledExperiments() {
+               ctxt.ToolTags = append(ctxt.ToolTags, "goexperiment."+exp)
+       }
+
        // The go/build rule for whether cgo is enabled is:
        //      1. If $CGO_ENABLED is set, respect it.
        //      2. Otherwise, if this is a cross-compile, disable cgo.
@@ -254,12 +259,12 @@ var (
        GOMODCACHE   = envOr("GOMODCACHE", gopathDir("pkg/mod"))
 
        // Used in envcmd.MkEnv and build ID computations.
-       GOARM    = envOr("GOARM", fmt.Sprint(objabi.GOARM))
-       GO386    = envOr("GO386", objabi.GO386)
-       GOMIPS   = envOr("GOMIPS", objabi.GOMIPS)
-       GOMIPS64 = envOr("GOMIPS64", objabi.GOMIPS64)
-       GOPPC64  = envOr("GOPPC64", fmt.Sprintf("%s%d", "power", objabi.GOPPC64))
-       GOWASM   = envOr("GOWASM", fmt.Sprint(objabi.GOWASM))
+       GOARM    = envOr("GOARM", fmt.Sprint(buildcfg.GOARM))
+       GO386    = envOr("GO386", buildcfg.GO386)
+       GOMIPS   = envOr("GOMIPS", buildcfg.GOMIPS)
+       GOMIPS64 = envOr("GOMIPS64", buildcfg.GOMIPS64)
+       GOPPC64  = envOr("GOPPC64", fmt.Sprintf("%s%d", "power", buildcfg.GOPPC64))
+       GOWASM   = envOr("GOWASM", fmt.Sprint(buildcfg.GOWASM))
 
        GOPROXY    = envOr("GOPROXY", "https://proxy.golang.org,direct")
        GOSUMDB    = envOr("GOSUMDB", "sum.golang.org")
index b1d40feb273b89d6604747ff8e2de6949572221a..fd4cb205591105d0ad527e25e811cd62dfadf5a8 100644 (file)
@@ -117,7 +117,7 @@ func runClean(ctx context.Context, cmd *base.Command, args []string) {
        }
 
        if cleanPkg {
-               for _, pkg := range load.PackagesAndErrors(ctx, args) {
+               for _, pkg := range load.PackagesAndErrors(ctx, load.PackageOpts{}, args) {
                        clean(pkg)
                }
        }
index 67f76e22563b6e84d21b7622b55675d03af60db2..8580a5dc4d2482a7e2f88640abe9a76a245adb18 100644 (file)
@@ -13,7 +13,7 @@ import (
 
 var CmdDoc = &base.Command{
        Run:         runDoc,
-       UsageLine:   "go doc [-u] [-c] [package|[package.]symbol[.methodOrField]]",
+       UsageLine:   "go doc [doc flags] [package|[package.]symbol[.methodOrField]]",
        CustomFlags: true,
        Short:       "show documentation for package or symbol",
        Long: `
index 6937187522bd237fbefac0c13727754af40fcb86..1553d263914541f05a639e03b8041969ba244301 100644 (file)
@@ -10,6 +10,8 @@ import (
        "encoding/json"
        "fmt"
        "go/build"
+       "internal/buildcfg"
+       "io"
        "os"
        "path/filepath"
        "runtime"
@@ -71,6 +73,7 @@ func MkEnv() []cfg.EnvVar {
                {Name: "GOCACHE", Value: cache.DefaultDir()},
                {Name: "GOENV", Value: envFile},
                {Name: "GOEXE", Value: cfg.ExeSuffix},
+               {Name: "GOEXPERIMENT", Value: buildcfg.GOEXPERIMENT()},
                {Name: "GOFLAGS", Value: cfg.Getenv("GOFLAGS")},
                {Name: "GOHOSTARCH", Value: runtime.GOARCH},
                {Name: "GOHOSTOS", Value: runtime.GOOS},
@@ -196,23 +199,31 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) {
        if *envU && *envW {
                base.Fatalf("go env: cannot use -u with -w")
        }
+
+       // Handle 'go env -w' and 'go env -u' before calling buildcfg.Check,
+       // so they can be used to recover from an invalid configuration.
+       if *envW {
+               runEnvW(args)
+               return
+       }
+
+       if *envU {
+               runEnvU(args)
+               return
+       }
+
+       buildcfg.Check()
+
        env := cfg.CmdEnv
        env = append(env, ExtraEnvVars()...)
 
-       if err := fsys.Init(base.Cwd); err != nil {
+       if err := fsys.Init(base.Cwd()); err != nil {
                base.Fatalf("go: %v", err)
        }
 
        // Do we need to call ExtraEnvVarsCostly, which is a bit expensive?
        needCostly := false
-       if *envU || *envW {
-               // We're overwriting or removing default settings,
-               // so it doesn't really matter what the existing settings are.
-               //
-               // Moreover, we haven't validated the new settings yet, so it is
-               // important that we NOT perform any actions based on them,
-               // such as initializing the builder to compute other variables.
-       } else if len(args) == 0 {
+       if len(args) == 0 {
                // We're listing all environment variables ("go env"),
                // including the expensive ones.
                needCostly = true
@@ -237,95 +248,6 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) {
                env = append(env, ExtraEnvVarsCostly()...)
        }
 
-       if *envW {
-               // Process and sanity-check command line.
-               if len(args) == 0 {
-                       base.Fatalf("go env -w: no KEY=VALUE arguments given")
-               }
-               osEnv := make(map[string]string)
-               for _, e := range cfg.OrigEnv {
-                       if i := strings.Index(e, "="); i >= 0 {
-                               osEnv[e[:i]] = e[i+1:]
-                       }
-               }
-               add := make(map[string]string)
-               for _, arg := range args {
-                       i := strings.Index(arg, "=")
-                       if i < 0 {
-                               base.Fatalf("go env -w: arguments must be KEY=VALUE: invalid argument: %s", arg)
-                       }
-                       key, val := arg[:i], arg[i+1:]
-                       if err := checkEnvWrite(key, val); err != nil {
-                               base.Fatalf("go env -w: %v", err)
-                       }
-                       if _, ok := add[key]; ok {
-                               base.Fatalf("go env -w: multiple values for key: %s", key)
-                       }
-                       add[key] = val
-                       if osVal := osEnv[key]; osVal != "" && osVal != val {
-                               fmt.Fprintf(os.Stderr, "warning: go env -w %s=... does not override conflicting OS environment variable\n", key)
-                       }
-               }
-
-               goos, okGOOS := add["GOOS"]
-               goarch, okGOARCH := add["GOARCH"]
-               if okGOOS || okGOARCH {
-                       if !okGOOS {
-                               goos = cfg.Goos
-                       }
-                       if !okGOARCH {
-                               goarch = cfg.Goarch
-                       }
-                       if err := work.CheckGOOSARCHPair(goos, goarch); err != nil {
-                               base.Fatalf("go env -w: %v", err)
-                       }
-               }
-
-               gotmp, okGOTMP := add["GOTMPDIR"]
-               if okGOTMP {
-                       if !filepath.IsAbs(gotmp) && gotmp != "" {
-                               base.Fatalf("go env -w: GOTMPDIR must be an absolute path")
-                       }
-               }
-
-               updateEnvFile(add, nil)
-               return
-       }
-
-       if *envU {
-               // Process and sanity-check command line.
-               if len(args) == 0 {
-                       base.Fatalf("go env -u: no arguments given")
-               }
-               del := make(map[string]bool)
-               for _, arg := range args {
-                       if err := checkEnvWrite(arg, ""); err != nil {
-                               base.Fatalf("go env -u: %v", err)
-                       }
-                       del[arg] = true
-               }
-               if del["GOOS"] || del["GOARCH"] {
-                       goos, goarch := cfg.Goos, cfg.Goarch
-                       if del["GOOS"] {
-                               goos = getOrigEnv("GOOS")
-                               if goos == "" {
-                                       goos = build.Default.GOOS
-                               }
-                       }
-                       if del["GOARCH"] {
-                               goarch = getOrigEnv("GOARCH")
-                               if goarch == "" {
-                                       goarch = build.Default.GOARCH
-                               }
-                       }
-                       if err := work.CheckGOOSARCHPair(goos, goarch); err != nil {
-                               base.Fatalf("go env -u: %v", err)
-                       }
-               }
-               updateEnvFile(nil, del)
-               return
-       }
-
        if len(args) > 0 {
                if *envJson {
                        var es []cfg.EnvVar
@@ -347,27 +269,135 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) {
                return
        }
 
+       PrintEnv(os.Stdout, env)
+}
+
+func runEnvW(args []string) {
+       // Process and sanity-check command line.
+       if len(args) == 0 {
+               base.Fatalf("go env -w: no KEY=VALUE arguments given")
+       }
+       osEnv := make(map[string]string)
+       for _, e := range cfg.OrigEnv {
+               if i := strings.Index(e, "="); i >= 0 {
+                       osEnv[e[:i]] = e[i+1:]
+               }
+       }
+       add := make(map[string]string)
+       for _, arg := range args {
+               i := strings.Index(arg, "=")
+               if i < 0 {
+                       base.Fatalf("go env -w: arguments must be KEY=VALUE: invalid argument: %s", arg)
+               }
+               key, val := arg[:i], arg[i+1:]
+               if err := checkEnvWrite(key, val); err != nil {
+                       base.Fatalf("go env -w: %v", err)
+               }
+               if _, ok := add[key]; ok {
+                       base.Fatalf("go env -w: multiple values for key: %s", key)
+               }
+               add[key] = val
+               if osVal := osEnv[key]; osVal != "" && osVal != val {
+                       fmt.Fprintf(os.Stderr, "warning: go env -w %s=... does not override conflicting OS environment variable\n", key)
+               }
+       }
+
+       if err := checkBuildConfig(add, nil); err != nil {
+               base.Fatalf("go env -w: %v", err)
+       }
+
+       gotmp, okGOTMP := add["GOTMPDIR"]
+       if okGOTMP {
+               if !filepath.IsAbs(gotmp) && gotmp != "" {
+                       base.Fatalf("go env -w: GOTMPDIR must be an absolute path")
+               }
+       }
+
+       updateEnvFile(add, nil)
+}
+
+func runEnvU(args []string) {
+       // Process and sanity-check command line.
+       if len(args) == 0 {
+               base.Fatalf("go env -u: no arguments given")
+       }
+       del := make(map[string]bool)
+       for _, arg := range args {
+               if err := checkEnvWrite(arg, ""); err != nil {
+                       base.Fatalf("go env -u: %v", err)
+               }
+               del[arg] = true
+       }
+
+       if err := checkBuildConfig(nil, del); err != nil {
+               base.Fatalf("go env -u: %v", err)
+       }
+
+       updateEnvFile(nil, del)
+}
+
+// checkBuildConfig checks whether the build configuration is valid
+// after the specified configuration environment changes are applied.
+func checkBuildConfig(add map[string]string, del map[string]bool) error {
+       // get returns the value for key after applying add and del and
+       // reports whether it changed. cur should be the current value
+       // (i.e., before applying changes) and def should be the default
+       // value (i.e., when no environment variables are provided at all).
+       get := func(key, cur, def string) (string, bool) {
+               if val, ok := add[key]; ok {
+                       return val, true
+               }
+               if del[key] {
+                       val := getOrigEnv(key)
+                       if val == "" {
+                               val = def
+                       }
+                       return val, true
+               }
+               return cur, false
+       }
+
+       goos, okGOOS := get("GOOS", cfg.Goos, build.Default.GOOS)
+       goarch, okGOARCH := get("GOARCH", cfg.Goarch, build.Default.GOARCH)
+       if okGOOS || okGOARCH {
+               if err := work.CheckGOOSARCHPair(goos, goarch); err != nil {
+                       return err
+               }
+       }
+
+       goexperiment, okGOEXPERIMENT := get("GOEXPERIMENT", buildcfg.GOEXPERIMENT(), "")
+       if okGOEXPERIMENT {
+               if _, _, err := buildcfg.ParseGOEXPERIMENT(goos, goarch, goexperiment); err != nil {
+                       return err
+               }
+       }
+
+       return nil
+}
+
+// PrintEnv prints the environment variables to w.
+func PrintEnv(w io.Writer, env []cfg.EnvVar) {
        for _, e := range env {
                if e.Name != "TERM" {
                        switch runtime.GOOS {
                        default:
-                               fmt.Printf("%s=\"%s\"\n", e.Name, e.Value)
+                               fmt.Fprintf(w, "%s=\"%s\"\n", e.Name, e.Value)
                        case "plan9":
                                if strings.IndexByte(e.Value, '\x00') < 0 {
-                                       fmt.Printf("%s='%s'\n", e.Name, strings.ReplaceAll(e.Value, "'", "''"))
+                                       fmt.Fprintf(w, "%s='%s'\n", e.Name, strings.ReplaceAll(e.Value, "'", "''"))
                                } else {
                                        v := strings.Split(e.Value, "\x00")
-                                       fmt.Printf("%s=(", e.Name)
+                                       fmt.Fprintf(w, "%s=(", e.Name)
                                        for x, s := range v {
                                                if x > 0 {
-                                                       fmt.Printf(" ")
+                                                       fmt.Fprintf(w, " ")
                                                }
-                                               fmt.Printf("%s", s)
+                                               fmt.Fprintf(w, "%s", s)
                                        }
-                                       fmt.Printf(")\n")
+                                       fmt.Fprintf(w, ")\n")
                                }
                        case "windows":
-                               fmt.Printf("set %s=%s\n", e.Name, e.Value)
+                               fmt.Fprintf(w, "set %s=%s\n", e.Name, e.Value)
                        }
                }
        }
@@ -428,7 +458,7 @@ func checkEnvWrite(key, val string) error {
                        return fmt.Errorf("GOPATH entry is relative; must be absolute path: %q", val)
                }
        // Make sure CC and CXX are absolute paths
-       case "CC", "CXX":
+       case "CC", "CXX", "GOMODCACHE":
                if !filepath.IsAbs(val) && val != "" && val != filepath.Base(val) {
                        return fmt.Errorf("%s entry is relative; must be absolute path: %q", key, val)
                }
index c7588c66d3ebcc56bab6f83ad91c0f85e9c15d29..988d45e71ccfe2ccf571e409962bdd3ade4e3430 100644 (file)
@@ -33,7 +33,7 @@ See also: go fmt, go vet.
 }
 
 func runFix(ctx context.Context, cmd *base.Command, args []string) {
-       pkgs := load.PackagesAndErrors(ctx, args)
+       pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{}, args)
        w := 0
        for _, pkg := range pkgs {
                if pkg.Error != nil {
index 6b98f0ccd31865c937def4ac99b22597ca2b52e3..8a040087539e8f9195c61a88d89883a379a963b2 100644 (file)
@@ -65,7 +65,7 @@ func runFmt(ctx context.Context, cmd *base.Command, args []string) {
                        }
                }()
        }
-       for _, pkg := range load.PackagesAndErrors(ctx, args) {
+       for _, pkg := range load.PackagesAndErrors(ctx, load.PackageOpts{}, args) {
                if modload.Enabled() && pkg.Module != nil && !pkg.Module.Main {
                        if !printed {
                                fmt.Fprintf(os.Stderr, "go: not formatting packages in dependency modules\n")
index 7b06c3c7f3a0118614d39d25a1f91af65d263966..0b806027e6469a3cac3b19e2e5e162b7ead8e92d 100644 (file)
@@ -44,7 +44,7 @@ func (n *node) isDeleted() bool {
 
 // TODO(matloob): encapsulate these in an io/fs-like interface
 var overlay map[string]*node // path -> file or directory node
-var cwd string               // copy of base.Cwd to avoid dependency
+var cwd string               // copy of base.Cwd() to avoid dependency
 
 // Canonicalize a path for looking it up in the overlay.
 // Important: filepath.Join(cwd, path) doesn't always produce
@@ -100,7 +100,7 @@ func Init(wd string) error {
 }
 
 func initFromJSON(overlayJSON OverlayJSON) error {
-       // Canonicalize the paths in in the overlay map.
+       // Canonicalize the paths in the overlay map.
        // Use reverseCanonicalized to check for collisions:
        // no two 'from' paths should canonicalize to the same path.
        overlay = make(map[string]*node)
index a48311d51b09b7a2a356e1e567abfcaa1af60b7b..80ea32b4284011712eb82b2bd671e4f5f9a35b2e 100644 (file)
@@ -161,8 +161,6 @@ func init() {
 }
 
 func runGenerate(ctx context.Context, cmd *base.Command, args []string) {
-       load.IgnoreImports = true
-
        if generateRunFlag != "" {
                var err error
                generateRunRE, err = regexp.Compile(generateRunFlag)
@@ -175,7 +173,8 @@ func runGenerate(ctx context.Context, cmd *base.Command, args []string) {
 
        // Even if the arguments are .go files, this loop suffices.
        printed := false
-       for _, pkg := range load.PackagesAndErrors(ctx, args) {
+       pkgOpts := load.PackageOpts{IgnoreImports: true}
+       for _, pkg := range load.PackagesAndErrors(ctx, pkgOpts, args) {
                if modload.Enabled() && pkg.Module != nil && !pkg.Module.Main {
                        if !printed {
                                fmt.Fprintf(os.Stderr, "go: not generating in packages in dependency modules\n")
@@ -334,6 +333,7 @@ func (g *Generator) setEnv() {
                "GOPACKAGE=" + g.pkg,
                "DOLLAR=" + "$",
        }
+       g.env = base.AppendPWD(g.env, g.dir)
 }
 
 // split breaks the line into words, evaluating quoted
index 329a2f5eda48175bac1ef07742e7511adba1eb07..3c16dc3040facba13a7a59416268ae7944250599 100644 (file)
@@ -26,7 +26,7 @@ import (
 )
 
 var CmdGet = &base.Command{
-       UsageLine: "go get [-d] [-f] [-t] [-u] [-v] [-fix] [-insecure] [build flags] [packages]",
+       UsageLine: "go get [-d] [-f] [-t] [-u] [-v] [-fix] [build flags] [packages]",
        Short:     "download and install packages and dependencies",
        Long: `
 Get downloads the packages named by the import paths, along with their
@@ -43,13 +43,6 @@ of the original.
 The -fix flag instructs get to run the fix tool on the downloaded packages
 before resolving dependencies or building the code.
 
-The -insecure flag permits fetching from repositories and resolving
-custom domains using insecure schemes such as HTTP. Use with caution.
-This flag is deprecated and will be removed in a future version of go.
-The GOINSECURE environment variable should be used instead, since it
-provides control over which packages may be retrieved using an insecure
-scheme. See 'go help environment' for details.
-
 The -t flag instructs get to also download the packages required to build
 the tests for the specified packages.
 
@@ -105,17 +98,17 @@ Usage: ` + CmdGet.UsageLine + `
 }
 
 var (
-       getD   = CmdGet.Flag.Bool("d", false, "")
-       getF   = CmdGet.Flag.Bool("f", false, "")
-       getT   = CmdGet.Flag.Bool("t", false, "")
-       getU   = CmdGet.Flag.Bool("u", false, "")
-       getFix = CmdGet.Flag.Bool("fix", false, "")
+       getD        = CmdGet.Flag.Bool("d", false, "")
+       getF        = CmdGet.Flag.Bool("f", false, "")
+       getT        = CmdGet.Flag.Bool("t", false, "")
+       getU        = CmdGet.Flag.Bool("u", false, "")
+       getFix      = CmdGet.Flag.Bool("fix", false, "")
+       getInsecure = CmdGet.Flag.Bool("insecure", false, "")
 )
 
 func init() {
        work.AddBuildFlags(CmdGet, work.OmitModFlag|work.OmitModCommonFlags)
        CmdGet.Run = runGet // break init loop
-       CmdGet.Flag.BoolVar(&cfg.Insecure, "insecure", cfg.Insecure, "")
 }
 
 func runGet(ctx context.Context, cmd *base.Command, args []string) {
@@ -129,11 +122,11 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) {
        if *getF && !*getU {
                base.Fatalf("go get: cannot use -f flag without -u")
        }
-       if cfg.Insecure {
-               fmt.Fprintf(os.Stderr, "go get: -insecure flag is deprecated; see 'go help get' for details\n")
+       if *getInsecure {
+               base.Fatalf("go get: -insecure flag is no longer supported; use GOINSECURE instead")
        }
 
-       // Disable any prompting for passwords by Git.
+       // Disable any prompting for passwords by Git itself.
        // Only has an effect for 2.3.0 or later, but avoiding
        // the prompt in earlier versions is just too hard.
        // If user has explicitly set GIT_TERMINAL_PROMPT=1, keep
@@ -143,7 +136,10 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) {
                os.Setenv("GIT_TERMINAL_PROMPT", "0")
        }
 
-       // Disable any ssh connection pooling by Git.
+       // Also disable prompting for passwords by the 'ssh' subprocess spawned by
+       // Git, because apparently GIT_TERMINAL_PROMPT isn't sufficient to do that.
+       // Adding '-o BatchMode=yes' should do the trick.
+       //
        // If a Git subprocess forks a child into the background to cache a new connection,
        // that child keeps stdout/stderr open. After the Git subprocess exits,
        // os /exec expects to be able to read from the stdout/stderr pipe
@@ -157,7 +153,14 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) {
        // assume they know what they are doing and don't step on it.
        // But default to turning off ControlMaster.
        if os.Getenv("GIT_SSH") == "" && os.Getenv("GIT_SSH_COMMAND") == "" {
-               os.Setenv("GIT_SSH_COMMAND", "ssh -o ControlMaster=no")
+               os.Setenv("GIT_SSH_COMMAND", "ssh -o ControlMaster=no -o BatchMode=yes")
+       }
+
+       // And one more source of Git prompts: the Git Credential Manager Core for Windows.
+       //
+       // See https://github.com/microsoft/Git-Credential-Manager-Core/blob/master/docs/environment.md#gcm_interactive.
+       if os.Getenv("GCM_INTERACTIVE") == "" {
+               os.Setenv("GCM_INTERACTIVE", "never")
        }
 
        // Phase 1. Download/update.
@@ -180,7 +183,7 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) {
        // everything.
        load.ClearPackageCache()
 
-       pkgs := load.PackagesAndErrors(ctx, args)
+       pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{}, args)
        load.CheckPackageErrors(pkgs)
 
        // Phase 3. Install.
@@ -255,9 +258,9 @@ func download(arg string, parent *load.Package, stk *load.ImportStack, mode int)
        load1 := func(path string, mode int) *load.Package {
                if parent == nil {
                        mode := 0 // don't do module or vendor resolution
-                       return load.LoadImport(context.TODO(), path, base.Cwd, nil, stk, nil, mode)
+                       return load.LoadImport(context.TODO(), load.PackageOpts{}, path, base.Cwd(), nil, stk, nil, mode)
                }
-               return load.LoadImport(context.TODO(), path, parent.Dir, parent, stk, nil, mode|load.ResolveModule)
+               return load.LoadImport(context.TODO(), load.PackageOpts{}, path, parent.Dir, parent, stk, nil, mode|load.ResolveModule)
        }
 
        p := load1(arg, mode)
@@ -435,7 +438,7 @@ func downloadPackage(p *load.Package) error {
                return fmt.Errorf("%s: invalid import path: %v", p.ImportPath, err)
        }
        security := web.SecureOnly
-       if cfg.Insecure || module.MatchPrefixPatterns(cfg.GOINSECURE, importPrefix) {
+       if module.MatchPrefixPatterns(cfg.GOINSECURE, importPrefix) {
                security = web.Insecure
        }
 
index 57cee4ff96c1acc42c01d69483bc630d86e8b750..490ff1fb7cf05bd5a7e107c1ea40bb44174cc0db 100644 (file)
@@ -251,7 +251,7 @@ For example,
 will result in the following requests:
 
        https://example.org/pkg/foo?go-get=1 (preferred)
-       http://example.org/pkg/foo?go-get=1  (fallback, only with -insecure)
+       http://example.org/pkg/foo?go-get=1  (fallback, only with use of correctly set GOINSECURE)
 
 If that page contains the meta tag
 
@@ -517,9 +517,8 @@ General-purpose environment variables:
                Comma-separated list of glob patterns (in the syntax of Go's path.Match)
                of module path prefixes that should always be fetched in an insecure
                manner. Only applies to dependencies that are being fetched directly.
-               Unlike the -insecure flag on 'go get', GOINSECURE does not disable
-               checksum database validation. GOPRIVATE or GONOSUMDB may be used
-               to achieve that.
+               GOINSECURE does not disable checksum database validation. GOPRIVATE or
+               GONOSUMDB may be used to achieve that.
        GOOS
                The operating system for which to compile code.
                Examples are linux, darwin, windows, netbsd.
@@ -599,6 +598,9 @@ Architecture-specific environment variables:
        GOMIPS64
                For GOARCH=mips64{,le}, whether to use floating point instructions.
                Valid values are hardfloat (default), softfloat.
+       GOPPC64
+               For GOARCH=ppc64{,le}, the target ISA (Instruction Set Architecture).
+               Valid values are power8 (default), power9.
        GOWASM
                For GOARCH=wasm, comma-separated list of experimental WebAssembly features to use.
                Valid values are satconv, signext.
@@ -608,6 +610,12 @@ Special-purpose environment variables:
        GCCGOTOOLDIR
                If set, where to find gccgo tools, such as cgo.
                The default is based on how gccgo was configured.
+       GOEXPERIMENT
+               Comma-separated list of toolchain experiments to enable or disable.
+               The list of available experiments may change arbitrarily over time.
+               See src/internal/goexperiment/flags.go for currently valid values.
+               Warning: This variable is provided for the development and testing
+               of the Go toolchain itself. Use beyond that purpose is unsupported.
        GOROOT_FINAL
                The root of the installed Go tree, when it is
                installed in a location other than where it is built.
@@ -785,7 +793,7 @@ var HelpBuildConstraint = &base.Command{
        Long: `
 A build constraint, also known as a build tag, is a line comment that begins
 
-       // +build
+       //go:build
 
 that lists the conditions under which a file should be included in the package.
 Constraints may appear in any kind of source file (not just Go), but
@@ -793,30 +801,20 @@ they must appear near the top of the file, preceded
 only by blank lines and other line comments. These rules mean that in Go
 files a build constraint must appear before the package clause.
 
-To distinguish build constraints from package documentation, a series of
-build constraints must be followed by a blank line.
+To distinguish build constraints from package documentation,
+a build constraint should be followed by a blank line.
 
-A build constraint is evaluated as the OR of space-separated options.
-Each option evaluates as the AND of its comma-separated terms.
-Each term consists of letters, digits, underscores, and dots.
-A term may be negated with a preceding !.
-For example, the build constraint:
+A build constraint is evaluated as an expression containing options
+combined by ||, &&, and ! operators and parentheses. Operators have
+the same meaning as in Go.
 
-       // +build linux,386 darwin,!cgo
+For example, the following build constraint constrains a file to
+build when the "linux" and "386" constraints are satisfied, or when
+"darwin" is satisfied and "cgo" is not:
 
-corresponds to the boolean formula:
+       //go:build (linux && 386) || (darwin && !cgo)
 
-       (linux AND 386) OR (darwin AND (NOT cgo))
-
-A file may have multiple build constraints. The overall constraint is the AND
-of the individual constraints. That is, the build constraints:
-
-       // +build linux darwin
-       // +build amd64
-
-corresponds to the boolean formula:
-
-       (linux OR darwin) AND amd64
+It is an error for a file to have more than one //go:build line.
 
 During a particular build, the following words are satisfied:
 
@@ -854,22 +852,26 @@ in addition to ios tags and files.
 
 To keep a file from being considered for the build:
 
-       // +build ignore
+       //go:build ignore
 
 (any other unsatisfied word will work as well, but "ignore" is conventional.)
 
 To build a file only when using cgo, and only on Linux and OS X:
 
-       // +build linux,cgo darwin,cgo
+       //go:build cgo && (linux || darwin)
 
 Such a file is usually paired with another file implementing the
 default functionality for other systems, which in this case would
 carry the constraint:
 
-       // +build !linux,!darwin !cgo
+       //go:build !(cgo && (linux || darwin))
 
 Naming a file dns_windows.go will cause it to be included only when
 building the package for Windows; similarly, math_386.s will be included
 only when building the package for 32-bit x86.
+
+Go versions 1.16 and earlier used a different syntax for build constraints,
+with a "// +build" prefix. The gofmt command will add an equivalent //go:build
+constraint when encountering the older syntax.
 `,
 }
index 5e270781d77bfeaca88908daf97d95d287ce7308..70d5190450502d042c2a2d0ed3d17105d50e6dbc 100644 (file)
@@ -8,6 +8,7 @@ package imports
 
 import (
        "bufio"
+       "bytes"
        "errors"
        "io"
        "unicode/utf8"
@@ -22,6 +23,19 @@ type importReader struct {
        nerr int
 }
 
+var bom = []byte{0xef, 0xbb, 0xbf}
+
+func newImportReader(b *bufio.Reader) *importReader {
+       // Remove leading UTF-8 BOM.
+       // Per https://golang.org/ref/spec#Source_code_representation:
+       // a compiler may ignore a UTF-8-encoded byte order mark (U+FEFF)
+       // if it is the first Unicode code point in the source text.
+       if leadingBytes, err := b.Peek(3); err == nil && bytes.Equal(leadingBytes, bom) {
+               b.Discard(3)
+       }
+       return &importReader{b: b}
+}
+
 func isIdent(c byte) bool {
        return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '_' || c >= utf8.RuneSelf
 }
@@ -201,7 +215,7 @@ func (r *importReader) readImport(imports *[]string) {
 // ReadComments is like io.ReadAll, except that it only reads the leading
 // block of comments in the file.
 func ReadComments(f io.Reader) ([]byte, error) {
-       r := &importReader{b: bufio.NewReader(f)}
+       r := newImportReader(bufio.NewReader(f))
        r.peekByte(true)
        if r.err == nil && !r.eof {
                // Didn't reach EOF, so must have found a non-space byte. Remove it.
@@ -213,7 +227,7 @@ func ReadComments(f io.Reader) ([]byte, error) {
 // ReadImports is like io.ReadAll, except that it expects a Go file as input
 // and stops reading the input once the imports have completed.
 func ReadImports(f io.Reader, reportSyntaxError bool, imports *[]string) ([]byte, error) {
-       r := &importReader{b: bufio.NewReader(f)}
+       r := newImportReader(bufio.NewReader(f))
 
        r.readKeyword("package")
        r.readIdent()
index 6ea356f1ff05acbd8aee3e9de9b5564cb1537dd3..6a1a6524a116d50c8036baa0b0ff3d60e08ccf1a 100644 (file)
@@ -66,6 +66,10 @@ var readImportsTests = []readTest{
                `,
                "",
        },
+       {
+               "\ufeff𝔻" + `package p; import "x";ℙvar x = 1`,
+               "",
+       },
 }
 
 var readCommentsTests = []readTest{
@@ -81,6 +85,10 @@ var readCommentsTests = []readTest{
                `ℙpackage p; import . "x"`,
                "",
        },
+       {
+               "\ufeff𝔻" + `ℙpackage p; import . "x"`,
+               "",
+       },
        {
                `// foo
 
@@ -90,6 +98,19 @@ var readCommentsTests = []readTest{
                
                /*/ zot */
 
+               // asdf
+               ℙHello, world`,
+               "",
+       },
+       {
+               "\ufeff𝔻" + `// foo
+
+               /* bar */
+
+               /* quux */ // baz
+
+               /*/ zot */
+
                // asdf
                ℙHello, world`,
                "",
@@ -107,6 +128,11 @@ func testRead(t *testing.T, tests []readTest, read func(io.Reader) ([]byte, erro
                        in = tt.in[:j] + tt.in[j+len("ℙ"):]
                        testOut = tt.in[:j]
                }
+               d := strings.Index(tt.in, "𝔻")
+               if d >= 0 {
+                       in = in[:d] + in[d+len("𝔻"):]
+                       testOut = testOut[d+len("𝔻"):]
+               }
                r := strings.NewReader(in)
                buf, err := read(r)
                if err != nil {
diff --git a/libgo/go/cmd/go/internal/imports/testdata/android/tags.txt b/libgo/go/cmd/go/internal/imports/testdata/android/tags.txt
new file mode 100644 (file)
index 0000000..aaf5a6b
--- /dev/null
@@ -0,0 +1 @@
+android arm64
\ No newline at end of file
diff --git a/libgo/go/cmd/go/internal/imports/testdata/android/want.txt b/libgo/go/cmd/go/internal/imports/testdata/android/want.txt
new file mode 100644 (file)
index 0000000..0fdf397
--- /dev/null
@@ -0,0 +1,6 @@
+a
+b
+c
+d
+e
+f
diff --git a/libgo/go/cmd/go/internal/imports/testdata/illumos/tags.txt b/libgo/go/cmd/go/internal/imports/testdata/illumos/tags.txt
new file mode 100644 (file)
index 0000000..b6386a3
--- /dev/null
@@ -0,0 +1 @@
+illumos amd64
diff --git a/libgo/go/cmd/go/internal/imports/testdata/illumos/want.txt b/libgo/go/cmd/go/internal/imports/testdata/illumos/want.txt
new file mode 100644 (file)
index 0000000..0fdf397
--- /dev/null
@@ -0,0 +1,6 @@
+a
+b
+c
+d
+e
+f
diff --git a/libgo/go/cmd/go/internal/imports/testdata/star/tags.txt b/libgo/go/cmd/go/internal/imports/testdata/star/tags.txt
new file mode 100644 (file)
index 0000000..f59ec20
--- /dev/null
@@ -0,0 +1 @@
+*
\ No newline at end of file
diff --git a/libgo/go/cmd/go/internal/imports/testdata/star/want.txt b/libgo/go/cmd/go/internal/imports/testdata/star/want.txt
new file mode 100644 (file)
index 0000000..139f5f4
--- /dev/null
@@ -0,0 +1,4 @@
+import1
+import2
+import3
+import4
index 68d691ebe2eeccd0e7f16ca8528204d0296854e9..2dc63766b70654576156bebd007d6b35c0def832 100644 (file)
@@ -17,6 +17,7 @@ type Context struct {
        UseAllFiles   bool     `json:",omitempty"` // use files regardless of +build lines, file names
        Compiler      string   `json:",omitempty"` // compiler to assume when computing target paths
        BuildTags     []string `json:",omitempty"` // build constraints to match in +build lines
+       ToolTags      []string `json:",omitempty"` // toolchain-specific build constraints
        ReleaseTags   []string `json:",omitempty"` // releases the current release is compatible with
        InstallSuffix string   `json:",omitempty"` // suffix to use in the name of the install dir
 }
@@ -31,6 +32,7 @@ func newContext(c *build.Context) *Context {
                UseAllFiles:   c.UseAllFiles,
                Compiler:      c.Compiler,
                BuildTags:     c.BuildTags,
+               ToolTags:      c.ToolTags,
                ReleaseTags:   c.ReleaseTags,
                InstallSuffix: c.InstallSuffix,
        }
index b4d82d9f8ccc97cb4e9400b15774958d4b4ce921..7cb9ec6d9492428aa0c9afe111fde89bf35fa536 100644 (file)
@@ -148,6 +148,7 @@ The template function "context" returns the build context, defined as:
         UseAllFiles   bool     // use files regardless of +build lines, file names
         Compiler      string   // compiler to assume when computing target paths
         BuildTags     []string // build constraints to match in +build lines
+        ToolTags      []string // toolchain-specific build constraints
         ReleaseTags   []string // releases the current release is compatible with
         InstallSuffix string   // suffix to use in the name of the install dir
     }
@@ -335,7 +336,10 @@ var (
 var nl = []byte{'\n'}
 
 func runList(ctx context.Context, cmd *base.Command, args []string) {
-       load.ModResolveTests = *listTest
+       if *listFmt != "" && *listJson == true {
+               base.Fatalf("go list -f cannot be used with -json")
+       }
+
        work.BuildInit()
        out := newTrackingWriter(os.Stdout)
        defer out.w.Flush()
@@ -344,7 +348,7 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
                if *listM {
                        *listFmt = "{{.String}}"
                        if *listVersions {
-                               *listFmt = `{{.Path}}{{range .Versions}} {{.}}{{end}}`
+                               *listFmt = `{{.Path}}{{range .Versions}} {{.}}{{end}}{{if .Deprecated}} (deprecated){{end}}`
                        }
                } else {
                        *listFmt = "{{.ImportPath}}"
@@ -423,7 +427,7 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
                        base.Fatalf("go list -m: not using modules")
                }
 
-               modload.LoadModFile(ctx) // Parses go.mod and sets cfg.BuildMod.
+               modload.LoadModFile(ctx) // Sets cfg.BuildMod as a side-effect.
                if cfg.BuildMod == "vendor" {
                        const actionDisabledFormat = "go list -m: can't %s using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)"
 
@@ -447,13 +451,29 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
                        }
                }
 
-               mods := modload.ListModules(ctx, args, *listU, *listVersions, *listRetracted)
+               var mode modload.ListMode
+               if *listU {
+                       mode |= modload.ListU | modload.ListRetracted | modload.ListDeprecated
+               }
+               if *listRetracted {
+                       mode |= modload.ListRetracted
+               }
+               if *listVersions {
+                       mode |= modload.ListVersions
+                       if *listRetracted {
+                               mode |= modload.ListRetractedVersions
+                       }
+               }
+               mods, err := modload.ListModules(ctx, args, mode)
                if !*listE {
                        for _, m := range mods {
                                if m.Error != nil {
                                        base.Errorf("go list -m: %v", m.Error.Err)
                                }
                        }
+                       if err != nil {
+                               base.Errorf("go list -m: %v", err)
+                       }
                        base.ExitIfErrors()
                }
                for _, m := range mods {
@@ -478,8 +498,11 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
                base.Fatalf("go list -test cannot be used with -find")
        }
 
-       load.IgnoreImports = *listFind
-       pkgs := load.PackagesAndErrors(ctx, args)
+       pkgOpts := load.PackageOpts{
+               IgnoreImports:   *listFind,
+               ModResolveTests: *listTest,
+       }
+       pkgs := load.PackagesAndErrors(ctx, pkgOpts, args)
        if !*listE {
                w := 0
                for _, pkg := range pkgs {
@@ -516,9 +539,9 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
                                var pmain, ptest, pxtest *load.Package
                                var err error
                                if *listE {
-                                       pmain, ptest, pxtest = load.TestPackagesAndErrors(ctx, p, nil)
+                                       pmain, ptest, pxtest = load.TestPackagesAndErrors(ctx, pkgOpts, p, nil)
                                } else {
-                                       pmain, ptest, pxtest, err = load.TestPackagesFor(ctx, p, nil)
+                                       pmain, ptest, pxtest, err = load.TestPackagesFor(ctx, pkgOpts, p, nil)
                                        if err != nil {
                                                base.Errorf("can't load test package: %s", err)
                                        }
@@ -605,7 +628,7 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
                old := make(map[string]string)
                for _, p := range all {
                        if p.ForTest != "" {
-                               new := p.ImportPath + " [" + p.ForTest + ".test]"
+                               new := p.Desc()
                                old[new] = p.ImportPath
                                p.ImportPath = new
                        }
@@ -679,9 +702,14 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
                }
 
                if len(args) > 0 {
-                       listU := false
-                       listVersions := false
-                       rmods := modload.ListModules(ctx, args, listU, listVersions, *listRetracted)
+                       var mode modload.ListMode
+                       if *listRetracted {
+                               mode |= modload.ListRetracted
+                       }
+                       rmods, err := modload.ListModules(ctx, args, mode)
+                       if err != nil && !*listE {
+                               base.Errorf("go list -retracted: %v", err)
+                       }
                        for i, arg := range args {
                                rmod := rmods[i]
                                for _, mod := range argToMods[arg] {
@@ -696,8 +724,18 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
 
        // Record non-identity import mappings in p.ImportMap.
        for _, p := range pkgs {
-               for i, srcPath := range p.Internal.RawImports {
-                       path := p.Imports[i]
+               nRaw := len(p.Internal.RawImports)
+               for i, path := range p.Imports {
+                       var srcPath string
+                       if i < nRaw {
+                               srcPath = p.Internal.RawImports[i]
+                       } else {
+                               // This path is not within the raw imports, so it must be an import
+                               // found only within CompiledGoFiles. Those paths are found in
+                               // CompiledImports.
+                               srcPath = p.Internal.CompiledImports[i-nRaw]
+                       }
+
                        if path != srcPath {
                                if p.ImportMap == nil {
                                        p.ImportMap = make(map[string]string)
index 7534e65f54c75309ee5fc3bcbe4fa3222481f9d0..440cb86134489a7e023ce516629fe9bccc00fe0c 100644 (file)
@@ -34,7 +34,7 @@ type ppfValue struct {
 
 // Set is called each time the flag is encountered on the command line.
 func (f *PerPackageFlag) Set(v string) error {
-       return f.set(v, base.Cwd)
+       return f.set(v, base.Cwd())
 }
 
 // set is the implementation of Set, taking a cwd (current working directory) for easier testing.
index e83f1d2cea9e8a4630a612d828c4c32874bcb4ce..c085fcbbf80faaa32677f605dea702182ddabf19 100644 (file)
@@ -14,6 +14,7 @@ import (
        "go/build"
        "go/scanner"
        "go/token"
+       "internal/goroot"
        "io/fs"
        "os"
        "path"
@@ -29,6 +30,8 @@ import (
        "cmd/go/internal/base"
        "cmd/go/internal/cfg"
        "cmd/go/internal/fsys"
+       "cmd/go/internal/imports"
+       "cmd/go/internal/modfetch"
        "cmd/go/internal/modinfo"
        "cmd/go/internal/modload"
        "cmd/go/internal/par"
@@ -37,11 +40,10 @@ import (
        "cmd/go/internal/trace"
        "cmd/internal/sys"
 
+       "golang.org/x/mod/modfile"
        "golang.org/x/mod/module"
 )
 
-var IgnoreImports bool // control whether we ignore imports in packages
-
 // A Package describes a single package found in a directory.
 type Package struct {
        PackagePublic                 // visible in 'go list'
@@ -85,6 +87,7 @@ type PackagePublic struct {
        CgoFiles          []string `json:",omitempty"` // .go source files that import "C"
        CompiledGoFiles   []string `json:",omitempty"` // .go output from running cgo on CgoFiles
        IgnoredGoFiles    []string `json:",omitempty"` // .go source files ignored due to build constraints
+       InvalidGoFiles    []string `json:",omitempty"` // .go source files with detected problems (parse error, wrong package name, and so on)
        IgnoredOtherFiles []string `json:",omitempty"` // non-.go source files ignored due to build constraints
        CFiles            []string `json:",omitempty"` // .c source files
        CXXFiles          []string `json:",omitempty"` // .cc, .cpp and .cxx source files
@@ -142,6 +145,7 @@ func (p *Package) AllFiles() []string {
                p.CgoFiles,
                // no p.CompiledGoFiles, because they are from GoFiles or generated by us
                p.IgnoredGoFiles,
+               // no p.InvalidGoFiles, because they are from GoFiles
                p.IgnoredOtherFiles,
                p.CFiles,
                p.CXXFiles,
@@ -190,8 +194,8 @@ type PackageInternal struct {
        // Unexported fields are not part of the public API.
        Build             *build.Package
        Imports           []*Package           // this package's direct imports
-       CompiledImports   []string             // additional Imports necessary when using CompiledGoFiles (all from standard library)
-       RawImports        []string             // this package's original imports as they appear in the text of the program
+       CompiledImports   []string             // additional Imports necessary when using CompiledGoFiles (all from standard library); 1:1 with the end of PackagePublic.Imports
+       RawImports        []string             // this package's original imports as they appear in the text of the program; 1:1 with the end of PackagePublic.Imports
        ForceLibrary      bool                 // this package is a library (even if named "main")
        CmdlineFiles      bool                 // package built from files listed on command line
        CmdlinePkg        bool                 // package listed on command line
@@ -206,6 +210,7 @@ type PackageInternal struct {
        BuildInfo         string               // add this info to package main
        TestmainGo        *[]byte              // content for _testmain.go
        Embed             map[string][]string  // //go:embed comment mapping
+       OrigImportPath    string               // original import path before adding '_test' suffix
 
        Asmflags   []string // -asmflags for this package
        Gcflags    []string // -gcflags for this package
@@ -343,7 +348,7 @@ type CoverVar struct {
        Var  string // name of count struct
 }
 
-func (p *Package) copyBuild(pp *build.Package) {
+func (p *Package) copyBuild(opts PackageOpts, pp *build.Package) {
        p.Internal.Build = pp
 
        if pp.PkgTargetRoot != "" && cfg.BuildPkgdir != "" {
@@ -368,6 +373,7 @@ func (p *Package) copyBuild(pp *build.Package) {
        p.GoFiles = pp.GoFiles
        p.CgoFiles = pp.CgoFiles
        p.IgnoredGoFiles = pp.IgnoredGoFiles
+       p.InvalidGoFiles = pp.InvalidGoFiles
        p.IgnoredOtherFiles = pp.IgnoredOtherFiles
        p.CFiles = pp.CFiles
        p.CXXFiles = pp.CXXFiles
@@ -392,7 +398,7 @@ func (p *Package) copyBuild(pp *build.Package) {
        p.TestImports = pp.TestImports
        p.XTestGoFiles = pp.XTestGoFiles
        p.XTestImports = pp.XTestImports
-       if IgnoreImports {
+       if opts.IgnoreImports {
                p.Imports = nil
                p.Internal.RawImports = nil
                p.TestImports = nil
@@ -401,6 +407,7 @@ func (p *Package) copyBuild(pp *build.Package) {
        p.EmbedPatterns = pp.EmbedPatterns
        p.TestEmbedPatterns = pp.TestEmbedPatterns
        p.XTestEmbedPatterns = pp.XTestEmbedPatterns
+       p.Internal.OrigImportPath = pp.ImportPath
 }
 
 // A PackageError describes an error loading information about a package.
@@ -476,8 +483,10 @@ type ImportPathError interface {
 
 var (
        _ ImportPathError = (*importError)(nil)
+       _ ImportPathError = (*mainPackageError)(nil)
        _ ImportPathError = (*modload.ImportMissingError)(nil)
        _ ImportPathError = (*modload.ImportMissingSumError)(nil)
+       _ ImportPathError = (*modload.DirectImportFromImplicitDependencyError)(nil)
 )
 
 type importError struct {
@@ -597,7 +606,7 @@ func ReloadPackageNoFlags(arg string, stk *ImportStack) *Package {
                })
                packageDataCache.Delete(p.ImportPath)
        }
-       return LoadImport(context.TODO(), arg, base.Cwd, nil, stk, nil, 0)
+       return LoadImport(context.TODO(), PackageOpts{}, arg, base.Cwd(), nil, stk, nil, 0)
 }
 
 // dirToImportPath returns the pseudo-import path we use for a package
@@ -649,11 +658,11 @@ const (
 // LoadImport does not set tool flags and should only be used by
 // this package, as part of a bigger load operation, and by GOPATH-based "go get".
 // TODO(rsc): When GOPATH-based "go get" is removed, unexport this function.
-func LoadImport(ctx context.Context, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) *Package {
-       return loadImport(ctx, nil, path, srcDir, parent, stk, importPos, mode)
+func LoadImport(ctx context.Context, opts PackageOpts, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) *Package {
+       return loadImport(ctx, opts, nil, path, srcDir, parent, stk, importPos, mode)
 }
 
-func loadImport(ctx context.Context, pre *preload, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) *Package {
+func loadImport(ctx context.Context, opts PackageOpts, pre *preload, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) *Package {
        if path == "" {
                panic("LoadImport called with empty package path")
        }
@@ -665,25 +674,30 @@ func loadImport(ctx context.Context, pre *preload, path, srcDir string, parent *
                parentRoot = parent.Root
                parentIsStd = parent.Standard
        }
-       bp, loaded, err := loadPackageData(path, parentPath, srcDir, parentRoot, parentIsStd, mode)
-       if loaded && pre != nil && !IgnoreImports {
-               pre.preloadImports(bp.Imports, bp)
+       bp, loaded, err := loadPackageData(ctx, path, parentPath, srcDir, parentRoot, parentIsStd, mode)
+       if loaded && pre != nil && !opts.IgnoreImports {
+               pre.preloadImports(ctx, opts, bp.Imports, bp)
        }
        if bp == nil {
-               if importErr, ok := err.(ImportPathError); !ok || importErr.ImportPath() != path {
-                       // Only add path to the error's import stack if it's not already present on the error.
-                       stk.Push(path)
-                       defer stk.Pop()
-               }
-               return &Package{
+               p := &Package{
                        PackagePublic: PackagePublic{
                                ImportPath: path,
-                               Error: &PackageError{
-                                       ImportStack: stk.Copy(),
-                                       Err:         err,
-                               },
+                               Incomplete: true,
                        },
                }
+               if importErr, ok := err.(ImportPathError); !ok || importErr.ImportPath() != path {
+                       // Only add path to the error's import stack if it's not already present
+                       // in the error.
+                       //
+                       // TODO(bcmills): setLoadPackageDataError itself has a similar Push / Pop
+                       // sequence that empirically doesn't trigger for these errors, guarded by
+                       // a somewhat complex condition. Figure out how to generalize that
+                       // condition and eliminate the explicit calls here.
+                       stk.Push(path)
+                       defer stk.Pop()
+               }
+               p.setLoadPackageDataError(err, path, stk, nil)
+               return p
        }
 
        importPath := bp.ImportPath
@@ -701,7 +715,7 @@ func loadImport(ctx context.Context, pre *preload, path, srcDir string, parent *
                // Load package.
                // loadPackageData may return bp != nil even if an error occurs,
                // in order to return partial information.
-               p.load(ctx, path, stk, importPos, bp, err)
+               p.load(ctx, opts, path, stk, importPos, bp, err)
 
                if !cfg.ModulesEnabled && path != cleanImport(path) {
                        p.Error = &PackageError{
@@ -714,7 +728,7 @@ func loadImport(ctx context.Context, pre *preload, path, srcDir string, parent *
        }
 
        // Checked on every import because the rules depend on the code doing the importing.
-       if perr := disallowInternal(srcDir, parent, parentPath, p, stk); perr != p {
+       if perr := disallowInternal(ctx, srcDir, parent, parentPath, p, stk); perr != p {
                perr.Error.setPos(importPos)
                return perr
        }
@@ -763,7 +777,7 @@ func loadImport(ctx context.Context, pre *preload, path, srcDir string, parent *
 //
 // loadPackageData returns a boolean, loaded, which is true if this is the
 // first time the package was loaded. Callers may preload imports in this case.
-func loadPackageData(path, parentPath, parentDir, parentRoot string, parentIsStd bool, mode int) (bp *build.Package, loaded bool, err error) {
+func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoot string, parentIsStd bool, mode int) (bp *build.Package, loaded bool, err error) {
        if path == "" {
                panic("loadPackageData called with empty package path")
        }
@@ -835,11 +849,34 @@ func loadPackageData(path, parentPath, parentDir, parentRoot string, parentIsStd
                                buildMode = build.ImportComment
                        }
                        data.p, data.err = cfg.BuildContext.ImportDir(r.dir, buildMode)
-                       if data.p.Root == "" && cfg.ModulesEnabled {
-                               if info := modload.PackageModuleInfo(path); info != nil {
+                       if cfg.ModulesEnabled {
+                               // Override data.p.Root, since ImportDir sets it to $GOPATH, if
+                               // the module is inside $GOPATH/src.
+                               if info := modload.PackageModuleInfo(ctx, path); info != nil {
                                        data.p.Root = info.Dir
                                }
                        }
+                       if r.err != nil {
+                               if data.err != nil {
+                                       // ImportDir gave us one error, and the module loader gave us another.
+                                       // We arbitrarily choose to keep the error from ImportDir because
+                                       // that's what our tests already expect, and it seems to provide a bit
+                                       // more detail in most cases.
+                               } else if errors.Is(r.err, imports.ErrNoGo) {
+                                       // ImportDir said there were files in the package, but the module
+                                       // loader said there weren't. Which one is right?
+                                       // Without this special-case hack, the TestScript/test_vet case fails
+                                       // on the vetfail/p1 package (added in CL 83955).
+                                       // Apparently, imports.ShouldBuild biases toward rejecting files
+                                       // with invalid build constraints, whereas ImportDir biases toward
+                                       // accepting them.
+                                       //
+                                       // TODO(#41410: Figure out how this actually ought to work and fix
+                                       // this mess.
+                               } else {
+                                       data.err = r.err
+                               }
+                       }
                } else if r.err != nil {
                        data.p = new(build.Package)
                        data.err = r.err
@@ -950,7 +987,7 @@ func newPreload() *preload {
 // preloadMatches loads data for package paths matched by patterns.
 // When preloadMatches returns, some packages may not be loaded yet, but
 // loadPackageData and loadImport are always safe to call.
-func (pre *preload) preloadMatches(matches []*search.Match) {
+func (pre *preload) preloadMatches(ctx context.Context, opts PackageOpts, matches []*search.Match) {
        for _, m := range matches {
                for _, pkg := range m.Pkgs {
                        select {
@@ -959,10 +996,10 @@ func (pre *preload) preloadMatches(matches []*search.Match) {
                        case pre.sema <- struct{}{}:
                                go func(pkg string) {
                                        mode := 0 // don't use vendoring or module import resolution
-                                       bp, loaded, err := loadPackageData(pkg, "", base.Cwd, "", false, mode)
+                                       bp, loaded, err := loadPackageData(ctx, pkg, "", base.Cwd(), "", false, mode)
                                        <-pre.sema
-                                       if bp != nil && loaded && err == nil && !IgnoreImports {
-                                               pre.preloadImports(bp.Imports, bp)
+                                       if bp != nil && loaded && err == nil && !opts.IgnoreImports {
+                                               pre.preloadImports(ctx, opts, bp.Imports, bp)
                                        }
                                }(pkg)
                        }
@@ -973,7 +1010,7 @@ func (pre *preload) preloadMatches(matches []*search.Match) {
 // preloadImports queues a list of imports for preloading.
 // When preloadImports returns, some packages may not be loaded yet,
 // but loadPackageData and loadImport are always safe to call.
-func (pre *preload) preloadImports(imports []string, parent *build.Package) {
+func (pre *preload) preloadImports(ctx context.Context, opts PackageOpts, imports []string, parent *build.Package) {
        parentIsStd := parent.Goroot && parent.ImportPath != "" && search.IsStandardImportPath(parent.ImportPath)
        for _, path := range imports {
                if path == "C" || path == "unsafe" {
@@ -984,10 +1021,10 @@ func (pre *preload) preloadImports(imports []string, parent *build.Package) {
                        return
                case pre.sema <- struct{}{}:
                        go func(path string) {
-                               bp, loaded, err := loadPackageData(path, parent.ImportPath, parent.Dir, parent.Root, parentIsStd, ResolveImport)
+                               bp, loaded, err := loadPackageData(ctx, path, parent.ImportPath, parent.Dir, parent.Root, parentIsStd, ResolveImport)
                                <-pre.sema
-                               if bp != nil && loaded && err == nil && !IgnoreImports {
-                                       pre.preloadImports(bp.Imports, bp)
+                               if bp != nil && loaded && err == nil && !opts.IgnoreImports {
+                                       pre.preloadImports(ctx, opts, bp.Imports, bp)
                                }
                        }(path)
                }
@@ -1323,6 +1360,11 @@ func reusePackage(p *Package, stk *ImportStack) *Package {
                                Err:           errors.New("import cycle not allowed"),
                                IsImportCycle: true,
                        }
+               } else if !p.Error.IsImportCycle {
+                       // If the error is already set, but it does not indicate that
+                       // we are in an import cycle, set IsImportCycle so that we don't
+                       // end up stuck in a loop down the road.
+                       p.Error.IsImportCycle = true
                }
                p.Incomplete = true
        }
@@ -1338,7 +1380,7 @@ func reusePackage(p *Package, stk *ImportStack) *Package {
 // is allowed to import p.
 // If the import is allowed, disallowInternal returns the original package p.
 // If not, it returns a new package containing just an appropriate error.
-func disallowInternal(srcDir string, importer *Package, importerPath string, p *Package, stk *ImportStack) *Package {
+func disallowInternal(ctx context.Context, srcDir string, importer *Package, importerPath string, p *Package, stk *ImportStack) *Package {
        // golang.org/s/go14internal:
        // An import of a path containing the element “internal”
        // is disallowed if the importing code is outside the tree
@@ -1416,7 +1458,7 @@ func disallowInternal(srcDir string, importer *Package, importerPath string, p *
                        // directory containing them.
                        // If the directory is outside the main module, this will resolve to ".",
                        // which is not a prefix of any valid module.
-                       importerPath = modload.DirImportPath(importer.Dir)
+                       importerPath = modload.DirImportPath(ctx, importer.Dir)
                }
                parentOfInternal := p.ImportPath[:i]
                if str.HasPathPrefix(importerPath, parentOfInternal) {
@@ -1638,8 +1680,8 @@ func (p *Package) DefaultExecName() string {
 // load populates p using information from bp, err, which should
 // be the result of calling build.Context.Import.
 // stk contains the import stack, not including path itself.
-func (p *Package) load(ctx context.Context, path string, stk *ImportStack, importPos []token.Position, bp *build.Package, err error) {
-       p.copyBuild(bp)
+func (p *Package) load(ctx context.Context, opts PackageOpts, path string, stk *ImportStack, importPos []token.Position, bp *build.Package, err error) {
+       p.copyBuild(opts, bp)
 
        // The localPrefix is the path we interpret ./ imports relative to.
        // Synthesized main packages sometimes override this.
@@ -1763,35 +1805,37 @@ func (p *Package) load(ctx context.Context, path string, stk *ImportStack, impor
                }
        }
 
-       // Cgo translation adds imports of "unsafe", "runtime/cgo" and "syscall",
-       // except for certain packages, to avoid circular dependencies.
-       if p.UsesCgo() {
-               addImport("unsafe", true)
-       }
-       if p.UsesCgo() && (!p.Standard || !cgoExclude[p.ImportPath]) && cfg.BuildContext.Compiler != "gccgo" {
-               addImport("runtime/cgo", true)
-       }
-       if p.UsesCgo() && (!p.Standard || !cgoSyscallExclude[p.ImportPath]) {
-               addImport("syscall", true)
-       }
-
-       // SWIG adds imports of some standard packages.
-       if p.UsesSwig() {
-               addImport("unsafe", true)
-               if cfg.BuildContext.Compiler != "gccgo" {
+       if !opts.IgnoreImports {
+               // Cgo translation adds imports of "unsafe", "runtime/cgo" and "syscall",
+               // except for certain packages, to avoid circular dependencies.
+               if p.UsesCgo() {
+                       addImport("unsafe", true)
+               }
+               if p.UsesCgo() && (!p.Standard || !cgoExclude[p.ImportPath]) && cfg.BuildContext.Compiler != "gccgo" {
                        addImport("runtime/cgo", true)
                }
-               addImport("syscall", true)
-               addImport("sync", true)
+               if p.UsesCgo() && (!p.Standard || !cgoSyscallExclude[p.ImportPath]) {
+                       addImport("syscall", true)
+               }
 
-               // TODO: The .swig and .swigcxx files can use
-               // %go_import directives to import other packages.
-       }
+               // SWIG adds imports of some standard packages.
+               if p.UsesSwig() {
+                       addImport("unsafe", true)
+                       if cfg.BuildContext.Compiler != "gccgo" {
+                               addImport("runtime/cgo", true)
+                       }
+                       addImport("syscall", true)
+                       addImport("sync", true)
 
-       // The linker loads implicit dependencies.
-       if p.Name == "main" && !p.Internal.ForceLibrary {
-               for _, dep := range LinkerDeps(p) {
-                       addImport(dep, false)
+                       // TODO: The .swig and .swigcxx files can use
+                       // %go_import directives to import other packages.
+               }
+
+               // The linker loads implicit dependencies.
+               if p.Name == "main" && !p.Internal.ForceLibrary {
+                       for _, dep := range LinkerDeps(p) {
+                               addImport(dep, false)
+                       }
                }
        }
 
@@ -1815,6 +1859,14 @@ func (p *Package) load(ctx context.Context, path string, stk *ImportStack, impor
        stk.Push(path)
        defer stk.Pop()
 
+       pkgPath := p.ImportPath
+       if p.Internal.CmdlineFiles {
+               pkgPath = "command-line-arguments"
+       }
+       if cfg.ModulesEnabled {
+               p.Module = modload.PackageModuleInfo(ctx, pkgPath)
+       }
+
        p.EmbedFiles, p.Internal.Embed, err = resolveEmbed(p.Dir, p.EmbedPatterns)
        if err != nil {
                p.Incomplete = true
@@ -1858,7 +1910,7 @@ func (p *Package) load(ctx context.Context, path string, stk *ImportStack, impor
                if path == "C" {
                        continue
                }
-               p1 := LoadImport(ctx, path, p.Dir, p, stk, p.Internal.Build.ImportPos[path], ResolveImport)
+               p1 := LoadImport(ctx, opts, path, p.Dir, p, stk, p.Internal.Build.ImportPos[path], ResolveImport)
 
                path = p1.ImportPath
                importPaths[i] = path
@@ -1874,6 +1926,10 @@ func (p *Package) load(ctx context.Context, path string, stk *ImportStack, impor
        p.Internal.Imports = imports
        p.collectDeps()
 
+       if cfg.ModulesEnabled && p.Error == nil && p.Name == "main" && len(p.DepsErrors) == 0 {
+               p.Internal.BuildInfo = modload.PackageBuildInfo(pkgPath, p.Deps)
+       }
+
        // unsafe is a fake package.
        if p.Standard && (p.ImportPath == "unsafe" || cfg.BuildContext.Compiler == "gccgo") {
                p.Target = ""
@@ -1913,17 +1969,6 @@ func (p *Package) load(ctx context.Context, path string, stk *ImportStack, impor
                setError(fmt.Errorf("Fortran source files not allowed when not using cgo or SWIG: %s", strings.Join(p.FFiles, " ")))
                return
        }
-
-       if cfg.ModulesEnabled && p.Error == nil {
-               mainPath := p.ImportPath
-               if p.Internal.CmdlineFiles {
-                       mainPath = "command-line-arguments"
-               }
-               p.Module = modload.PackageModuleInfo(mainPath)
-               if p.Name == "main" && len(p.DepsErrors) == 0 {
-                       p.Internal.BuildInfo = modload.PackageBuildInfo(mainPath, p.Deps)
-               }
-       }
 }
 
 // An EmbedError indicates a problem with a go:embed directive.
@@ -2305,7 +2350,7 @@ func PackageList(roots []*Package) []*Package {
 // TestPackageList returns the list of packages in the dag rooted at roots
 // as visited in a depth-first post-order traversal, including the test
 // imports of the roots. This ignores errors in test packages.
-func TestPackageList(ctx context.Context, roots []*Package) []*Package {
+func TestPackageList(ctx context.Context, opts PackageOpts, roots []*Package) []*Package {
        seen := map[*Package]bool{}
        all := []*Package{}
        var walk func(*Package)
@@ -2321,7 +2366,7 @@ func TestPackageList(ctx context.Context, roots []*Package) []*Package {
        }
        walkTest := func(root *Package, path string) {
                var stk ImportStack
-               p1 := LoadImport(ctx, path, root.Dir, root, &stk, root.Internal.Build.TestImportPos[path], ResolveImport)
+               p1 := LoadImport(ctx, opts, path, root.Dir, root, &stk, root.Internal.Build.TestImportPos[path], ResolveImport)
                if p1.Error == nil {
                        walk(p1)
                }
@@ -2344,22 +2389,35 @@ func TestPackageList(ctx context.Context, roots []*Package) []*Package {
 // TODO(jayconrod): delete this function and set flags automatically
 // in LoadImport instead.
 func LoadImportWithFlags(path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) *Package {
-       p := LoadImport(context.TODO(), path, srcDir, parent, stk, importPos, mode)
+       p := LoadImport(context.TODO(), PackageOpts{}, path, srcDir, parent, stk, importPos, mode)
        setToolFlags(p)
        return p
 }
 
-// ModResolveTests indicates whether calls to the module loader should also
-// resolve test dependencies of the requested packages.
-//
-// If ModResolveTests is true, then the module loader needs to resolve test
-// dependencies at the same time as packages; otherwise, the test dependencies
-// of those packages could be missing, and resolving those missing dependencies
-// could change the selected versions of modules that provide other packages.
-//
-// TODO(#40775): Change this from a global variable to an explicit function
-// argument where needed.
-var ModResolveTests bool
+// PackageOpts control the behavior of PackagesAndErrors and other package
+// loading functions.
+type PackageOpts struct {
+       // IgnoreImports controls whether we ignore explicit and implicit imports
+       // when loading packages.  Implicit imports are added when supporting Cgo
+       // or SWIG and when linking main packages.
+       IgnoreImports bool
+
+       // ModResolveTests indicates whether calls to the module loader should also
+       // resolve test dependencies of the requested packages.
+       //
+       // If ModResolveTests is true, then the module loader needs to resolve test
+       // dependencies at the same time as packages; otherwise, the test dependencies
+       // of those packages could be missing, and resolving those missing dependencies
+       // could change the selected versions of modules that provide other packages.
+       ModResolveTests bool
+
+       // MainOnly is true if the caller only wants to load main packages.
+       // For a literal argument matching a non-main package, a stub may be returned
+       // with an error. For a non-literal argument (with "..."), non-main packages
+       // are not be matched, and their dependencies may not be loaded. A warning
+       // may be printed for non-literal arguments that match no main packages.
+       MainOnly bool
+}
 
 // PackagesAndErrors returns the packages named by the command line arguments
 // 'patterns'. If a named package cannot be loaded, PackagesAndErrors returns
@@ -2369,7 +2427,7 @@ var ModResolveTests bool
 //
 // To obtain a flat list of packages, use PackageList.
 // To report errors loading packages, use ReportPackageErrors.
-func PackagesAndErrors(ctx context.Context, patterns []string) []*Package {
+func PackagesAndErrors(ctx context.Context, opts PackageOpts, patterns []string) []*Package {
        ctx, span := trace.StartSpan(ctx, "load.PackagesAndErrors")
        defer span.Done()
 
@@ -2381,19 +2439,19 @@ func PackagesAndErrors(ctx context.Context, patterns []string) []*Package {
                        // We need to test whether the path is an actual Go file and not a
                        // package path or pattern ending in '.go' (see golang.org/issue/34653).
                        if fi, err := fsys.Stat(p); err == nil && !fi.IsDir() {
-                               return []*Package{GoFilesPackage(ctx, patterns)}
+                               return []*Package{GoFilesPackage(ctx, opts, patterns)}
                        }
                }
        }
 
        var matches []*search.Match
        if modload.Init(); cfg.ModulesEnabled {
-               loadOpts := modload.PackageOpts{
+               modOpts := modload.PackageOpts{
                        ResolveMissingImports: true,
-                       LoadTests:             ModResolveTests,
-                       SilenceErrors:         true,
+                       LoadTests:             opts.ModResolveTests,
+                       SilencePackageErrors:  true,
                }
-               matches, _ = modload.LoadPackages(ctx, loadOpts, patterns...)
+               matches, _ = modload.LoadPackages(ctx, modOpts, patterns...)
        } else {
                matches = search.ImportPaths(patterns)
        }
@@ -2406,14 +2464,14 @@ func PackagesAndErrors(ctx context.Context, patterns []string) []*Package {
 
        pre := newPreload()
        defer pre.flush()
-       pre.preloadMatches(matches)
+       pre.preloadMatches(ctx, opts, matches)
 
        for _, m := range matches {
                for _, pkg := range m.Pkgs {
                        if pkg == "" {
                                panic(fmt.Sprintf("ImportPaths returned empty package for pattern %s", m.Pattern()))
                        }
-                       p := loadImport(ctx, pre, pkg, base.Cwd, nil, &stk, nil, 0)
+                       p := loadImport(ctx, opts, pre, pkg, base.Cwd(), nil, &stk, nil, 0)
                        p.Match = append(p.Match, m.Pattern())
                        p.Internal.CmdlinePkg = true
                        if m.IsLiteral() {
@@ -2449,6 +2507,10 @@ func PackagesAndErrors(ctx context.Context, patterns []string) []*Package {
                }
        }
 
+       if opts.MainOnly {
+               pkgs = mainPackagesOnly(pkgs, matches)
+       }
+
        // Now that CmdlinePkg is set correctly,
        // compute the effective flags for all loaded packages
        // (not just the ones matching the patterns but also
@@ -2497,6 +2559,80 @@ func CheckPackageErrors(pkgs []*Package) {
        base.ExitIfErrors()
 }
 
+// mainPackagesOnly filters out non-main packages matched only by arguments
+// containing "..." and returns the remaining main packages.
+//
+// Packages with missing, invalid, or ambiguous names may be treated as
+// possibly-main packages.
+//
+// mainPackagesOnly sets a non-main package's Error field and returns it if it
+// is named by a literal argument.
+//
+// mainPackagesOnly prints warnings for non-literal arguments that only match
+// non-main packages.
+func mainPackagesOnly(pkgs []*Package, matches []*search.Match) []*Package {
+       treatAsMain := map[string]bool{}
+       for _, m := range matches {
+               if m.IsLiteral() {
+                       for _, path := range m.Pkgs {
+                               treatAsMain[path] = true
+                       }
+               }
+       }
+
+       var mains []*Package
+       for _, pkg := range pkgs {
+               if pkg.Name == "main" {
+                       treatAsMain[pkg.ImportPath] = true
+                       mains = append(mains, pkg)
+                       continue
+               }
+
+               if len(pkg.InvalidGoFiles) > 0 { // TODO(#45999): && pkg.Name == "", but currently go/build sets pkg.Name arbitrarily if it is ambiguous.
+                       // The package has (or may have) conflicting names, and we can't easily
+                       // tell whether one of them is "main". So assume that it could be, and
+                       // report an error for the package.
+                       treatAsMain[pkg.ImportPath] = true
+               }
+               if treatAsMain[pkg.ImportPath] {
+                       if pkg.Error == nil {
+                               pkg.Error = &PackageError{Err: &mainPackageError{importPath: pkg.ImportPath}}
+                       }
+                       mains = append(mains, pkg)
+               }
+       }
+
+       for _, m := range matches {
+               if m.IsLiteral() || len(m.Pkgs) == 0 {
+                       continue
+               }
+               foundMain := false
+               for _, path := range m.Pkgs {
+                       if treatAsMain[path] {
+                               foundMain = true
+                               break
+                       }
+               }
+               if !foundMain {
+                       fmt.Fprintf(os.Stderr, "go: warning: %q matched only non-main packages\n", m.Pattern())
+               }
+       }
+
+       return mains
+}
+
+type mainPackageError struct {
+       importPath string
+}
+
+func (e *mainPackageError) Error() string {
+       return fmt.Sprintf("package %s is not a main package", e.importPath)
+}
+
+func (e *mainPackageError) ImportPath() string {
+       return e.importPath
+}
+
 func setToolFlags(pkgs ...*Package) {
        for _, p := range PackageList(pkgs) {
                p.Internal.Asmflags = BuildAsmflags.For(p)
@@ -2509,7 +2645,7 @@ func setToolFlags(pkgs ...*Package) {
 // GoFilesPackage creates a package for building a collection of Go files
 // (typically named on the command line). The target is named p.a for
 // package p or named after the first Go file for package main.
-func GoFilesPackage(ctx context.Context, gofiles []string) *Package {
+func GoFilesPackage(ctx context.Context, opts PackageOpts, gofiles []string) *Package {
        modload.Init()
 
        for _, f := range gofiles {
@@ -2562,7 +2698,7 @@ func GoFilesPackage(ctx context.Context, gofiles []string) *Package {
 
        var err error
        if dir == "" {
-               dir = base.Cwd
+               dir = base.Cwd()
        }
        dir, err = filepath.Abs(dir)
        if err != nil {
@@ -2573,7 +2709,7 @@ func GoFilesPackage(ctx context.Context, gofiles []string) *Package {
        pkg := new(Package)
        pkg.Internal.Local = true
        pkg.Internal.CmdlineFiles = true
-       pkg.load(ctx, "command-line-arguments", &stk, nil, bp, err)
+       pkg.load(ctx, opts, "command-line-arguments", &stk, nil, bp, err)
        pkg.Internal.LocalPrefix = dirToImportPath(dir)
        pkg.ImportPath = "command-line-arguments"
        pkg.Target = ""
@@ -2589,7 +2725,138 @@ func GoFilesPackage(ctx context.Context, gofiles []string) *Package {
                }
        }
 
+       if opts.MainOnly && pkg.Name != "main" && pkg.Error == nil {
+               pkg.Error = &PackageError{Err: &mainPackageError{importPath: pkg.ImportPath}}
+       }
        setToolFlags(pkg)
 
        return pkg
 }
+
+// PackagesAndErrorsOutsideModule is like PackagesAndErrors but runs in
+// module-aware mode and ignores the go.mod file in the current directory or any
+// parent directory, if there is one. This is used in the implementation of 'go
+// install pkg@version' and other commands that support similar forms.
+//
+// modload.ForceUseModules must be true, and modload.RootMode must be NoRoot
+// before calling this function.
+//
+// PackagesAndErrorsOutsideModule imposes several constraints to avoid
+// ambiguity. All arguments must have the same version suffix (not just a suffix
+// that resolves to the same version). They must refer to packages in the same
+// module, which must not be std or cmd. That module is not considered the main
+// module, but its go.mod file (if it has one) must not contain directives that
+// would cause it to be interpreted differently if it were the main module
+// (replace, exclude).
+func PackagesAndErrorsOutsideModule(ctx context.Context, opts PackageOpts, args []string) ([]*Package, error) {
+       if !modload.ForceUseModules {
+               panic("modload.ForceUseModules must be true")
+       }
+       if modload.RootMode != modload.NoRoot {
+               panic("modload.RootMode must be NoRoot")
+       }
+
+       // Check that the arguments satisfy syntactic constraints.
+       var version string
+       for _, arg := range args {
+               if i := strings.Index(arg, "@"); i >= 0 {
+                       version = arg[i+1:]
+                       if version == "" {
+                               return nil, fmt.Errorf("%s: version must not be empty", arg)
+                       }
+                       break
+               }
+       }
+       patterns := make([]string, len(args))
+       for i, arg := range args {
+               if !strings.HasSuffix(arg, "@"+version) {
+                       return nil, fmt.Errorf("%s: all arguments must have the same version (@%s)", arg, version)
+               }
+               p := arg[:len(arg)-len(version)-1]
+               switch {
+               case build.IsLocalImport(p):
+                       return nil, fmt.Errorf("%s: argument must be a package path, not a relative path", arg)
+               case filepath.IsAbs(p):
+                       return nil, fmt.Errorf("%s: argument must be a package path, not an absolute path", arg)
+               case search.IsMetaPackage(p):
+                       return nil, fmt.Errorf("%s: argument must be a package path, not a meta-package", arg)
+               case path.Clean(p) != p:
+                       return nil, fmt.Errorf("%s: argument must be a clean package path", arg)
+               case !strings.Contains(p, "...") && search.IsStandardImportPath(p) && goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, p):
+                       return nil, fmt.Errorf("%s: argument must not be a package in the standard library", arg)
+               default:
+                       patterns[i] = p
+               }
+       }
+
+       // Query the module providing the first argument, load its go.mod file, and
+       // check that it doesn't contain directives that would cause it to be
+       // interpreted differently if it were the main module.
+       //
+       // If multiple modules match the first argument, accept the longest match
+       // (first result). It's possible this module won't provide packages named by
+       // later arguments, and other modules would. Let's not try to be too
+       // magical though.
+       allowed := modload.CheckAllowed
+       if modload.IsRevisionQuery(version) {
+               // Don't check for retractions if a specific revision is requested.
+               allowed = nil
+       }
+       noneSelected := func(path string) (version string) { return "none" }
+       qrs, err := modload.QueryPackages(ctx, patterns[0], version, noneSelected, allowed)
+       if err != nil {
+               return nil, fmt.Errorf("%s: %w", args[0], err)
+       }
+       rootMod := qrs[0].Mod
+       data, err := modfetch.GoMod(rootMod.Path, rootMod.Version)
+       if err != nil {
+               return nil, fmt.Errorf("%s: %w", args[0], err)
+       }
+       f, err := modfile.Parse("go.mod", data, nil)
+       if err != nil {
+               return nil, fmt.Errorf("%s (in %s): %w", args[0], rootMod, err)
+       }
+       directiveFmt := "%s (in %s):\n" +
+               "\tThe go.mod file for the module providing named packages contains one or\n" +
+               "\tmore %s directives. It must not contain directives that would cause\n" +
+               "\tit to be interpreted differently than if it were the main module."
+       if len(f.Replace) > 0 {
+               return nil, fmt.Errorf(directiveFmt, args[0], rootMod, "replace")
+       }
+       if len(f.Exclude) > 0 {
+               return nil, fmt.Errorf(directiveFmt, args[0], rootMod, "exclude")
+       }
+
+       // Since we are in NoRoot mode, the build list initially contains only
+       // the dummy command-line-arguments module. Add a requirement on the
+       // module that provides the packages named on the command line.
+       if _, err := modload.EditBuildList(ctx, nil, []module.Version{rootMod}); err != nil {
+               return nil, fmt.Errorf("%s: %w", args[0], err)
+       }
+
+       // Load packages for all arguments.
+       pkgs := PackagesAndErrors(ctx, opts, patterns)
+
+       // Check that named packages are all provided by the same module.
+       for _, pkg := range pkgs {
+               var pkgErr error
+               if pkg.Module == nil {
+                       // Packages in std, cmd, and their vendored dependencies
+                       // don't have this field set.
+                       pkgErr = fmt.Errorf("package %s not provided by module %s", pkg.ImportPath, rootMod)
+               } else if pkg.Module.Path != rootMod.Path || pkg.Module.Version != rootMod.Version {
+                       pkgErr = fmt.Errorf("package %s provided by module %s@%s\n\tAll packages must be provided by the same module (%s).", pkg.ImportPath, pkg.Module.Path, pkg.Module.Version, rootMod)
+               }
+               if pkgErr != nil && pkg.Error == nil {
+                       pkg.Error = &PackageError{Err: pkgErr}
+               }
+       }
+
+       matchers := make([]func(string) bool, len(patterns))
+       for i, p := range patterns {
+               if strings.Contains(p, "...") {
+                       matchers[i] = search.MatchPattern(p)
+               }
+       }
+       return pkgs, nil
+}
index eb8aef3ee28126d289e39a91f57ca285051e339e..c8282965669c56d330c68a2390ba51d8c39452b8 100644 (file)
@@ -21,6 +21,7 @@ import (
        "unicode"
        "unicode/utf8"
 
+       "cmd/go/internal/fsys"
        "cmd/go/internal/str"
        "cmd/go/internal/trace"
 )
@@ -45,8 +46,8 @@ type TestCover struct {
 // TestPackagesFor is like TestPackagesAndErrors but it returns
 // an error if the test packages or their dependencies have errors.
 // Only test packages without errors are returned.
-func TestPackagesFor(ctx context.Context, p *Package, cover *TestCover) (pmain, ptest, pxtest *Package, err error) {
-       pmain, ptest, pxtest = TestPackagesAndErrors(ctx, p, cover)
+func TestPackagesFor(ctx context.Context, opts PackageOpts, p *Package, cover *TestCover) (pmain, ptest, pxtest *Package, err error) {
+       pmain, ptest, pxtest = TestPackagesAndErrors(ctx, opts, p, cover)
        for _, p1 := range []*Package{ptest, pxtest, pmain} {
                if p1 == nil {
                        // pxtest may be nil
@@ -92,7 +93,7 @@ func TestPackagesFor(ctx context.Context, p *Package, cover *TestCover) (pmain,
 //
 // The caller is expected to have checked that len(p.TestGoFiles)+len(p.XTestGoFiles) > 0,
 // or else there's no point in any of this.
-func TestPackagesAndErrors(ctx context.Context, p *Package, cover *TestCover) (pmain, ptest, pxtest *Package) {
+func TestPackagesAndErrors(ctx context.Context, opts PackageOpts, p *Package, cover *TestCover) (pmain, ptest, pxtest *Package) {
        ctx, span := trace.StartSpan(ctx, "load.TestPackagesAndErrors")
        defer span.Done()
 
@@ -100,7 +101,7 @@ func TestPackagesAndErrors(ctx context.Context, p *Package, cover *TestCover) (p
        defer pre.flush()
        allImports := append([]string{}, p.TestImports...)
        allImports = append(allImports, p.XTestImports...)
-       pre.preloadImports(allImports, p.Internal.Build)
+       pre.preloadImports(ctx, opts, allImports, p.Internal.Build)
 
        var ptestErr, pxtestErr *PackageError
        var imports, ximports []*Package
@@ -109,13 +110,13 @@ func TestPackagesAndErrors(ctx context.Context, p *Package, cover *TestCover) (p
        stk.Push(p.ImportPath + " (test)")
        rawTestImports := str.StringList(p.TestImports)
        for i, path := range p.TestImports {
-               p1 := loadImport(ctx, pre, path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], ResolveImport)
+               p1 := loadImport(ctx, opts, pre, path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], ResolveImport)
                if str.Contains(p1.Deps, p.ImportPath) || p1.ImportPath == p.ImportPath {
                        // Same error that loadPackage returns (via reusePackage) in pkg.go.
                        // Can't change that code, because that code is only for loading the
                        // non-test copy of a package.
                        ptestErr = &PackageError{
-                               ImportStack:   testImportStack(stk[0], p1, p.ImportPath),
+                               ImportStack:   importCycleStack(p1, p.ImportPath),
                                Err:           errors.New("import cycle not allowed in test"),
                                IsImportCycle: true,
                        }
@@ -139,7 +140,7 @@ func TestPackagesAndErrors(ctx context.Context, p *Package, cover *TestCover) (p
        pxtestNeedsPtest := false
        rawXTestImports := str.StringList(p.XTestImports)
        for i, path := range p.XTestImports {
-               p1 := loadImport(ctx, pre, path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], ResolveImport)
+               p1 := loadImport(ctx, opts, pre, path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], ResolveImport)
                if p1.ImportPath == p.ImportPath {
                        pxtestNeedsPtest = true
                } else {
@@ -203,6 +204,7 @@ func TestPackagesAndErrors(ctx context.Context, p *Package, cover *TestCover) (p
                }
                ptest.Internal.Embed = testEmbed
                ptest.EmbedFiles = str.StringList(p.EmbedFiles, p.TestEmbedFiles)
+               ptest.Internal.OrigImportPath = p.Internal.OrigImportPath
                ptest.collectDeps()
        } else {
                ptest = p
@@ -232,11 +234,12 @@ func TestPackagesAndErrors(ctx context.Context, p *Package, cover *TestCover) (p
                                Imports:    ximports,
                                RawImports: rawXTestImports,
 
-                               Asmflags:   p.Internal.Asmflags,
-                               Gcflags:    p.Internal.Gcflags,
-                               Ldflags:    p.Internal.Ldflags,
-                               Gccgoflags: p.Internal.Gccgoflags,
-                               Embed:      xtestEmbed,
+                               Asmflags:       p.Internal.Asmflags,
+                               Gcflags:        p.Internal.Gcflags,
+                               Ldflags:        p.Internal.Ldflags,
+                               Gccgoflags:     p.Internal.Gccgoflags,
+                               Embed:          xtestEmbed,
+                               OrigImportPath: p.Internal.OrigImportPath,
                        },
                }
                if pxtestNeedsPtest {
@@ -257,12 +260,13 @@ func TestPackagesAndErrors(ctx context.Context, p *Package, cover *TestCover) (p
                        Module:     p.Module,
                },
                Internal: PackageInternal{
-                       Build:      &build.Package{Name: "main"},
-                       BuildInfo:  p.Internal.BuildInfo,
-                       Asmflags:   p.Internal.Asmflags,
-                       Gcflags:    p.Internal.Gcflags,
-                       Ldflags:    p.Internal.Ldflags,
-                       Gccgoflags: p.Internal.Gccgoflags,
+                       Build:          &build.Package{Name: "main"},
+                       BuildInfo:      p.Internal.BuildInfo,
+                       Asmflags:       p.Internal.Asmflags,
+                       Gcflags:        p.Internal.Gcflags,
+                       Ldflags:        p.Internal.Ldflags,
+                       Gccgoflags:     p.Internal.Gccgoflags,
+                       OrigImportPath: p.Internal.OrigImportPath,
                },
        }
 
@@ -277,7 +281,7 @@ func TestPackagesAndErrors(ctx context.Context, p *Package, cover *TestCover) (p
                if dep == ptest.ImportPath {
                        pmain.Internal.Imports = append(pmain.Internal.Imports, ptest)
                } else {
-                       p1 := loadImport(ctx, pre, dep, "", nil, &stk, nil, 0)
+                       p1 := loadImport(ctx, opts, pre, dep, "", nil, &stk, nil, 0)
                        pmain.Internal.Imports = append(pmain.Internal.Imports, p1)
                }
        }
@@ -290,10 +294,12 @@ func TestPackagesAndErrors(ctx context.Context, p *Package, cover *TestCover) (p
                        seen[p1] = true
                }
                for _, p1 := range cover.Pkgs {
-                       if !seen[p1] {
-                               seen[p1] = true
-                               pmain.Internal.Imports = append(pmain.Internal.Imports, p1)
+                       if seen[p1] {
+                               // Don't add duplicate imports.
+                               continue
                        }
+                       seen[p1] = true
+                       pmain.Internal.Imports = append(pmain.Internal.Imports, p1)
                }
        }
 
@@ -369,22 +375,44 @@ func TestPackagesAndErrors(ctx context.Context, p *Package, cover *TestCover) (p
        return pmain, ptest, pxtest
 }
 
-func testImportStack(top string, p *Package, target string) []string {
-       stk := []string{top, p.ImportPath}
-Search:
-       for p.ImportPath != target {
-               for _, p1 := range p.Internal.Imports {
-                       if p1.ImportPath == target || str.Contains(p1.Deps, target) {
-                               stk = append(stk, p1.ImportPath)
-                               p = p1
-                               continue Search
+// importCycleStack returns an import stack from p to the package whose import
+// path is target.
+func importCycleStack(p *Package, target string) []string {
+       // importerOf maps each import path to its importer nearest to p.
+       importerOf := map[string]string{p.ImportPath: ""}
+
+       // q is a breadth-first queue of packages to search for target.
+       // Every package added to q has a corresponding entry in pathTo.
+       //
+       // We search breadth-first for two reasons:
+       //
+       //      1. We want to report the shortest cycle.
+       //
+       //      2. If p contains multiple cycles, the first cycle we encounter might not
+       //         contain target. To ensure termination, we have to break all cycles
+       //         other than the first.
+       q := []*Package{p}
+
+       for len(q) > 0 {
+               p := q[0]
+               q = q[1:]
+               if path := p.ImportPath; path == target {
+                       var stk []string
+                       for path != "" {
+                               stk = append(stk, path)
+                               path = importerOf[path]
+                       }
+                       return stk
+               }
+               for _, dep := range p.Internal.Imports {
+                       if _, ok := importerOf[dep.ImportPath]; !ok {
+                               importerOf[dep.ImportPath] = p.ImportPath
+                               q = append(q, dep)
                        }
                }
-               // Can't happen, but in case it does...
-               stk = append(stk, "<lost path to cycle>")
-               break
        }
-       return stk
+
+       panic("lost path to cycle")
 }
 
 // recompileForTest copies and replaces certain packages in pmain's dependency
@@ -576,7 +604,13 @@ type testFunc struct {
 var testFileSet = token.NewFileSet()
 
 func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error {
-       f, err := parser.ParseFile(testFileSet, filename, nil, parser.ParseComments)
+       // Pass in the overlaid source if we have an overlay for this file.
+       src, err := fsys.Open(filename)
+       if err != nil {
+               return err
+       }
+       defer src.Close()
+       f, err := parser.ParseFile(testFileSet, filename, src, parser.ParseComments)
        if err != nil {
                return err
        }
index ea480f8c2f6fa0c8666394bdbd1a5d3684462d2c..e302fe7fccf56bf761ddcf27d8c4478ff23e6778 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || (solaris && !illumos)
 // +build aix solaris,!illumos
 
 // This code implements the filelock API using POSIX 'fcntl' locks, which attach
index c09530d1b70b45ef3257547de157faeb9317cbc1..c6eac302c573f325316c5073d16a064fd095815b 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !aix && !darwin && !dragonfly && !freebsd && !hurd && !linux && !netbsd && !openbsd && !plan9 && !solaris && !windows
 // +build !aix,!darwin,!dragonfly,!freebsd,!hurd,!linux,!netbsd,!openbsd,!plan9,!solaris,!windows
 
 package filelock
index 0798ee469a46f40959bce21eea17ee36c5f6c360..908afb6c8cb7687d4d34545038b831e27434c2d8 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build plan9
 // +build plan9
 
 package filelock
index 2ac2052b8f57372dd674b5f8eb5fbdb15f198161..640d4406f4200cd1e44c426421955678feb66f91 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js && !plan9
 // +build !js,!plan9
 
 package filelock_test
index c06b0f77427df3adde49dcecba0399ed70a5d019..b22c0bb9918cad7e946e2da36f7a2f35133319bc 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || hurd || illumos || linux || netbsd || openbsd
 // +build darwin dragonfly freebsd hurd illumos linux netbsd openbsd
 
 package filelock
index 19de27eb9b6021ad9761712218ca1402a9d88f74..dd27ce92bd8d617449952f0c792f7966d10d2b84 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build windows
 // +build windows
 
 package filelock
index efc66461ed2fd6a2f12ca0b0440cc3f6ddb81f73..e4923f68764dad89a06539bbffccbe112e645996 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !plan9
 // +build !plan9
 
 package lockedfile
@@ -10,7 +11,6 @@ import (
        "io/fs"
        "os"
 
-       "cmd/go/internal/fsys"
        "cmd/go/internal/lockedfile/internal/filelock"
 )
 
@@ -20,7 +20,7 @@ func openFile(name string, flag int, perm fs.FileMode) (*os.File, error) {
        // calls for Linux and Windows anyway, so it's simpler to use that approach
        // consistently.
 
-       f, err := fsys.OpenFile(name, flag&^os.O_TRUNC, perm)
+       f, err := os.OpenFile(name, flag&^os.O_TRUNC, perm)
        if err != nil {
                return nil, err
        }
index 70d6eddf2d2da4b349e8de1ef114a986744aef91..979118b10ae83d13d01064ca3eb896f5b6a38d48 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build plan9
 // +build plan9
 
 package lockedfile
@@ -12,8 +13,6 @@ import (
        "os"
        "strings"
        "time"
-
-       "cmd/go/internal/fsys"
 )
 
 // Opening an exclusive-use file returns an error.
@@ -58,7 +57,7 @@ func openFile(name string, flag int, perm fs.FileMode) (*os.File, error) {
        // If the file was unpacked or created by some other program, it might not
        // have the ModeExclusive bit set. Set it before we call OpenFile, so that we
        // can be confident that a successful OpenFile implies exclusive use.
-       if fi, err := fsys.Stat(name); err == nil {
+       if fi, err := os.Stat(name); err == nil {
                if fi.Mode()&fs.ModeExclusive == 0 {
                        if err := os.Chmod(name, fi.Mode()|fs.ModeExclusive); err != nil {
                                return nil, err
@@ -71,7 +70,7 @@ func openFile(name string, flag int, perm fs.FileMode) (*os.File, error) {
        nextSleep := 1 * time.Millisecond
        const maxSleep = 500 * time.Millisecond
        for {
-               f, err := fsys.OpenFile(name, flag, perm|fs.ModeExclusive)
+               f, err := os.OpenFile(name, flag, perm|fs.ModeExclusive)
                if err == nil {
                        return f, nil
                }
index 34327dd841e112cbb17f9f2789ccb858fbee433f..3acc6695a748003e6f0fc7107bc49ffcf5995162 100644 (file)
@@ -3,6 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // js does not support inter-process file locking.
+//go:build !js
 // +build !js
 
 package lockedfile_test
index 407d48ea4a35f5cad06b31b70b8b9c8e1aaae681..b753346e7da50bccbb6d904a3f59c30648093153 100644 (file)
@@ -3,6 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // js does not support inter-process file locking.
+//go:build !js
 // +build !js
 
 package lockedfile_test
index a602bb9bbe9d50f6ea0d10812756ae69a11f0566..0e5af852376e76c5363d595d15c55f18d4acd8f6 100644 (file)
@@ -134,21 +134,18 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
        }
 
        var mods []*moduleJSON
-       listU := false
-       listVersions := false
-       listRetractions := false
        type token struct{}
        sem := make(chan token, runtime.GOMAXPROCS(0))
-       infos := modload.ListModules(ctx, args, listU, listVersions, listRetractions)
+       infos, infosErr := modload.ListModules(ctx, args, 0)
        if !haveExplicitArgs {
-               // 'go mod download' is sometimes run without arguments to pre-populate
-               // the module cache. It may fetch modules that aren't needed to build
-               // packages in the main mdoule. This is usually not intended, so don't save
-               // sums for downloaded modules (golang.org/issue/45332).
-               // TODO(golang.org/issue/45551): For now, save sums needed to load the
-               // build list (same as 1.15 behavior). In the future, report an error if
-               // go.mod or go.sum need to be updated after loading the build list.
-               modload.WriteGoMod()
+               // 'go mod download' is sometimes run without arguments to pre-populate the
+               // module cache. It may fetch modules that aren't needed to build packages
+               // in the main mdoule. This is usually not intended, so don't save sums for
+               // downloaded modules (golang.org/issue/45332).
+               // TODO(golang.org/issue/45551): For now, in ListModules, save sums needed
+               // to load the build list (same as 1.15 behavior). In the future, report an
+               // error if go.mod or go.sum need to be updated after loading the build
+               // list.
                modload.DisallowWriteGoMod()
        }
 
@@ -209,6 +206,13 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
        //
        // Don't save sums for 'go mod download' without arguments; see comment above.
        if haveExplicitArgs {
-               modload.WriteGoMod()
+               modload.WriteGoMod(ctx)
+       }
+
+       // If there was an error matching some of the requested packages, emit it now
+       // (after we've written the checksums for the modules that were downloaded
+       // successfully).
+       if infosErr != nil {
+               base.Errorf("go mod download: %v", infosErr)
        }
 }
index 1df104eb1dd54954a9670c5ee86a3372a2417067..bb3d5210926aef7993e93a8beb0fbd189859e399 100644 (file)
@@ -25,7 +25,7 @@ import (
 )
 
 var cmdEdit = &base.Command{
-       UsageLine: "go mod edit [editing flags] [go.mod]",
+       UsageLine: "go mod edit [editing flags] [-fmt|-print|-json] [go.mod]",
        Short:     "edit go.mod from tools or scripts",
        Long: `
 Edit provides a command-line interface for editing go.mod,
@@ -85,12 +85,12 @@ The -json flag prints the final go.mod file in JSON format instead of
 writing it back to go.mod. The JSON output corresponds to these Go types:
 
        type Module struct {
-               Path string
+               Path    string
                Version string
        }
 
        type GoMod struct {
-               Module  Module
+               Module  ModPath
                Go      string
                Require []Require
                Exclude []Module
@@ -98,6 +98,11 @@ writing it back to go.mod. The JSON output corresponds to these Go types:
                Retract []Retract
        }
 
+       type ModPath struct {
+               Path       string
+               Deprecated string
+       }
+
        type Require struct {
                Path string
                Version string
@@ -191,7 +196,7 @@ func runEdit(ctx context.Context, cmd *base.Command, args []string) {
 
        if *editGo != "" {
                if !modfile.GoVersionRE.MatchString(*editGo) {
-                       base.Fatalf(`go mod: invalid -go option; expecting something like "-go 1.12"`)
+                       base.Fatalf(`go mod: invalid -go option; expecting something like "-go %s"`, modload.LatestGoVersion())
                }
        }
 
@@ -450,7 +455,7 @@ func flagDropRetract(arg string) {
 
 // fileJSON is the -json output data structure.
 type fileJSON struct {
-       Module  module.Version
+       Module  editModuleJSON
        Go      string `json:",omitempty"`
        Require []requireJSON
        Exclude []module.Version
@@ -458,6 +463,11 @@ type fileJSON struct {
        Retract []retractJSON
 }
 
+type editModuleJSON struct {
+       Path       string
+       Deprecated string `json:",omitempty"`
+}
+
 type requireJSON struct {
        Path     string
        Version  string `json:",omitempty"`
@@ -479,7 +489,10 @@ type retractJSON struct {
 func editPrintJSON(modFile *modfile.File) {
        var f fileJSON
        if modFile.Module != nil {
-               f.Module = modFile.Module.Mod
+               f.Module = editModuleJSON{
+                       Path:       modFile.Module.Mod.Path,
+                       Deprecated: modFile.Module.Deprecated,
+               }
        }
        if modFile.Go != nil {
                f.Go = modFile.Go.Version
index a88e9ef4557ad3459cfe9db87f8af3fc63b2f591..ac81f26dadea69dd3f58d7491caaa39aba7cfcad 100644 (file)
@@ -10,7 +10,6 @@ import (
        "bufio"
        "context"
        "os"
-       "sort"
 
        "cmd/go/internal/base"
        "cmd/go/internal/modload"
@@ -19,7 +18,7 @@ import (
 )
 
 var cmdGraph = &base.Command{
-       UsageLine: "go mod graph",
+       UsageLine: "go mod graph [-go=version]",
        Short:     "print module requirement graph",
        Long: `
 Graph prints the module requirement graph (with replacements applied)
@@ -27,12 +26,21 @@ in text form. Each line in the output has two space-separated fields: a module
 and one of its requirements. Each module is identified as a string of the form
 path@version, except for the main module, which has no @version suffix.
 
+The -go flag causes graph to report the module graph as loaded by the
+given Go version, instead of the version indicated by the 'go' directive
+in the go.mod file.
+
 See https://golang.org/ref/mod#go-mod-graph for more about 'go mod graph'.
        `,
        Run: runGraph,
 }
 
+var (
+       graphGo goVersionFlag
+)
+
 func init() {
+       cmdGraph.Flag.Var(&graphGo, "go", "")
        base.AddModCommonFlags(&cmdGraph.Flag)
 }
 
@@ -42,43 +50,26 @@ func runGraph(ctx context.Context, cmd *base.Command, args []string) {
        }
        modload.ForceUseModules = true
        modload.RootMode = modload.NeedRoot
-       modload.LoadAllModules(ctx)
+       mg := modload.LoadModGraph(ctx, graphGo.String())
 
-       reqs := modload.MinReqs()
-       format := func(m module.Version) string {
-               if m.Version == "" {
-                       return m.Path
-               }
-               return m.Path + "@" + m.Version
-       }
+       w := bufio.NewWriter(os.Stdout)
+       defer w.Flush()
 
-       var out []string
-       var deps int // index in out where deps start
-       seen := map[module.Version]bool{modload.Target: true}
-       queue := []module.Version{modload.Target}
-       for len(queue) > 0 {
-               var m module.Version
-               m, queue = queue[0], queue[1:]
-               list, _ := reqs.Required(m)
-               for _, r := range list {
-                       if !seen[r] {
-                               queue = append(queue, r)
-                               seen[r] = true
-                       }
-                       out = append(out, format(m)+" "+format(r)+"\n")
-               }
-               if m == modload.Target {
-                       deps = len(out)
+       format := func(m module.Version) {
+               w.WriteString(m.Path)
+               if m.Version != "" {
+                       w.WriteString("@")
+                       w.WriteString(m.Version)
                }
        }
 
-       sort.Slice(out[deps:], func(i, j int) bool {
-               return out[deps+i][0] < out[deps+j][0]
+       mg.WalkBreadthFirst(func(m module.Version) {
+               reqs, _ := mg.RequiredBy(m)
+               for _, r := range reqs {
+                       format(m)
+                       w.WriteByte(' ')
+                       format(r)
+                       w.WriteByte('\n')
+               }
        })
-
-       w := bufio.NewWriter(os.Stdout)
-       for _, line := range out {
-               w.WriteString(line)
-       }
-       w.Flush()
 }
index 73cc282d81408a18dee2f405891fbc68813a7dc0..958c3066ac11082dee31fe8b0cc4f3f049124e5e 100644 (file)
@@ -13,7 +13,7 @@ import (
 )
 
 var cmdInit = &base.Command{
-       UsageLine: "go mod init [module]",
+       UsageLine: "go mod init [module-path]",
        Short:     "initialize new module in current directory",
        Long: `
 Init initializes and writes a new go.mod file in the current directory, in
index 67f90b123c3721bb2a8b87d64942766e852c7c77..fe25507e94f4fe365ec17d48b09e91be1109d702 100644 (file)
@@ -12,10 +12,14 @@ import (
        "cmd/go/internal/imports"
        "cmd/go/internal/modload"
        "context"
+       "fmt"
+
+       "golang.org/x/mod/modfile"
+       "golang.org/x/mod/semver"
 )
 
 var cmdTidy = &base.Command{
-       UsageLine: "go mod tidy [-e] [-v]",
+       UsageLine: "go mod tidy [-e] [-v] [-go=version] [-compat=version]",
        Short:     "add missing and remove unused modules",
        Long: `
 Tidy makes sure go.mod matches the source code in the module.
@@ -30,19 +34,65 @@ to standard error.
 The -e flag causes tidy to attempt to proceed despite errors
 encountered while loading packages.
 
+The -go flag causes tidy to update the 'go' directive in the go.mod
+file to the given version, which may change which module dependencies
+are retained as explicit requirements in the go.mod file.
+(Go versions 1.17 and higher retain more requirements in order to
+support lazy module loading.)
+
+The -compat flag preserves any additional checksums needed for the
+'go' command from the indicated major Go release to successfully load
+the module graph, and causes tidy to error out if that version of the
+'go' command would load any imported package from a different module
+version. By default, tidy acts as if the -compat flag were set to the
+version prior to the one indicated by the 'go' directive in the go.mod
+file.
+
 See https://golang.org/ref/mod#go-mod-tidy for more about 'go mod tidy'.
        `,
        Run: runTidy,
 }
 
-var tidyE bool // if true, report errors but proceed anyway.
+var (
+       tidyE      bool          // if true, report errors but proceed anyway.
+       tidyGo     goVersionFlag // go version to write to the tidied go.mod file (toggles lazy loading)
+       tidyCompat goVersionFlag // go version for which the tidied go.mod and go.sum files should be “compatible”
+)
 
 func init() {
        cmdTidy.Flag.BoolVar(&cfg.BuildV, "v", false, "")
        cmdTidy.Flag.BoolVar(&tidyE, "e", false, "")
+       cmdTidy.Flag.Var(&tidyGo, "go", "")
+       cmdTidy.Flag.Var(&tidyCompat, "compat", "")
        base.AddModCommonFlags(&cmdTidy.Flag)
 }
 
+// A goVersionFlag is a flag.Value representing a supported Go version.
+//
+// (Note that the -go argument to 'go mod edit' is *not* a goVersionFlag.
+// It intentionally allows newer-than-supported versions as arguments.)
+type goVersionFlag struct {
+       v string
+}
+
+func (f *goVersionFlag) String() string   { return f.v }
+func (f *goVersionFlag) Get() interface{} { return f.v }
+
+func (f *goVersionFlag) Set(s string) error {
+       if s != "" {
+               latest := modload.LatestGoVersion()
+               if !modfile.GoVersionRE.MatchString(s) {
+                       return fmt.Errorf("expecting a Go version like %q", latest)
+               }
+               if semver.Compare("v"+s, "v"+latest) > 0 {
+                       return fmt.Errorf("maximum supported Go version is %s", latest)
+               }
+       }
+
+       f.v = s
+       return nil
+}
+
 func runTidy(ctx context.Context, cmd *base.Command, args []string) {
        if len(args) > 0 {
                base.Fatalf("go mod tidy: no arguments allowed")
@@ -61,17 +111,15 @@ func runTidy(ctx context.Context, cmd *base.Command, args []string) {
        modload.ForceUseModules = true
        modload.RootMode = modload.NeedRoot
 
-       modload.CheckTidyVersion(ctx, tidyE)
-
        modload.LoadPackages(ctx, modload.PackageOpts{
+               GoVersion:                tidyGo.String(),
                Tags:                     imports.AnyTags(),
+               Tidy:                     true,
+               TidyCompatibleVersion:    tidyCompat.String(),
+               VendorModulesInGOROOTSrc: true,
                ResolveMissingImports:    true,
                LoadTests:                true,
                AllowErrors:              tidyE,
                SilenceMissingStdImports: true,
        }, "all")
-
-       modload.TidyBuildList()
-       modload.TrimGoSum()
-       modload.WriteGoMod()
 }
index ac1fb7720aad4c86e86cfab8a9193fcad4bde4ed..713d5f9f3faa6ac9fb58dffc561c96d2dd5b1b70 100644 (file)
@@ -13,6 +13,7 @@ import (
        "io"
        "io/fs"
        "os"
+       "path"
        "path/filepath"
        "sort"
        "strings"
@@ -65,6 +66,7 @@ func runVendor(ctx context.Context, cmd *base.Command, args []string) {
 
        loadOpts := modload.PackageOpts{
                Tags:                     imports.AnyTags(),
+               VendorModulesInGOROOTSrc: true,
                ResolveMissingImports:    true,
                UseVendorAll:             true,
                AllowErrors:              vendorE,
@@ -87,15 +89,23 @@ func runVendor(ctx context.Context, cmd *base.Command, args []string) {
        }
 
        includeAllReplacements := false
+       includeGoVersions := false
        isExplicit := map[module.Version]bool{}
-       if gv := modload.ModFile().Go; gv != nil && semver.Compare("v"+gv.Version, "v1.14") >= 0 {
-               // If the Go version is at least 1.14, annotate all explicit 'require' and
-               // 'replace' targets found in the go.mod file so that we can perform a
-               // stronger consistency check when -mod=vendor is set.
-               for _, r := range modload.ModFile().Require {
-                       isExplicit[r.Mod] = true
+       if gv := modload.ModFile().Go; gv != nil {
+               if semver.Compare("v"+gv.Version, "v1.14") >= 0 {
+                       // If the Go version is at least 1.14, annotate all explicit 'require' and
+                       // 'replace' targets found in the go.mod file so that we can perform a
+                       // stronger consistency check when -mod=vendor is set.
+                       for _, r := range modload.ModFile().Require {
+                               isExplicit[r.Mod] = true
+                       }
+                       includeAllReplacements = true
+               }
+               if semver.Compare("v"+gv.Version, "v1.17") >= 0 {
+                       // If the Go version is at least 1.17, annotate all modules with their
+                       // 'go' version directives.
+                       includeGoVersions = true
                }
-               includeAllReplacements = true
        }
 
        var vendorMods []module.Version
@@ -109,26 +119,35 @@ func runVendor(ctx context.Context, cmd *base.Command, args []string) {
        }
        module.Sort(vendorMods)
 
-       var buf bytes.Buffer
+       var (
+               buf bytes.Buffer
+               w   io.Writer = &buf
+       )
+       if cfg.BuildV {
+               w = io.MultiWriter(&buf, os.Stderr)
+       }
+
        for _, m := range vendorMods {
                line := moduleLine(m, modload.Replacement(m))
-               buf.WriteString(line)
-               if cfg.BuildV {
-                       os.Stderr.WriteString(line)
+               io.WriteString(w, line)
+
+               goVersion := ""
+               if includeGoVersions {
+                       goVersion = modload.ModuleInfo(ctx, m.Path).GoVersion
                }
-               if isExplicit[m] {
-                       buf.WriteString("## explicit\n")
-                       if cfg.BuildV {
-                               os.Stderr.WriteString("## explicit\n")
-                       }
+               switch {
+               case isExplicit[m] && goVersion != "":
+                       fmt.Fprintf(w, "## explicit; go %s\n", goVersion)
+               case isExplicit[m]:
+                       io.WriteString(w, "## explicit\n")
+               case goVersion != "":
+                       fmt.Fprintf(w, "## go %s\n", goVersion)
                }
+
                pkgs := modpkgs[m]
                sort.Strings(pkgs)
                for _, pkg := range pkgs {
-                       fmt.Fprintf(&buf, "%s\n", pkg)
-                       if cfg.BuildV {
-                               fmt.Fprintf(os.Stderr, "%s\n", pkg)
-                       }
+                       fmt.Fprintf(w, "%s\n", pkg)
                        vendorPkg(vdir, pkg)
                }
        }
@@ -281,7 +300,7 @@ func copyMetadata(modPath, pkg, dst, src string, copiedFiles map[string]bool) {
                if modPath == pkg {
                        break
                }
-               pkg = filepath.Dir(pkg)
+               pkg = path.Dir(pkg)
                dst = filepath.Dir(dst)
                src = filepath.Dir(src)
        }
@@ -322,6 +341,15 @@ func matchPotentialSourceFile(dir string, info fs.DirEntry) bool {
        if strings.HasSuffix(info.Name(), "_test.go") {
                return false
        }
+       if info.Name() == "go.mod" || info.Name() == "go.sum" {
+               if gv := modload.ModFile().Go; gv != nil && semver.Compare("v"+gv.Version, "v1.17") >= 0 {
+                       // As of Go 1.17, we strip go.mod and go.sum files from dependency modules.
+                       // Otherwise, 'go' commands invoked within the vendor subtree may misidentify
+                       // an arbitrary directory within the vendor tree as a module root.
+                       // (See https://golang.org/issue/42970.)
+                       return false
+               }
+       }
        if strings.HasSuffix(info.Name(), ".go") {
                f, err := fsys.Open(filepath.Join(dir, info.Name()))
                if err != nil {
index 832142913108976469a87a5ec4688b1ce9ae611a..5a6eca32cfb706bfcd50906937d9eec70e4fc4c4 100644 (file)
@@ -54,7 +54,8 @@ func runVerify(ctx context.Context, cmd *base.Command, args []string) {
        sem := make(chan token, runtime.GOMAXPROCS(0))
 
        // Use a slice of result channels, so that the output is deterministic.
-       mods := modload.LoadAllModules(ctx)[1:]
+       const defaultGoVersion = ""
+       mods := modload.LoadModGraph(ctx, defaultGoVersion).BuildList()[1:]
        errsChans := make([]<-chan []error, len(mods))
 
        for i, mod := range mods {
index a5f3e8afcbe3a52072e7265eecb7e117f9dabc78..3b14b27c8c780d954a133cd46dc4bee2f875e442 100644 (file)
@@ -68,22 +68,25 @@ func runWhy(ctx context.Context, cmd *base.Command, args []string) {
        modload.RootMode = modload.NeedRoot
 
        loadOpts := modload.PackageOpts{
-               Tags:          imports.AnyTags(),
-               LoadTests:     !*whyVendor,
-               SilenceErrors: true,
-               UseVendorAll:  *whyVendor,
+               Tags:                     imports.AnyTags(),
+               VendorModulesInGOROOTSrc: true,
+               LoadTests:                !*whyVendor,
+               SilencePackageErrors:     true,
+               UseVendorAll:             *whyVendor,
        }
 
        if *whyM {
-               listU := false
-               listVersions := false
-               listRetractions := false
                for _, arg := range args {
                        if strings.Contains(arg, "@") {
                                base.Fatalf("go mod why: module query not allowed")
                        }
                }
-               mods := modload.ListModules(ctx, args, listU, listVersions, listRetractions)
+
+               mods, err := modload.ListModules(ctx, args, 0)
+               if err != nil {
+                       base.Fatalf("go mod why: %v", err)
+               }
+
                byModule := make(map[module.Version][]string)
                _, pkgs := modload.LoadPackages(ctx, loadOpts, "all")
                for _, path := range pkgs {
index 5d4165c9443225163f6a50936c4d9ac2a3461dad..9c861f8e99e1537fd05d83f975ea5f85359fb797 100644 (file)
@@ -12,7 +12,6 @@ import (
        "strings"
 
        "cmd/go/internal/base"
-       "cmd/go/internal/modfetch"
 
        "golang.org/x/mod/modfile"
        "golang.org/x/mod/module"
@@ -21,7 +20,7 @@ import (
 
 // ConvertLegacyConfig converts legacy config to modfile.
 // The file argument is slash-delimited.
-func ConvertLegacyConfig(f *modfile.File, file string, data []byte) error {
+func ConvertLegacyConfig(f *modfile.File, file string, data []byte, queryPackage func(path, rev string) (module.Version, error)) error {
        i := strings.LastIndex(file, "/")
        j := -2
        if i >= 0 {
@@ -62,15 +61,13 @@ func ConvertLegacyConfig(f *modfile.File, file string, data []byte) error {
                sem <- token{}
                go func(i int, m module.Version) {
                        defer func() { <-sem }()
-                       repo, info, err := modfetch.ImportRepoRev(m.Path, m.Version)
+                       version, err := queryPackage(m.Path, m.Version)
                        if err != nil {
                                fmt.Fprintf(os.Stderr, "go: converting %s: stat %s@%s: %v\n", base.ShortPath(file), m.Path, m.Version, err)
                                return
                        }
 
-                       path := repo.ModulePath()
-                       versions[i].Path = path
-                       versions[i].Version = info.Version
+                       versions[i] = version
                }(i, m)
        }
        // Fill semaphore channel to wait for all tasks to finish.
diff --git a/libgo/go/cmd/go/internal/modconv/convert_test.go b/libgo/go/cmd/go/internal/modconv/convert_test.go
deleted file mode 100644 (file)
index 66b9ff4..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package modconv
-
-import (
-       "bytes"
-       "context"
-       "fmt"
-       "internal/testenv"
-       "log"
-       "os"
-       "os/exec"
-       "path/filepath"
-       "strings"
-       "testing"
-
-       "cmd/go/internal/cfg"
-       "cmd/go/internal/modfetch"
-
-       "golang.org/x/mod/modfile"
-       "golang.org/x/mod/module"
-)
-
-func TestMain(m *testing.M) {
-       os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
-       cfg.GOPROXY = "direct"
-
-       if _, err := exec.LookPath("git"); err != nil {
-               fmt.Fprintln(os.Stderr, "skipping because git binary not found")
-               fmt.Println("PASS")
-               return 0
-       }
-
-       dir, err := os.MkdirTemp("", "modconv-test-")
-       if err != nil {
-               log.Fatal(err)
-       }
-       defer os.RemoveAll(dir)
-       cfg.GOMODCACHE = filepath.Join(dir, "pkg/mod")
-
-       return m.Run()
-}
-
-func TestConvertLegacyConfig(t *testing.T) {
-       testenv.MustHaveExternalNetwork(t)
-
-       if testing.Verbose() {
-               old := cfg.BuildX
-               defer func() {
-                       cfg.BuildX = old
-               }()
-               cfg.BuildX = true
-       }
-
-       var tests = []struct {
-               path  string
-               vers  string
-               gomod string
-       }{
-               /*
-                       Different versions of git seem to find or not find
-                       github.com/Masterminds/semver's a93e51b5a57e,
-                       which is an unmerged pull request.
-                       We'd rather not provide access to unmerged pull requests,
-                       so the line is removed from the golden file here,
-                       but some git commands still find it somehow.
-
-                       {
-                               // Gopkg.lock parsing.
-                               "github.com/golang/dep", "v0.4.0",
-                               `module github.com/golang/dep
-
-                               require (
-                                       github.com/Masterminds/vcs v1.11.1
-                                       github.com/armon/go-radix v0.0.0-20160115234725-4239b77079c7
-                                       github.com/boltdb/bolt v1.3.1
-                                       github.com/go-yaml/yaml v0.0.0-20170407172122-cd8b52f8269e
-                                       github.com/golang/protobuf v0.0.0-20170901042739-5afd06f9d81a
-                                       github.com/jmank88/nuts v0.3.0
-                                       github.com/nightlyone/lockfile v0.0.0-20170707060451-e83dc5e7bba0
-                                       github.com/pelletier/go-toml v0.0.0-20171218135716-b8b5e7696574
-                                       github.com/pkg/errors v0.8.0
-                                       github.com/sdboyer/constext v0.0.0-20170321163424-836a14457353
-                                       golang.org/x/net v0.0.0-20170828231752-66aacef3dd8a
-                                       golang.org/x/sync v0.0.0-20170517211232-f52d1811a629
-                                       golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea
-                               )`,
-                       },
-               */
-
-               // TODO: https://github.com/docker/distribution uses vendor.conf
-
-               {
-                       // Godeps.json parsing.
-                       // TODO: Should v2.0.0 work here too?
-                       "github.com/docker/distribution", "v0.0.0-20150410205453-85de3967aa93",
-                       `module github.com/docker/distribution
-
-                       require (
-                               github.com/AdRoll/goamz v0.0.0-20150130162828-d3664b76d905
-                               github.com/MSOpenTech/azure-sdk-for-go v0.0.0-20150323223030-d90753bcad2e
-                               github.com/Sirupsen/logrus v0.7.3
-                               github.com/bugsnag/bugsnag-go v1.0.3-0.20141110184014-b1d153021fcd
-                               github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b
-                               github.com/bugsnag/panicwrap v0.0.0-20141110184334-e5f9854865b9
-                               github.com/codegangsta/cli v1.4.2-0.20150131031259-6086d7927ec3
-                               github.com/docker/docker v1.4.2-0.20150204013315-165ea5c158cf
-                               github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1
-                               github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7
-                               github.com/gorilla/context v0.0.0-20140604161150-14f550f51af5
-                               github.com/gorilla/handlers v0.0.0-20140825150757-0e84b7d810c1
-                               github.com/gorilla/mux v0.0.0-20140926153814-e444e69cbd2e
-                               github.com/jlhawn/go-crypto v0.0.0-20150401213827-cd738dde20f0
-                               github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43
-                               github.com/yvasiyarov/gorelic v0.0.7-0.20141212073537-a9bba5b9ab50
-                               github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f
-                               golang.org/x/net v0.0.0-20150202051010-1dfe7915deaf
-                               gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789
-                               gopkg.in/yaml.v2 v2.0.0-20150116202057-bef53efd0c76
-                       )`,
-               },
-
-               {
-                       // golang.org/issue/24585 - confusion about v2.0.0 tag in legacy non-v2 module
-                       "github.com/fishy/gcsbucket", "v0.0.0-20180217031846-618d60fe84e0",
-                       `module github.com/fishy/gcsbucket
-
-                       require (
-                               cloud.google.com/go v0.18.0
-                               github.com/fishy/fsdb v0.0.0-20180217030800-5527ded01371
-                               github.com/golang/protobuf v1.0.0
-                               github.com/googleapis/gax-go v2.0.0+incompatible
-                               golang.org/x/net v0.0.0-20180216171745-136a25c244d3
-                               golang.org/x/oauth2 v0.0.0-20180207181906-543e37812f10
-                               golang.org/x/text v0.3.1-0.20180208041248-4e4a3210bb54
-                               google.golang.org/api v0.0.0-20180217000815-c7a403bb5fe1
-                               google.golang.org/appengine v1.0.0
-                               google.golang.org/genproto v0.0.0-20180206005123-2b5a72b8730b
-                               google.golang.org/grpc v1.10.0
-                       )`,
-               },
-       }
-
-       ctx := context.Background()
-
-       for _, tt := range tests {
-               t.Run(strings.ReplaceAll(tt.path, "/", "_")+"_"+tt.vers, func(t *testing.T) {
-                       f, err := modfile.Parse("golden", []byte(tt.gomod), nil)
-                       if err != nil {
-                               t.Fatal(err)
-                       }
-                       want, err := f.Format()
-                       if err != nil {
-                               t.Fatal(err)
-                       }
-
-                       dir, err := modfetch.Download(ctx, module.Version{Path: tt.path, Version: tt.vers})
-                       if err != nil {
-                               t.Fatal(err)
-                       }
-
-                       for name := range Converters {
-                               file := filepath.Join(dir, name)
-                               data, err := os.ReadFile(file)
-                               if err == nil {
-                                       f := new(modfile.File)
-                                       f.AddModuleStmt(tt.path)
-                                       if err := ConvertLegacyConfig(f, filepath.ToSlash(file), data); err != nil {
-                                               t.Fatal(err)
-                                       }
-                                       out, err := f.Format()
-                                       if err != nil {
-                                               t.Fatalf("format after conversion: %v", err)
-                                       }
-                                       if !bytes.Equal(out, want) {
-                                               t.Fatalf("final go.mod:\n%s\n\nwant:\n%s", out, want)
-                                       }
-                                       return
-                               }
-                       }
-                       t.Fatalf("no converter found for %s@%s", tt.path, tt.vers)
-               })
-       }
-}
diff --git a/libgo/go/cmd/go/internal/modconv/testdata/traefik.dep b/libgo/go/cmd/go/internal/modconv/testdata/traefik.dep
new file mode 100644 (file)
index 0000000..8510f0f
--- /dev/null
@@ -0,0 +1,79 @@
+# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
+
+[[projects]]
+  name = "github.com/Nvveen/Gotty"
+  packages = ["."]
+  revision = "a8b993ba6abdb0e0c12b0125c603323a71c7790c"
+  source = "github.com/ijc25/Gotty"
+
+[[projects]]
+  branch = "master"
+  name = "github.com/OpenDNS/vegadns2client"
+  packages = ["."]
+  revision = "a3fa4a771d87bda2514a90a157e1fed1b6897d2e"
+
+[[projects]]
+  name = "github.com/PuerkitoBio/purell"
+  packages = ["."]
+  revision = "8a290539e2e8629dbc4e6bad948158f790ec31f4"
+  version = "v1.0.0"
+
+[[projects]]
+  name = "github.com/PuerkitoBio/urlesc"
+  packages = ["."]
+  revision = "5bd2802263f21d8788851d5305584c82a5c75d7e"
+
+[[projects]]
+  name = "github.com/Shopify/sarama"
+  packages = ["."]
+  revision = "70f6a705d4a17af059acbc6946fb2bd30762acd7"
+
+[[projects]]
+  name = "github.com/VividCortex/gohistogram"
+  packages = ["."]
+  revision = "51564d9861991fb0ad0f531c99ef602d0f9866e6"
+  version = "v1.0.0"
+
+[[projects]]
+  branch = "containous-fork"
+  name = "github.com/abbot/go-http-auth"
+  packages = ["."]
+  revision = "65b0cdae8d7fe5c05c7430e055938ef6d24a66c9"
+  source = "github.com/containous/go-http-auth"
+
+[[projects]]
+  branch = "master"
+  name = "github.com/abronan/valkeyrie"
+  packages = [
+    ".",
+    "store",
+    "store/boltdb",
+    "store/consul",
+    "store/etcd/v2",
+    "store/etcd/v3",
+    "store/zookeeper"
+  ]
+  revision = "063d875e3c5fd734fa2aa12fac83829f62acfc70"
+  
+[[projects]]
+  branch = "master"
+  name = "github.com/mesosphere/mesos-dns"
+  packages = [
+    "detect",
+    "errorutil",
+    "logging",
+    "models",
+    "records",
+    "records/labels",
+    "records/state",
+    "util"
+  ]
+  revision = "b47dc4c19f215e98da687b15b4c64e70f629bea5"
+  source = "git@github.com:containous/mesos-dns.git"
+
+  [[projects]]
+  name = "gopkg.in/fsnotify.v1"
+  packages = ["."]
+  revision = "629574ca2a5df945712d3079857300b5e4da0236"
+  source = "github.com/fsnotify/fsnotify"
+  version = "v1.4.2"
\ No newline at end of file
diff --git a/libgo/go/cmd/go/internal/modconv/testdata/traefik.out b/libgo/go/cmd/go/internal/modconv/testdata/traefik.out
new file mode 100644 (file)
index 0000000..5054295
--- /dev/null
@@ -0,0 +1,14 @@
+github.com/Nvveen/Gotty a8b993ba6abdb0e0c12b0125c603323a71c7790c
+github.com/OpenDNS/vegadns2client a3fa4a771d87bda2514a90a157e1fed1b6897d2e
+github.com/PuerkitoBio/purell v1.0.0
+github.com/PuerkitoBio/urlesc 5bd2802263f21d8788851d5305584c82a5c75d7e
+github.com/Shopify/sarama 70f6a705d4a17af059acbc6946fb2bd30762acd7
+github.com/VividCortex/gohistogram v1.0.0
+github.com/abbot/go-http-auth 65b0cdae8d7fe5c05c7430e055938ef6d24a66c9
+github.com/abronan/valkeyrie 063d875e3c5fd734fa2aa12fac83829f62acfc70
+github.com/mesosphere/mesos-dns b47dc4c19f215e98da687b15b4c64e70f629bea5
+gopkg.in/fsnotify.v1 v1.4.2
+replace: github.com/Nvveen/Gotty a8b993ba6abdb0e0c12b0125c603323a71c7790c github.com/ijc25/Gotty a8b993ba6abdb0e0c12b0125c603323a71c7790c
+replace: github.com/abbot/go-http-auth 65b0cdae8d7fe5c05c7430e055938ef6d24a66c9 github.com/containous/go-http-auth 65b0cdae8d7fe5c05c7430e055938ef6d24a66c9
+replace: github.com/mesosphere/mesos-dns b47dc4c19f215e98da687b15b4c64e70f629bea5 github.com/containous/mesos-dns b47dc4c19f215e98da687b15b4c64e70f629bea5
+replace: gopkg.in/fsnotify.v1 v1.4.2 github.com/fsnotify/fsnotify v1.4.2
index e4020b0b41e803f56dc2eed8d061d26d7a63f12b..ed694581a7c6af47ba12c789ece904fb15c1099c 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build cmd_go_bootstrap
 // +build cmd_go_bootstrap
 
 package modfetch
index 07e046c8cba7328a949e80f9e521130a3dd2396d..b01b4674131e7af76436c5b5513b6dbc1c155cbe 100644 (file)
@@ -11,8 +11,10 @@ import (
        "fmt"
        "io"
        "io/fs"
+       "math/rand"
        "os"
        "path/filepath"
+       "strconv"
        "strings"
        "sync"
 
@@ -21,17 +23,15 @@ import (
        "cmd/go/internal/lockedfile"
        "cmd/go/internal/modfetch/codehost"
        "cmd/go/internal/par"
-       "cmd/go/internal/renameio"
+       "cmd/go/internal/robustio"
 
        "golang.org/x/mod/module"
        "golang.org/x/mod/semver"
 )
 
 func cacheDir(path string) (string, error) {
-       if cfg.GOMODCACHE == "" {
-               // modload.Init exits if GOPATH[0] is empty, and cfg.GOMODCACHE
-               // is set to GOPATH[0]/pkg/mod if GOMODCACHE is empty, so this should never happen.
-               return "", fmt.Errorf("internal error: cfg.GOMODCACHE not set")
+       if err := checkCacheDir(); err != nil {
+               return "", err
        }
        enc, err := module.EscapePath(path)
        if err != nil {
@@ -64,10 +64,8 @@ func CachePath(m module.Version, suffix string) (string, error) {
 // along with the directory if the directory does not exist or if the directory
 // is not completely populated.
 func DownloadDir(m module.Version) (string, error) {
-       if cfg.GOMODCACHE == "" {
-               // modload.Init exits if GOPATH[0] is empty, and cfg.GOMODCACHE
-               // is set to GOPATH[0]/pkg/mod if GOMODCACHE is empty, so this should never happen.
-               return "", fmt.Errorf("internal error: cfg.GOMODCACHE not set")
+       if err := checkCacheDir(); err != nil {
+               return "", err
        }
        enc, err := module.EscapePath(m.Path)
        if err != nil {
@@ -108,7 +106,9 @@ func DownloadDir(m module.Version) (string, error) {
 
        // Check if a .ziphash file exists. It should be created before the
        // zip is extracted, but if it was deleted (by another program?), we need
-       // to re-calculate it.
+       // to re-calculate it. Note that checkMod will repopulate the ziphash
+       // file if it doesn't exist, but if the module is excluded by checks
+       // through GONOSUMDB or GOPRIVATE, that check and repopulation won't happen.
        ziphashPath, err := CachePath(m, "ziphash")
        if err != nil {
                return dir, err
@@ -146,15 +146,13 @@ func lockVersion(mod module.Version) (unlock func(), err error) {
        return lockedfile.MutexAt(path).Lock()
 }
 
-// SideLock locks a file within the module cache that that previously guarded
+// SideLock locks a file within the module cache that previously guarded
 // edits to files outside the cache, such as go.sum and go.mod files in the
 // user's working directory.
 // If err is nil, the caller MUST eventually call the unlock function.
 func SideLock() (unlock func(), err error) {
-       if cfg.GOMODCACHE == "" {
-               // modload.Init exits if GOPATH[0] is empty, and cfg.GOMODCACHE
-               // is set to GOPATH[0]/pkg/mod if GOMODCACHE is empty, so this should never happen.
-               base.Fatalf("go: internal error: cfg.GOMODCACHE not set")
+       if err := checkCacheDir(); err != nil {
+               return nil, err
        }
 
        path := filepath.Join(cfg.GOMODCACHE, "cache", "lock")
@@ -332,7 +330,7 @@ func InfoFile(path, version string) (string, error) {
        }
 
        // Stat should have populated the disk cache for us.
-       file, _, err := readDiskStat(path, version)
+       file, err := CachePath(module.Version{Path: path, Version: version}, "info")
        if err != nil {
                return "", err
        }
@@ -349,6 +347,9 @@ func GoMod(path, rev string) ([]byte, error) {
                if _, info, err := readDiskStat(path, rev); err == nil {
                        rev = info.Version
                } else {
+                       if errors.Is(err, statCacheErr) {
+                               return nil, err
+                       }
                        err := TryProxies(func(proxy string) error {
                                info, err := Lookup(proxy, path).Stat(rev)
                                if err == nil {
@@ -384,7 +385,7 @@ func GoModFile(path, version string) (string, error) {
                return "", err
        }
        // GoMod should have populated the disk cache for us.
-       file, _, err := readDiskGoMod(path, version)
+       file, err := CachePath(module.Version{Path: path, Version: version}, "mod")
        if err != nil {
                return "", err
        }
@@ -499,7 +500,7 @@ func readDiskStatByHash(path, rev string) (file string, info *RevInfo, err error
        for _, name := range names {
                if strings.HasSuffix(name, suffix) {
                        v := strings.TrimSuffix(name, ".info")
-                       if IsPseudoVersion(v) && semver.Compare(v, maxVersion) > 0 {
+                       if module.IsPseudoVersion(v) && semver.Compare(v, maxVersion) > 0 {
                                maxVersion = v
                                file, info, err = readDiskStat(path, strings.TrimSuffix(name, ".info"))
                        }
@@ -547,7 +548,7 @@ func readDiskCache(path, rev, suffix string) (file string, data []byte, err erro
        if err != nil {
                return "", nil, errNotCached
        }
-       data, err = renameio.ReadFile(file)
+       data, err = robustio.ReadFile(file)
        if err != nil {
                return file, nil, errNotCached
        }
@@ -584,7 +585,29 @@ func writeDiskCache(file string, data []byte) error {
                return err
        }
 
-       if err := renameio.WriteFile(file, data, 0666); err != nil {
+       // Write the file to a temporary location, and then rename it to its final
+       // path to reduce the likelihood of a corrupt file existing at that final path.
+       f, err := tempFile(filepath.Dir(file), filepath.Base(file), 0666)
+       if err != nil {
+               return err
+       }
+       defer func() {
+               // Only call os.Remove on f.Name() if we failed to rename it: otherwise,
+               // some other process may have created a new file with the same name after
+               // the rename completed.
+               if err != nil {
+                       f.Close()
+                       os.Remove(f.Name())
+               }
+       }()
+
+       if _, err := f.Write(data); err != nil {
+               return err
+       }
+       if err := f.Close(); err != nil {
+               return err
+       }
+       if err := robustio.Rename(f.Name(), file); err != nil {
                return err
        }
 
@@ -594,29 +617,49 @@ func writeDiskCache(file string, data []byte) error {
        return nil
 }
 
+// tempFile creates a new temporary file with given permission bits.
+func tempFile(dir, prefix string, perm fs.FileMode) (f *os.File, err error) {
+       for i := 0; i < 10000; i++ {
+               name := filepath.Join(dir, prefix+strconv.Itoa(rand.Intn(1000000000))+".tmp")
+               f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, perm)
+               if os.IsExist(err) {
+                       continue
+               }
+               break
+       }
+       return
+}
+
 // rewriteVersionList rewrites the version list in dir
 // after a new *.mod file has been written.
-func rewriteVersionList(dir string) {
+func rewriteVersionList(dir string) (err error) {
        if filepath.Base(dir) != "@v" {
                base.Fatalf("go: internal error: misuse of rewriteVersionList")
        }
 
        listFile := filepath.Join(dir, "list")
 
-       // We use a separate lockfile here instead of locking listFile itself because
-       // we want to use Rename to write the file atomically. The list may be read by
-       // a GOPROXY HTTP server, and if we crash midway through a rewrite (or if the
-       // HTTP server ignores our locking and serves the file midway through a
-       // rewrite) it's better to serve a stale list than a truncated one.
-       unlock, err := lockedfile.MutexAt(listFile + ".lock").Lock()
+       // Lock listfile when writing to it to try to avoid corruption to the file.
+       // Under rare circumstances, for instance, if the system loses power in the
+       // middle of a write it is possible for corrupt data to be written. This is
+       // not a problem for the go command itself, but may be an issue if the the
+       // cache is being served by a GOPROXY HTTP server. This will be corrected
+       // the next time a new version of the module is fetched and the file is rewritten.
+       // TODO(matloob): golang.org/issue/43313 covers adding a go mod verify
+       // command that removes module versions that fail checksums. It should also
+       // remove list files that are detected to be corrupt.
+       f, err := lockedfile.Edit(listFile)
        if err != nil {
-               base.Fatalf("go: can't lock version list lockfile: %v", err)
+               return err
        }
-       defer unlock()
-
+       defer func() {
+               if cerr := f.Close(); cerr != nil && err == nil {
+                       err = cerr
+               }
+       }()
        infos, err := os.ReadDir(dir)
        if err != nil {
-               return
+               return err
        }
        var list []string
        for _, info := range infos {
@@ -634,19 +677,74 @@ func rewriteVersionList(dir string) {
                        }
                }
        }
-       SortVersions(list)
+       semver.Sort(list)
 
        var buf bytes.Buffer
        for _, v := range list {
                buf.WriteString(v)
                buf.WriteString("\n")
        }
-       old, _ := renameio.ReadFile(listFile)
-       if bytes.Equal(buf.Bytes(), old) {
-               return
+       if fi, err := f.Stat(); err == nil && int(fi.Size()) == buf.Len() {
+               old := make([]byte, buf.Len()+1)
+               if n, err := f.ReadAt(old, 0); err == io.EOF && n == buf.Len() && bytes.Equal(buf.Bytes(), old) {
+                       return nil // No edit needed.
+               }
+       }
+       // Remove existing contents, so that when we truncate to the actual size it will zero-fill,
+       // and we will be able to detect (some) incomplete writes as files containing trailing NUL bytes.
+       if err := f.Truncate(0); err != nil {
+               return err
+       }
+       // Reserve the final size and zero-fill.
+       if err := f.Truncate(int64(buf.Len())); err != nil {
+               return err
+       }
+       // Write the actual contents. If this fails partway through,
+       // the remainder of the file should remain as zeroes.
+       if _, err := f.Write(buf.Bytes()); err != nil {
+               f.Truncate(0)
+               return err
        }
 
-       if err := renameio.WriteFile(listFile, buf.Bytes(), 0666); err != nil {
-               base.Fatalf("go: failed to write version list: %v", err)
+       return nil
+}
+
+var (
+       statCacheOnce sync.Once
+       statCacheErr  error
+)
+
+// checkCacheDir checks if the directory specified by GOMODCACHE exists. An
+// error is returned if it does not.
+func checkCacheDir() error {
+       if cfg.GOMODCACHE == "" {
+               // modload.Init exits if GOPATH[0] is empty, and cfg.GOMODCACHE
+               // is set to GOPATH[0]/pkg/mod if GOMODCACHE is empty, so this should never happen.
+               return fmt.Errorf("internal error: cfg.GOMODCACHE not set")
+       }
+       if !filepath.IsAbs(cfg.GOMODCACHE) {
+               return fmt.Errorf("GOMODCACHE entry is relative; must be absolute path: %q.\n", cfg.GOMODCACHE)
        }
+
+       // os.Stat is slow on Windows, so we only call it once to prevent unnecessary
+       // I/O every time this function is called.
+       statCacheOnce.Do(func() {
+               fi, err := os.Stat(cfg.GOMODCACHE)
+               if err != nil {
+                       if !os.IsNotExist(err) {
+                               statCacheErr = fmt.Errorf("could not create module cache: %w", err)
+                               return
+                       }
+                       if err := os.MkdirAll(cfg.GOMODCACHE, 0777); err != nil {
+                               statCacheErr = fmt.Errorf("could not create module cache: %w", err)
+                               return
+                       }
+                       return
+               }
+               if !fi.IsDir() {
+                       statCacheErr = fmt.Errorf("could not create module cache: %q is not a directory", cfg.GOMODCACHE)
+                       return
+               }
+       })
+       return statCacheErr
 }
index 72005e27d5eb83e75d56053dae51e64eb8ea63c8..4d4964edf447ebb7e963acd2c0defb74bb5957f6 100644 (file)
@@ -296,6 +296,9 @@ func (r *gitRepo) stat(rev string) (*RevInfo, error) {
        // Or maybe it's the prefix of a hash of a named ref.
        // Try to resolve to both a ref (git name) and full (40-hex-digit) commit hash.
        r.refsOnce.Do(r.loadRefs)
+       // loadRefs may return an error if git fails, for example segfaults, or
+       // could not load a private repo, but defer checking to the else block
+       // below, in case we already have the rev in question in the local cache.
        var ref, hash string
        if r.refs["refs/tags/"+rev] != "" {
                ref = "refs/tags/" + rev
@@ -332,6 +335,9 @@ func (r *gitRepo) stat(rev string) (*RevInfo, error) {
                        hash = rev
                }
        } else {
+               if r.refsErr != nil {
+                       return nil, r.refsErr
+               }
                return nil, &UnknownRevisionError{Rev: rev}
        }
 
index 89a73baad9d9c7f1329bca9da9a150b46429cafe..a684fa1a9bba9e4a253b19018840adf3b34c32ce 100644 (file)
@@ -8,7 +8,6 @@ import (
        "archive/zip"
        "bytes"
        "flag"
-       "fmt"
        "internal/testenv"
        "io"
        "io/fs"
@@ -47,12 +46,6 @@ var altRepos = []string{
 var localGitRepo string
 
 func testMain(m *testing.M) int {
-       if _, err := exec.LookPath("git"); err != nil {
-               fmt.Fprintln(os.Stderr, "skipping because git binary not found")
-               fmt.Println("PASS")
-               return 0
-       }
-
        dir, err := os.MkdirTemp("", "gitrepo-test-")
        if err != nil {
                log.Fatal(err)
@@ -60,23 +53,25 @@ func testMain(m *testing.M) int {
        defer os.RemoveAll(dir)
 
        if testenv.HasExternalNetwork() && testenv.HasExec() {
-               // Clone gitrepo1 into a local directory.
-               // If we use a file:// URL to access the local directory,
-               // then git starts up all the usual protocol machinery,
-               // which will let us test remote git archive invocations.
-               localGitRepo = filepath.Join(dir, "gitrepo2")
-               if _, err := Run("", "git", "clone", "--mirror", gitrepo1, localGitRepo); err != nil {
-                       log.Fatal(err)
-               }
-               if _, err := Run(localGitRepo, "git", "config", "daemon.uploadarch", "true"); err != nil {
-                       log.Fatal(err)
+               if _, err := exec.LookPath("git"); err == nil {
+                       // Clone gitrepo1 into a local directory.
+                       // If we use a file:// URL to access the local directory,
+                       // then git starts up all the usual protocol machinery,
+                       // which will let us test remote git archive invocations.
+                       localGitRepo = filepath.Join(dir, "gitrepo2")
+                       if _, err := Run("", "git", "clone", "--mirror", gitrepo1, localGitRepo); err != nil {
+                               log.Fatal(err)
+                       }
+                       if _, err := Run(localGitRepo, "git", "config", "daemon.uploadarch", "true"); err != nil {
+                               log.Fatal(err)
+                       }
                }
        }
 
        return m.Run()
 }
 
-func testRepo(remote string) (Repo, error) {
+func testRepo(t *testing.T, remote string) (Repo, error) {
        if remote == "localGitRepo" {
                // Convert absolute path to file URL. LocalGitRepo will not accept
                // Windows absolute paths because they look like a host:path remote.
@@ -87,15 +82,17 @@ func testRepo(remote string) (Repo, error) {
                } else {
                        url = "file:///" + filepath.ToSlash(localGitRepo)
                }
+               testenv.MustHaveExecPath(t, "git")
                return LocalGitRepo(url)
        }
-       kind := "git"
+       vcs := "git"
        for _, k := range []string{"hg"} {
                if strings.Contains(remote, "/"+k+"/") {
-                       kind = k
+                       vcs = k
                }
        }
-       return NewRepo(kind, remote)
+       testenv.MustHaveExecPath(t, vcs)
+       return NewRepo(vcs, remote)
 }
 
 var tagsTests = []struct {
@@ -116,7 +113,7 @@ func TestTags(t *testing.T) {
 
        for _, tt := range tagsTests {
                f := func(t *testing.T) {
-                       r, err := testRepo(tt.repo)
+                       r, err := testRepo(t, tt.repo)
                        if err != nil {
                                t.Fatal(err)
                        }
@@ -168,7 +165,7 @@ func TestLatest(t *testing.T) {
 
        for _, tt := range latestTests {
                f := func(t *testing.T) {
-                       r, err := testRepo(tt.repo)
+                       r, err := testRepo(t, tt.repo)
                        if err != nil {
                                t.Fatal(err)
                        }
@@ -221,7 +218,7 @@ func TestReadFile(t *testing.T) {
 
        for _, tt := range readFileTests {
                f := func(t *testing.T) {
-                       r, err := testRepo(tt.repo)
+                       r, err := testRepo(t, tt.repo)
                        if err != nil {
                                t.Fatal(err)
                        }
@@ -412,7 +409,7 @@ func TestReadZip(t *testing.T) {
 
        for _, tt := range readZipTests {
                f := func(t *testing.T) {
-                       r, err := testRepo(tt.repo)
+                       r, err := testRepo(t, tt.repo)
                        if err != nil {
                                t.Fatal(err)
                        }
@@ -581,7 +578,7 @@ func TestStat(t *testing.T) {
 
        for _, tt := range statTests {
                f := func(t *testing.T) {
-                       r, err := testRepo(tt.repo)
+                       r, err := testRepo(t, tt.repo)
                        if err != nil {
                                t.Fatal(err)
                        }
index ce8b501d53c8a565ce538d7f9fcc54d8f70e3bf1..0e9f38196676b108a28c77e9c2d5b591ecb0ae02 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 // Interactive debugging shell for codehost.Repo implementations.
index 2dcbb99b18514ae3abd52e78a3406810fae83f3a..dfef9f73c27aefa1bd3073706280a62f5cd8173e 100644 (file)
@@ -159,7 +159,7 @@ func (r *codeRepo) Versions(prefix string) ([]string, error) {
                if r.codeDir != "" {
                        v = v[len(r.codeDir)+1:]
                }
-               if v == "" || v != module.CanonicalVersion(v) || IsPseudoVersion(v) {
+               if v == "" || v != module.CanonicalVersion(v) || module.IsPseudoVersion(v) {
                        continue
                }
 
@@ -172,8 +172,8 @@ func (r *codeRepo) Versions(prefix string) ([]string, error) {
 
                list = append(list, v)
        }
-       SortVersions(list)
-       SortVersions(incompatible)
+       semver.Sort(list)
+       semver.Sort(incompatible)
 
        return r.appendIncompatibleVersions(list, incompatible)
 }
@@ -385,7 +385,7 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e
        if statVers != "" && statVers == module.CanonicalVersion(statVers) {
                info2.Version = statVers
 
-               if IsPseudoVersion(info2.Version) {
+               if module.IsPseudoVersion(info2.Version) {
                        if err := r.validatePseudoVersion(info, info2.Version); err != nil {
                                return nil, err
                        }
@@ -433,7 +433,7 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e
                }
                trimmed := tag[len(tagPrefix):]
                // Tags that look like pseudo-versions would be confusing. Ignore them.
-               if IsPseudoVersion(tag) {
+               if module.IsPseudoVersion(tag) {
                        return "", false
                }
 
@@ -531,7 +531,7 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e
                pseudoBase, _ = tagToVersion(tag) // empty if the tag is invalid
        }
 
-       info2.Version = PseudoVersion(r.pseudoMajor, pseudoBase, info.Time, info.Short)
+       info2.Version = module.PseudoVersion(r.pseudoMajor, pseudoBase, info.Time, info.Short)
        return checkGoMod()
 }
 
@@ -560,7 +560,7 @@ func (r *codeRepo) validatePseudoVersion(info *codehost.RevInfo, version string)
                return err
        }
 
-       rev, err := PseudoVersionRev(version)
+       rev, err := module.PseudoVersionRev(version)
        if err != nil {
                return err
        }
@@ -575,12 +575,12 @@ func (r *codeRepo) validatePseudoVersion(info *codehost.RevInfo, version string)
                }
        }
 
-       t, err := PseudoVersionTime(version)
+       t, err := module.PseudoVersionTime(version)
        if err != nil {
                return err
        }
        if !t.Equal(info.Time.Truncate(time.Second)) {
-               return fmt.Errorf("does not match version-control timestamp (expected %s)", info.Time.UTC().Format(pseudoVersionTimestampFormat))
+               return fmt.Errorf("does not match version-control timestamp (expected %s)", info.Time.UTC().Format(module.PseudoVersionTimestampFormat))
        }
 
        tagPrefix := ""
@@ -604,7 +604,7 @@ func (r *codeRepo) validatePseudoVersion(info *codehost.RevInfo, version string)
        // not enforce that property when resolving existing pseudo-versions: we don't
        // know when the parent tags were added, and the highest-tagged parent may not
        // have existed when the pseudo-version was first resolved.
-       base, err := PseudoVersionBase(strings.TrimSuffix(version, "+incompatible"))
+       base, err := module.PseudoVersionBase(strings.TrimSuffix(version, "+incompatible"))
        if err != nil {
                return err
        }
@@ -661,7 +661,7 @@ func (r *codeRepo) validatePseudoVersion(info *codehost.RevInfo, version string)
                if err != nil {
                        return err
                }
-               rev, err := PseudoVersionRev(version)
+               rev, err := module.PseudoVersionRev(version)
                if err != nil {
                        return fmt.Errorf("not a descendent of preceding tag (%s)", lastTag)
                }
@@ -672,8 +672,8 @@ func (r *codeRepo) validatePseudoVersion(info *codehost.RevInfo, version string)
 
 func (r *codeRepo) revToRev(rev string) string {
        if semver.IsValid(rev) {
-               if IsPseudoVersion(rev) {
-                       r, _ := PseudoVersionRev(rev)
+               if module.IsPseudoVersion(rev) {
+                       r, _ := module.PseudoVersionRev(rev)
                        return r
                }
                if semver.Build(rev) == "+incompatible" {
@@ -843,7 +843,7 @@ func (r *codeRepo) GoMod(version string) (data []byte, err error) {
                return nil, fmt.Errorf("version %s is not canonical", version)
        }
 
-       if IsPseudoVersion(version) {
+       if module.IsPseudoVersion(version) {
                // findDir ignores the metadata encoded in a pseudo-version,
                // only using the revision at the end.
                // Invoke Stat to verify the metadata explicitly so we don't return
@@ -864,22 +864,25 @@ func (r *codeRepo) GoMod(version string) (data []byte, err error) {
        data, err = r.code.ReadFile(rev, path.Join(dir, "go.mod"), codehost.MaxGoMod)
        if err != nil {
                if os.IsNotExist(err) {
-                       return r.legacyGoMod(rev, dir), nil
+                       return LegacyGoMod(r.modPath), nil
                }
                return nil, err
        }
        return data, nil
 }
 
-func (r *codeRepo) legacyGoMod(rev, dir string) []byte {
-       // We used to try to build a go.mod reflecting pre-existing
-       // package management metadata files, but the conversion
-       // was inherently imperfect (because those files don't have
-       // exactly the same semantics as go.mod) and, when done
-       // for dependencies in the middle of a build, impossible to
-       // correct. So we stopped.
-       // Return a fake go.mod that simply declares the module path.
-       return []byte(fmt.Sprintf("module %s\n", modfile.AutoQuote(r.modPath)))
+// LegacyGoMod generates a fake go.mod file for a module that doesn't have one.
+// The go.mod file contains a module directive and nothing else: no go version,
+// no requirements.
+//
+// We used to try to build a go.mod reflecting pre-existing
+// package management metadata files, but the conversion
+// was inherently imperfect (because those files don't have
+// exactly the same semantics as go.mod) and, when done
+// for dependencies in the middle of a build, impossible to
+// correct. So we stopped.
+func LegacyGoMod(modPath string) []byte {
+       return []byte(fmt.Sprintf("module %s\n", modfile.AutoQuote(modPath)))
 }
 
 func (r *codeRepo) modPrefix(rev string) string {
@@ -942,7 +945,7 @@ func (r *codeRepo) Zip(dst io.Writer, version string) error {
                return fmt.Errorf("version %s is not canonical", version)
        }
 
-       if IsPseudoVersion(version) {
+       if module.IsPseudoVersion(version) {
                // findDir ignores the metadata encoded in a pseudo-version,
                // only using the revision at the end.
                // Invoke Stat to verify the metadata explicitly so we don't return
index eb7d30e0ab9584a8fb47250b35cf8f2b716518a8..d3d30d970b3b979b14741ce2a2da38c8812a422c 100644 (file)
@@ -8,6 +8,8 @@ import (
        "archive/zip"
        "bytes"
        "context"
+       "crypto/sha256"
+       "encoding/base64"
        "errors"
        "fmt"
        "io"
@@ -20,9 +22,9 @@ import (
 
        "cmd/go/internal/base"
        "cmd/go/internal/cfg"
+       "cmd/go/internal/fsys"
        "cmd/go/internal/lockedfile"
        "cmd/go/internal/par"
-       "cmd/go/internal/renameio"
        "cmd/go/internal/robustio"
        "cmd/go/internal/trace"
 
@@ -37,10 +39,8 @@ var downloadCache par.Cache
 // local download cache and returns the name of the directory
 // corresponding to the root of the module's file tree.
 func Download(ctx context.Context, mod module.Version) (dir string, err error) {
-       if cfg.GOMODCACHE == "" {
-               // modload.Init exits if GOPATH[0] is empty, and cfg.GOMODCACHE
-               // is set to GOPATH[0]/pkg/mod if GOMODCACHE is empty, so this should never happen.
-               base.Fatalf("go: internal error: cfg.GOMODCACHE not set")
+       if err := checkCacheDir(); err != nil {
+               base.Fatalf("go: %v", err)
        }
 
        // The par.Cache here avoids duplicate work.
@@ -223,11 +223,10 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e
        // Clean up any remaining tempfiles from previous runs.
        // This is only safe to do because the lock file ensures that their
        // writers are no longer active.
-       for _, base := range []string{zipfile, zipfile + "hash"} {
-               if old, err := filepath.Glob(renameio.Pattern(base)); err == nil {
-                       for _, path := range old {
-                               os.Remove(path) // best effort
-                       }
+       tmpPattern := filepath.Base(zipfile) + "*.tmp"
+       if old, err := filepath.Glob(filepath.Join(filepath.Dir(zipfile), tmpPattern)); err == nil {
+               for _, path := range old {
+                       os.Remove(path) // best effort
                }
        }
 
@@ -242,7 +241,7 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e
        // contents of the file (by hashing it) before we commit it. Because the file
        // is zip-compressed, we need an actual file — or at least an io.ReaderAt — to
        // validate it: we can't just tee the stream as we write it.
-       f, err := os.CreateTemp(filepath.Dir(zipfile), filepath.Base(renameio.Pattern(zipfile)))
+       f, err := os.CreateTemp(filepath.Dir(zipfile), tmpPattern)
        if err != nil {
                return err
        }
@@ -298,12 +297,6 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e
                }
        }
 
-       // Sync the file before renaming it: otherwise, after a crash the reader may
-       // observe a 0-length file instead of the actual contents.
-       // See https://golang.org/issue/22397#issuecomment-380831736.
-       if err := f.Sync(); err != nil {
-               return err
-       }
        if err := f.Close(); err != nil {
                return err
        }
@@ -334,7 +327,21 @@ func hashZip(mod module.Version, zipfile, ziphashfile string) error {
        if err := checkModSum(mod, hash); err != nil {
                return err
        }
-       return renameio.WriteFile(ziphashfile, []byte(hash), 0666)
+       hf, err := lockedfile.Create(ziphashfile)
+       if err != nil {
+               return err
+       }
+       if err := hf.Truncate(int64(len(hash))); err != nil {
+               return err
+       }
+       if _, err := hf.WriteAt([]byte(hash), 0); err != nil {
+               return err
+       }
+       if err := hf.Close(); err != nil {
+               return err
+       }
+
+       return nil
 }
 
 // makeDirsReadOnly makes a best-effort attempt to remove write permissions for dir
@@ -410,7 +417,18 @@ func initGoSum() (bool, error) {
 
        goSum.m = make(map[module.Version][]string)
        goSum.status = make(map[modSum]modSumStatus)
-       data, err := lockedfile.Read(GoSumFile)
+       var (
+               data []byte
+               err  error
+       )
+       if actualSumFile, ok := fsys.OverlayPath(GoSumFile); ok {
+               // Don't lock go.sum if it's part of the overlay.
+               // On Plan 9, locking requires chmod, and we don't want to modify any file
+               // in the overlay. See #44700.
+               data, err = os.ReadFile(actualSumFile)
+       } else {
+               data, err = lockedfile.Read(GoSumFile)
+       }
        if err != nil && !os.IsNotExist(err) {
                return false, err
        }
@@ -485,11 +503,24 @@ func checkMod(mod module.Version) {
        if err != nil {
                base.Fatalf("verifying %v", module.VersionError(mod, err))
        }
-       data, err := renameio.ReadFile(ziphash)
+       data, err := lockedfile.Read(ziphash)
        if err != nil {
                base.Fatalf("verifying %v", module.VersionError(mod, err))
        }
-       h := strings.TrimSpace(string(data))
+       data = bytes.TrimSpace(data)
+       if !isValidSum(data) {
+               // Recreate ziphash file from zip file and use that to check the mod sum.
+               zip, err := CachePath(mod, "zip")
+               if err != nil {
+                       base.Fatalf("verifying %v", module.VersionError(mod, err))
+               }
+               err = hashZip(mod, zip, ziphash)
+               if err != nil {
+                       base.Fatalf("verifying %v", module.VersionError(mod, err))
+               }
+               return
+       }
+       h := string(data)
        if !strings.HasPrefix(h, "h1:") {
                base.Fatalf("verifying %v", module.VersionError(mod, fmt.Errorf("unexpected ziphash: %q", h)))
        }
@@ -634,11 +665,32 @@ func Sum(mod module.Version) string {
        if err != nil {
                return ""
        }
-       data, err := renameio.ReadFile(ziphash)
+       data, err := lockedfile.Read(ziphash)
        if err != nil {
                return ""
        }
-       return strings.TrimSpace(string(data))
+       data = bytes.TrimSpace(data)
+       if !isValidSum(data) {
+               return ""
+       }
+       return string(data)
+}
+
+// isValidSum returns true if data is the valid contents of a zip hash file.
+// Certain critical files are written to disk by first truncating
+// then writing the actual bytes, so that if the write fails
+// the corrupt file should contain at least one of the null
+// bytes written by the truncate operation.
+func isValidSum(data []byte) bool {
+       if bytes.IndexByte(data, '\000') >= 0 {
+               return false
+       }
+
+       if len(data) != len("h1:")+base64.StdEncoding.EncodedLen(sha256.Size) {
+               return false
+       }
+
+       return true
 }
 
 // WriteGoSum writes the go.sum file if it needs to be updated.
@@ -676,6 +728,9 @@ Outer:
        if cfg.BuildMod == "readonly" {
                base.Fatalf("go: updates to go.sum needed, disabled by -mod=readonly")
        }
+       if _, ok := fsys.OverlayPath(GoSumFile); ok {
+               base.Fatalf("go: updates to go.sum needed, but go.sum is part of the overlay specified with -overlay")
+       }
 
        // Make a best-effort attempt to acquire the side lock, only to exclude
        // previous versions of the 'go' command from making simultaneous edits.
diff --git a/libgo/go/cmd/go/internal/modfetch/insecure.go b/libgo/go/cmd/go/internal/modfetch/insecure.go
deleted file mode 100644 (file)
index 012d05f..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package modfetch
-
-import (
-       "cmd/go/internal/cfg"
-
-       "golang.org/x/mod/module"
-)
-
-// allowInsecure reports whether we are allowed to fetch this path in an insecure manner.
-func allowInsecure(path string) bool {
-       return cfg.Insecure || module.MatchPrefixPatterns(cfg.GOINSECURE, path)
-}
index 6c86d8d786d94a161f509a66fffcfbc9bb00189c..31d453c8074e6a52b4b9fe7009ef9ef79aba70e3 100644 (file)
@@ -228,7 +228,7 @@ func (p *proxyRepo) versionError(version string, err error) error {
                        Path: p.path,
                        Err: &module.InvalidVersionError{
                                Version: version,
-                               Pseudo:  IsPseudoVersion(version),
+                               Pseudo:  module.IsPseudoVersion(version),
                                Err:     err,
                        },
                }
@@ -276,11 +276,11 @@ func (p *proxyRepo) Versions(prefix string) ([]string, error) {
        var list []string
        for _, line := range strings.Split(string(data), "\n") {
                f := strings.Fields(line)
-               if len(f) >= 1 && semver.IsValid(f[0]) && strings.HasPrefix(f[0], prefix) && !IsPseudoVersion(f[0]) {
+               if len(f) >= 1 && semver.IsValid(f[0]) && strings.HasPrefix(f[0], prefix) && !module.IsPseudoVersion(f[0]) {
                        list = append(list, f[0])
                }
        }
-       SortVersions(list)
+       semver.Sort(list)
        return list, nil
 }
 
@@ -307,8 +307,8 @@ func (p *proxyRepo) latest() (*RevInfo, error) {
                        )
                        if len(f) >= 2 {
                                ft, _ = time.Parse(time.RFC3339, f[1])
-                       } else if IsPseudoVersion(f[0]) {
-                               ft, _ = PseudoVersionTime(f[0])
+                       } else if module.IsPseudoVersion(f[0]) {
+                               ft, _ = module.PseudoVersionTime(f[0])
                                ftIsFromPseudo = true
                        } else {
                                // Repo.Latest promises that this method is only called where there are
diff --git a/libgo/go/cmd/go/internal/modfetch/pseudo_test.go b/libgo/go/cmd/go/internal/modfetch/pseudo_test.go
deleted file mode 100644 (file)
index 4483f8e..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package modfetch
-
-import (
-       "testing"
-       "time"
-)
-
-var pseudoTests = []struct {
-       major   string
-       older   string
-       version string
-}{
-       {"", "", "v0.0.0-20060102150405-hash"},
-       {"v0", "", "v0.0.0-20060102150405-hash"},
-       {"v1", "", "v1.0.0-20060102150405-hash"},
-       {"v2", "", "v2.0.0-20060102150405-hash"},
-       {"unused", "v0.0.0", "v0.0.1-0.20060102150405-hash"},
-       {"unused", "v1.2.3", "v1.2.4-0.20060102150405-hash"},
-       {"unused", "v1.2.99999999999999999", "v1.2.100000000000000000-0.20060102150405-hash"},
-       {"unused", "v1.2.3-pre", "v1.2.3-pre.0.20060102150405-hash"},
-       {"unused", "v1.3.0-pre", "v1.3.0-pre.0.20060102150405-hash"},
-       {"unused", "v0.0.0--", "v0.0.0--.0.20060102150405-hash"},
-       {"unused", "v1.0.0+metadata", "v1.0.1-0.20060102150405-hash+metadata"},
-       {"unused", "v2.0.0+incompatible", "v2.0.1-0.20060102150405-hash+incompatible"},
-       {"unused", "v2.3.0-pre+incompatible", "v2.3.0-pre.0.20060102150405-hash+incompatible"},
-}
-
-var pseudoTime = time.Date(2006, 1, 2, 15, 4, 5, 0, time.UTC)
-
-func TestPseudoVersion(t *testing.T) {
-       for _, tt := range pseudoTests {
-               v := PseudoVersion(tt.major, tt.older, pseudoTime, "hash")
-               if v != tt.version {
-                       t.Errorf("PseudoVersion(%q, %q, ...) = %v, want %v", tt.major, tt.older, v, tt.version)
-               }
-       }
-}
-
-func TestIsPseudoVersion(t *testing.T) {
-       for _, tt := range pseudoTests {
-               if !IsPseudoVersion(tt.version) {
-                       t.Errorf("IsPseudoVersion(%q) = false, want true", tt.version)
-               }
-               if IsPseudoVersion(tt.older) {
-                       t.Errorf("IsPseudoVersion(%q) = true, want false", tt.older)
-               }
-       }
-}
-
-func TestPseudoVersionTime(t *testing.T) {
-       for _, tt := range pseudoTests {
-               tm, err := PseudoVersionTime(tt.version)
-               if tm != pseudoTime || err != nil {
-                       t.Errorf("PseudoVersionTime(%q) = %v, %v, want %v, nil", tt.version, tm.Format(time.RFC3339), err, pseudoTime.Format(time.RFC3339))
-               }
-               tm, err = PseudoVersionTime(tt.older)
-               if tm != (time.Time{}) || err == nil {
-                       t.Errorf("PseudoVersionTime(%q) = %v, %v, want %v, error", tt.older, tm.Format(time.RFC3339), err, time.Time{}.Format(time.RFC3339))
-               }
-       }
-}
-
-func TestInvalidPseudoVersionTime(t *testing.T) {
-       const v = "---"
-       if _, err := PseudoVersionTime(v); err == nil {
-               t.Error("expected error, got nil instead")
-       }
-}
-
-func TestPseudoVersionRev(t *testing.T) {
-       for _, tt := range pseudoTests {
-               rev, err := PseudoVersionRev(tt.version)
-               if rev != "hash" || err != nil {
-                       t.Errorf("PseudoVersionRev(%q) = %q, %v, want %q, nil", tt.older, rev, err, "hash")
-               }
-               rev, err = PseudoVersionRev(tt.older)
-               if rev != "" || err == nil {
-                       t.Errorf("PseudoVersionRev(%q) = %q, %v, want %q, error", tt.older, rev, err, "")
-               }
-       }
-}
-
-func TestPseudoVersionBase(t *testing.T) {
-       for _, tt := range pseudoTests {
-               base, err := PseudoVersionBase(tt.version)
-               if err != nil {
-                       t.Errorf("PseudoVersionBase(%q): %v", tt.version, err)
-               } else if base != tt.older {
-                       t.Errorf("PseudoVersionBase(%q) = %q; want %q", tt.version, base, tt.older)
-               }
-       }
-}
-
-func TestInvalidPseudoVersionBase(t *testing.T) {
-       for _, in := range []string{
-               "v0.0.0",
-               "v0.0.0-",                                 // malformed: empty prerelease
-               "v0.0.0-0.20060102150405-hash",            // Z+1 == 0
-               "v0.1.0-0.20060102150405-hash",            // Z+1 == 0
-               "v1.0.0-0.20060102150405-hash",            // Z+1 == 0
-               "v0.0.0-20060102150405-hash+incompatible", // "+incompatible without base version
-               "v0.0.0-20060102150405-hash+metadata",     // other metadata without base version
-       } {
-               base, err := PseudoVersionBase(in)
-               if err == nil || base != "" {
-                       t.Errorf(`PseudoVersionBase(%q) = %q, %v; want "", error`, in, base, err)
-               }
-       }
-}
-
-func TestIncDecimal(t *testing.T) {
-       cases := []struct {
-               in, want string
-       }{
-               {"0", "1"},
-               {"1", "2"},
-               {"99", "100"},
-               {"100", "101"},
-               {"101", "102"},
-       }
-
-       for _, tc := range cases {
-               got := incDecimal(tc.in)
-               if got != tc.want {
-                       t.Fatalf("incDecimal(%q) = %q; want %q", tc.in, tc.want, got)
-               }
-       }
-}
-
-func TestDecDecimal(t *testing.T) {
-       cases := []struct {
-               in, want string
-       }{
-               {"", ""},
-               {"0", ""},
-               {"00", ""},
-               {"1", "0"},
-               {"2", "1"},
-               {"99", "98"},
-               {"100", "99"},
-               {"101", "100"},
-       }
-
-       for _, tc := range cases {
-               got := decDecimal(tc.in)
-               if got != tc.want {
-                       t.Fatalf("decDecimal(%q) = %q; want %q", tc.in, tc.want, got)
-               }
-       }
-}
index af9e24cefdc8dd3e82463280511020a53fe5e3f8..0bffa55af6f2ed6c4b12ec8363a8bb4f7f434bc6 100644 (file)
@@ -9,7 +9,6 @@ import (
        "io"
        "io/fs"
        "os"
-       "sort"
        "strconv"
        "time"
 
@@ -20,7 +19,6 @@ import (
        web "cmd/go/internal/web"
 
        "golang.org/x/mod/module"
-       "golang.org/x/mod/semver"
 )
 
 const traceRepo = false // trace all repo actions, for debugging
@@ -35,7 +33,7 @@ type Repo interface {
        // Pseudo-versions are not included.
        //
        // Versions should be returned sorted in semver order
-       // (implementations can use SortVersions).
+       // (implementations can use semver.Sort).
        //
        // Versions returns a non-nil error only if there was a problem
        // fetching the list of versions: it may return an empty list
@@ -171,15 +169,6 @@ type RevInfo struct {
 // and it can check that the path can be resolved to a target repository.
 // To avoid version control access except when absolutely necessary,
 // Lookup does not attempt to connect to the repository itself.
-//
-// The ImportRepoRev function is a variant of Import which is limited
-// to code in a source code repository at a particular revision identifier
-// (usually a commit hash or source code repository tag, not necessarily
-// a module version).
-// ImportRepoRev is used when converting legacy dependency requirements
-// from older systems into go.mod files. Those older systems worked
-// at either package or repository granularity, and most of the time they
-// recorded commit hashes, not tagged versions.
 
 var lookupCache par.Cache
 
@@ -194,7 +183,8 @@ type lookupCacheKey struct {
 // from its origin, and "noproxy" indicates that the patch should be fetched
 // directly only if GONOPROXY matches the given path.
 //
-// For the distinguished proxy "off", Lookup always returns a non-nil error.
+// For the distinguished proxy "off", Lookup always returns a Repo that returns
+// a non-nil error for every method call.
 //
 // A successful return does not guarantee that the module
 // has any defined versions.
@@ -267,7 +257,7 @@ var (
 func lookupDirect(path string) (Repo, error) {
        security := web.SecureOnly
 
-       if allowInsecure(path) {
+       if module.MatchPrefixPatterns(cfg.GOINSECURE, path) {
                security = web.Insecure
        }
        rr, err := vcs.RepoRootForImportPath(path, vcs.PreferMod, security)
@@ -299,63 +289,6 @@ func lookupCodeRepo(rr *vcs.RepoRoot) (codehost.Repo, error) {
        return code, nil
 }
 
-// ImportRepoRev returns the module and version to use to access
-// the given import path loaded from the source code repository that
-// the original "go get" would have used, at the specific repository revision
-// (typically a commit hash, but possibly also a source control tag).
-func ImportRepoRev(path, rev string) (Repo, *RevInfo, error) {
-       if cfg.BuildMod == "vendor" || cfg.BuildMod == "readonly" {
-               return nil, nil, fmt.Errorf("repo version lookup disabled by -mod=%s", cfg.BuildMod)
-       }
-
-       // Note: Because we are converting a code reference from a legacy
-       // version control system, we ignore meta tags about modules
-       // and use only direct source control entries (get.IgnoreMod).
-       security := web.SecureOnly
-       if allowInsecure(path) {
-               security = web.Insecure
-       }
-       rr, err := vcs.RepoRootForImportPath(path, vcs.IgnoreMod, security)
-       if err != nil {
-               return nil, nil, err
-       }
-
-       code, err := lookupCodeRepo(rr)
-       if err != nil {
-               return nil, nil, err
-       }
-
-       revInfo, err := code.Stat(rev)
-       if err != nil {
-               return nil, nil, err
-       }
-
-       // TODO: Look in repo to find path, check for go.mod files.
-       // For now we're just assuming rr.Root is the module path,
-       // which is true in the absence of go.mod files.
-
-       repo, err := newCodeRepo(code, rr.Root, rr.Root)
-       if err != nil {
-               return nil, nil, err
-       }
-
-       info, err := repo.(*codeRepo).convert(revInfo, rev)
-       if err != nil {
-               return nil, nil, err
-       }
-       return repo, info, nil
-}
-
-func SortVersions(list []string) {
-       sort.Slice(list, func(i, j int) bool {
-               cmp := semver.Compare(list[i], list[j])
-               if cmp != 0 {
-                       return cmp < 0
-               }
-               return list[i] < list[j]
-       })
-}
-
 // A loggingRepo is a wrapper around an underlying Repo
 // that prints a log message at the start and end of each call.
 // It can be inserted when debugging.
index 4fbc54d15ce837ba73fe28f65a7c85a602de47da..f233cba6df1bb7e996735147834e9c40960158f4 100644 (file)
@@ -4,6 +4,7 @@
 
 // Go checksum database lookup
 
+//go:build !cmd_go_bootstrap
 // +build !cmd_go_bootstrap
 
 package modfetch
@@ -33,7 +34,7 @@ import (
 
 // useSumDB reports whether to use the Go checksum database for the given module.
 func useSumDB(mod module.Version) bool {
-       return cfg.GOSUMDB != "off" && !cfg.Insecure && !module.MatchPrefixPatterns(cfg.GONOSUMDB, mod.Path)
+       return cfg.GOSUMDB != "off" && !module.MatchPrefixPatterns(cfg.GONOSUMDB, mod.Path)
 }
 
 // lookupSumDB returns the Go checksum database's go.sum lines for the given module,
@@ -184,7 +185,7 @@ func (c *dbClient) initBase() {
                }
        })
        if errors.Is(err, fs.ErrNotExist) {
-               // No proxies, or all proxies failed (with 404, 410, or were were allowed
+               // No proxies, or all proxies failed (with 404, 410, or were allowed
                // to fall back), or we reached an explicit "direct" or "off".
                c.base = c.direct
        } else if err != nil {
index 5a98408a325fb35f02f6a597727793af11032e9a..9672e5598e0d3a980570899a4770925effaee087 100644 (file)
@@ -30,16 +30,15 @@ import (
        "fmt"
        "os"
        "path/filepath"
-       "reflect"
        "runtime"
        "sort"
        "strings"
        "sync"
 
        "cmd/go/internal/base"
-       "cmd/go/internal/cfg"
        "cmd/go/internal/imports"
        "cmd/go/internal/load"
+       "cmd/go/internal/modfetch"
        "cmd/go/internal/modload"
        "cmd/go/internal/par"
        "cmd/go/internal/search"
@@ -53,7 +52,7 @@ import (
 var CmdGet = &base.Command{
        // Note: -d -u are listed explicitly because they are the most common get flags.
        // Do not send CLs removing them because they're covered by [get flags].
-       UsageLine: "go get [-d] [-t] [-u] [-v] [-insecure] [build flags] [packages]",
+       UsageLine: "go get [-d] [-t] [-u] [-v] [build flags] [packages]",
        Short:     "add dependencies to current module and install them",
        Long: `
 Get resolves its command-line arguments to packages at specific module versions,
@@ -99,14 +98,6 @@ but changes the default to select patch releases.
 When the -t and -u flags are used together, get will update
 test dependencies as well.
 
-The -insecure flag permits fetching from repositories and resolving
-custom domains using insecure schemes such as HTTP, and also bypassess
-module sum validation using the checksum database. Use with caution.
-This flag is deprecated and will be removed in a future version of go.
-To permit the use of insecure schemes, use the GOINSECURE environment
-variable instead. To bypass module sum validation, use GOPRIVATE or
-GONOSUMDB. See 'go help environment' for details.
-
 The -d flag instructs get not to build or install packages. get will only
 update go.mod and download source code needed to build packages.
 
@@ -227,13 +218,13 @@ variable for future go command invocations.
 }
 
 var (
-       getD   = CmdGet.Flag.Bool("d", false, "")
-       getF   = CmdGet.Flag.Bool("f", false, "")
-       getFix = CmdGet.Flag.Bool("fix", false, "")
-       getM   = CmdGet.Flag.Bool("m", false, "")
-       getT   = CmdGet.Flag.Bool("t", false, "")
-       getU   upgradeFlag
-       // -insecure is cfg.Insecure
+       getD        = CmdGet.Flag.Bool("d", false, "")
+       getF        = CmdGet.Flag.Bool("f", false, "")
+       getFix      = CmdGet.Flag.Bool("fix", false, "")
+       getM        = CmdGet.Flag.Bool("m", false, "")
+       getT        = CmdGet.Flag.Bool("t", false, "")
+       getU        upgradeFlag
+       getInsecure = CmdGet.Flag.Bool("insecure", false, "")
        // -v is cfg.BuildV
 )
 
@@ -264,7 +255,6 @@ func (v *upgradeFlag) String() string { return "" }
 func init() {
        work.AddBuildFlags(CmdGet, work.OmitModFlag)
        CmdGet.Run = runGet // break init loop
-       CmdGet.Flag.BoolVar(&cfg.Insecure, "insecure", cfg.Insecure, "")
        CmdGet.Flag.Var(&getU, "u", "")
 }
 
@@ -284,10 +274,9 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) {
        if *getM {
                base.Fatalf("go get: -m flag is no longer supported; consider -d to skip building packages")
        }
-       if cfg.Insecure {
-               fmt.Fprintf(os.Stderr, "go get: -insecure flag is deprecated; see 'go help get' for details\n")
+       if *getInsecure {
+               base.Fatalf("go get: -insecure flag is no longer supported; use GOINSECURE instead")
        }
-       load.ModResolveTests = *getT
 
        // Do not allow any updating of go.mod until we've applied
        // all the requested changes and checked that the result matches
@@ -298,8 +287,6 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) {
        // 'go get' is expected to do this, unlike other commands.
        modload.AllowMissingModuleImports()
 
-       modload.LoadModFile(ctx) // Initializes modload.Target.
-
        queries := parseArgs(ctx, args)
 
        r := newResolver(ctx, queries)
@@ -310,7 +297,7 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) {
                r.performWildcardQueries(ctx)
                r.performPatternAllQueries(ctx)
 
-               if changed := r.resolveCandidates(ctx, queries, nil); changed {
+               if changed := r.resolveQueries(ctx, queries); changed {
                        // 'go get' arguments can be (and often are) package patterns rather than
                        // (just) modules. A package can be provided by any module with a prefix
                        // of its import path, and a wildcard can even match packages in modules
@@ -347,12 +334,12 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) {
                // - ambiguous import errors.
                //   TODO(#27899): Try to resolve ambiguous import errors automatically.
                upgrades := r.findAndUpgradeImports(ctx, queries)
-               if changed := r.resolveCandidates(ctx, nil, upgrades); changed {
+               if changed := r.applyUpgrades(ctx, upgrades); changed {
                        continue
                }
 
                r.findMissingWildcards(ctx)
-               if changed := r.resolveCandidates(ctx, r.wildcardQueries, nil); changed {
+               if changed := r.resolveQueries(ctx, r.wildcardQueries); changed {
                        continue
                }
 
@@ -367,7 +354,7 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) {
                        pkgPatterns = append(pkgPatterns, q.pattern)
                }
        }
-       r.checkPackagesAndRetractions(ctx, pkgPatterns)
+       r.checkPackageProblems(ctx, pkgPatterns)
 
        // We've already downloaded modules (and identified direct and indirect
        // dependencies) by loading packages in findAndUpgradeImports.
@@ -380,12 +367,51 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) {
        // directory.
        if !*getD && len(pkgPatterns) > 0 {
                work.BuildInit()
-               pkgs := load.PackagesAndErrors(ctx, pkgPatterns)
+
+               pkgOpts := load.PackageOpts{ModResolveTests: *getT}
+               var pkgs []*load.Package
+               for _, pkg := range load.PackagesAndErrors(ctx, pkgOpts, pkgPatterns) {
+                       if pkg.Error != nil {
+                               var noGo *load.NoGoError
+                               if errors.As(pkg.Error.Err, &noGo) {
+                                       if m := modload.PackageModule(pkg.ImportPath); m.Path == pkg.ImportPath {
+                                               // pkg is at the root of a module, and doesn't exist with the current
+                                               // build tags. Probably the user just wanted to change the version of
+                                               // that module — not also build the package — so suppress the error.
+                                               // (See https://golang.org/issue/33526.)
+                                               continue
+                                       }
+                               }
+                       }
+                       pkgs = append(pkgs, pkg)
+               }
                load.CheckPackageErrors(pkgs)
+
+               haveExternalExe := false
+               for _, pkg := range pkgs {
+                       if pkg.Name == "main" && pkg.Module != nil && pkg.Module.Path != modload.Target.Path {
+                               haveExternalExe = true
+                               break
+                       }
+               }
+               if haveExternalExe {
+                       fmt.Fprint(os.Stderr, "go get: installing executables with 'go get' in module mode is deprecated.")
+                       var altMsg string
+                       if modload.HasModRoot() {
+                               altMsg = `
+       To adjust and download dependencies of the current module, use 'go get -d'.
+       To install using requirements of the current module, use 'go install'.
+       To install ignoring the current module, use 'go install' with a version,
+       like 'go install example.com/cmd@latest'.
+`
+                       } else {
+                               altMsg = "\n\tUse 'go install pkg@version' instead.\n"
+                       }
+                       fmt.Fprint(os.Stderr, altMsg)
+                       fmt.Fprintf(os.Stderr, "\tFor more information, see https://golang.org/doc/go-get-install-deprecation\n\tor run 'go help get' or 'go help install'.\n")
+               }
+
                work.InstallPackages(ctx, pkgPatterns, pkgs)
-               // TODO(#40276): After Go 1.16, print a deprecation notice when building and
-               // installing main packages. 'go install pkg' or 'go install pkg@version'
-               // should be used instead. Give the specific argument to use if possible.
        }
 
        if !modload.HasModRoot() {
@@ -396,7 +422,7 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) {
        oldReqs := reqsFromGoMod(modload.ModFile())
 
        modload.AllowWriteGoMod()
-       modload.WriteGoMod()
+       modload.WriteGoMod(ctx)
        modload.DisallowWriteGoMod()
 
        newReqs := reqsFromGoMod(modload.ModFile())
@@ -460,9 +486,8 @@ type resolver struct {
        // that resolved the module to that version (the “reason”).
        resolvedVersion map[string]versionReason
 
-       buildList                 []module.Version
-       buildListResolvedVersions int               // len(resolvedVersion) when buildList was computed
-       buildListVersion          map[string]string // index of buildList (module path → version)
+       buildList        []module.Version
+       buildListVersion map[string]string // index of buildList (module path → version)
 
        initialVersion map[string]string // index of the initial build list at the start of 'go get'
 
@@ -479,7 +504,12 @@ type versionReason struct {
 }
 
 func newResolver(ctx context.Context, queries []*query) *resolver {
-       buildList := modload.LoadAllModules(ctx)
+       // LoadModGraph also sets modload.Target, which is needed by various resolver
+       // methods.
+       const defaultGoVersion = ""
+       mg := modload.LoadModGraph(ctx, defaultGoVersion)
+
+       buildList := mg.BuildList()
        initialVersion := make(map[string]string, len(buildList))
        for _, m := range buildList {
                initialVersion[m.Path] = m.Version
@@ -688,7 +718,7 @@ func (r *resolver) performLocalQueries(ctx context.Context) {
 
                        // Absolute paths like C:\foo and relative paths like ../foo... are
                        // restricted to matching packages in the main module.
-                       pkgPattern := modload.DirImportPath(q.pattern)
+                       pkgPattern := modload.DirImportPath(ctx, q.pattern)
                        if pkgPattern == "." {
                                return errSet(fmt.Errorf("%s%s is not within module rooted at %s", q.pattern, absDetail, modload.ModRoot()))
                        }
@@ -1121,9 +1151,11 @@ func (r *resolver) findAndUpgradeImports(ctx context.Context, queries []*query)
 // build list.
 func (r *resolver) loadPackages(ctx context.Context, patterns []string, findPackage func(ctx context.Context, path string, m module.Version) (versionOk bool)) {
        opts := modload.PackageOpts{
-               Tags:          imports.AnyTags(),
-               LoadTests:     *getT,
-               SilenceErrors: true, // May be fixed by subsequent upgrades or downgrades.
+               Tags:                     imports.AnyTags(),
+               VendorModulesInGOROOTSrc: true,
+               LoadTests:                *getT,
+               AssumeRootsImported:      true, // After 'go get foo', imports of foo should build.
+               SilencePackageErrors:     true, // May be fixed by subsequent upgrades or downgrades.
        }
 
        opts.AllowPackage = func(ctx context.Context, path string, m module.Version) error {
@@ -1176,24 +1208,19 @@ func (r *resolver) loadPackages(ctx context.Context, patterns []string, findPack
 // to be updated before its dependencies can be loaded.
 var errVersionChange = errors.New("version change needed")
 
-// resolveCandidates resolves candidates sets that are attached to the given
+// resolveQueries resolves candidate sets that are attached to the given
 // queries and/or needed to provide the given missing-package dependencies.
 //
-// resolveCandidates starts by resolving one module version from each
+// resolveQueries starts by resolving one module version from each
 // unambiguous pathSet attached to the given queries.
 //
 // If no unambiguous query results in a change to the build list,
-// resolveCandidates modifies the build list by adding one module version from
-// each pathSet in missing, but does not mark those versions as resolved
-// (so they can still be modified by other queries).
-//
-// If that still does not result in any changes to the build list,
-// resolveCandidates revisits the ambiguous query candidates and resolves them
+// resolveQueries revisits the ambiguous query candidates and resolves them
 // arbitrarily in order to guarantee forward progress.
 //
 // If all pathSets are resolved without any changes to the build list,
-// resolveCandidates returns with changed=false.
-func (r *resolver) resolveCandidates(ctx context.Context, queries []*query, upgrades []pathSet) (changed bool) {
+// resolveQueries returns with changed=false.
+func (r *resolver) resolveQueries(ctx context.Context, queries []*query) (changed bool) {
        defer base.ExitIfErrors()
 
        // Note: this is O(N²) with the number of pathSets in the worst case.
@@ -1247,12 +1274,52 @@ func (r *resolver) resolveCandidates(ctx context.Context, queries []*query, upgr
                }
        }
 
-       if changed := r.updateBuildList(ctx, nil); changed {
-               // The build list has changed, so disregard any missing packages: they might
-               // now be determined by requirements in the build list, which we would
-               // prefer to use instead of arbitrary "latest" versions.
-               return true
+       if resolved > 0 {
+               if changed = r.updateBuildList(ctx, nil); changed {
+                       // The build list has changed, so disregard any remaining ambiguous queries:
+                       // they might now be determined by requirements in the build list, which we
+                       // would prefer to use instead of arbitrary versions.
+                       return true
+               }
+       }
+
+       // The build list will be the same on the next iteration as it was on this
+       // iteration, so any ambiguous queries will remain so. In order to make
+       // progress, resolve them arbitrarily but deterministically.
+       //
+       // If that results in conflicting versions, the user can re-run 'go get'
+       // with additional explicit versions for the conflicting packages or
+       // modules.
+       resolvedArbitrarily := 0
+       for _, q := range queries {
+               for _, cs := range q.candidates {
+                       isPackage, m := r.chooseArbitrarily(cs)
+                       if isPackage {
+                               q.matchesPackages = true
+                       }
+                       r.resolve(q, m)
+                       resolvedArbitrarily++
+               }
        }
+       if resolvedArbitrarily > 0 {
+               changed = r.updateBuildList(ctx, nil)
+       }
+       return changed
+}
+
+// applyUpgrades disambiguates candidate sets that are needed to upgrade (or
+// provide) transitive dependencies imported by previously-resolved packages.
+//
+// applyUpgrades modifies the build list by adding one module version from each
+// pathSet in upgrades, then downgrading (or further upgrading) those modules as
+// needed to maintain any already-resolved versions of other modules.
+// applyUpgrades does not mark the new versions as resolved, so they can still
+// be further modified by other queries (such as wildcards).
+//
+// If all pathSets are resolved without any changes to the build list,
+// applyUpgrades returns with changed=false.
+func (r *resolver) applyUpgrades(ctx context.Context, upgrades []pathSet) (changed bool) {
+       defer base.ExitIfErrors()
 
        // Arbitrarily add a "latest" version that provides each missing package, but
        // do not mark the version as resolved: we still want to allow the explicit
@@ -1276,27 +1343,9 @@ func (r *resolver) resolveCandidates(ctx context.Context, queries []*query, upgr
                tentative = append(tentative, m)
        }
        base.ExitIfErrors()
-       if changed := r.updateBuildList(ctx, tentative); changed {
-               return true
-       }
 
-       // The build list will be the same on the next iteration as it was on this
-       // iteration, so any ambiguous queries will remain so. In order to make
-       // progress, resolve them arbitrarily but deterministically.
-       //
-       // If that results in conflicting versions, the user can re-run 'go get'
-       // with additional explicit versions for the conflicting packages or
-       // modules.
-       for _, q := range queries {
-               for _, cs := range q.candidates {
-                       isPackage, m := r.chooseArbitrarily(cs)
-                       if isPackage {
-                               q.matchesPackages = true
-                       }
-                       r.resolve(q, m)
-               }
-       }
-       return r.updateBuildList(ctx, nil)
+       changed = r.updateBuildList(ctx, tentative)
+       return changed
 }
 
 // disambiguate eliminates candidates from cs that conflict with other module
@@ -1417,25 +1466,33 @@ func (r *resolver) chooseArbitrarily(cs pathSet) (isPackage bool, m module.Versi
        return false, cs.mod
 }
 
-// checkPackagesAndRetractions reloads packages for the given patterns and
-// reports missing and ambiguous package errors. It also reports loads and
-// reports retractions for resolved modules and modules needed to build
-// named packages.
+// checkPackageProblems reloads packages for the given patterns and reports
+// missing and ambiguous package errors. It also reports retractions and
+// deprecations for resolved modules and modules needed to build named packages.
+// It also adds a sum for each updated module in the build list if we had one
+// before and didn't get one while loading packages.
 //
 // We skip missing-package errors earlier in the process, since we want to
 // resolve pathSets ourselves, but at that point, we don't have enough context
 // to log the package-import chains leading to each error.
-func (r *resolver) checkPackagesAndRetractions(ctx context.Context, pkgPatterns []string) {
+func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []string) {
        defer base.ExitIfErrors()
 
-       // Build a list of modules to load retractions for. Start with versions
-       // selected based on command line queries.
-       //
-       // This is a subset of the build list. If the main module has a lot of
-       // dependencies, loading retractions for the entire build list would be slow.
-       relevantMods := make(map[module.Version]struct{})
+       // Gather information about modules we might want to load retractions and
+       // deprecations for. Loading this metadata requires at least one version
+       // lookup per module, and we don't want to load information that's neither
+       // relevant nor actionable.
+       type modFlags int
+       const (
+               resolved modFlags = 1 << iota // version resolved by 'go get'
+               named                         // explicitly named on command line or provides a named package
+               hasPkg                        // needed to build named packages
+               direct                        // provides a direct dependency of the main module
+       )
+       relevantMods := make(map[module.Version]modFlags)
        for path, reason := range r.resolvedVersion {
-               relevantMods[module.Version{Path: path, Version: reason.version}] = struct{}{}
+               m := module.Version{Path: path, Version: reason.version}
+               relevantMods[m] |= resolved
        }
 
        // Reload packages, reporting errors for missing and ambiguous imports.
@@ -1443,9 +1500,11 @@ func (r *resolver) checkPackagesAndRetractions(ctx context.Context, pkgPatterns
                // LoadPackages will print errors (since it has more context) but will not
                // exit, since we need to load retractions later.
                pkgOpts := modload.PackageOpts{
-                       LoadTests:             *getT,
-                       ResolveMissingImports: false,
-                       AllowErrors:           true,
+                       VendorModulesInGOROOTSrc: true,
+                       LoadTests:                *getT,
+                       ResolveMissingImports:    false,
+                       AllowErrors:              true,
+                       SilenceNoGoErrors:        true,
                }
                matches, pkgs := modload.LoadPackages(ctx, pkgOpts, pkgPatterns...)
                for _, m := range matches {
@@ -1461,53 +1520,141 @@ func (r *resolver) checkPackagesAndRetractions(ctx context.Context, pkgPatterns
                                        // associated with either the package or its test — ErrNoGo must
                                        // indicate that none of those source files happen to apply in this
                                        // configuration. If we are actually building the package (no -d
-                                       // flag), the compiler will report the problem; otherwise, assume that
-                                       // the user is going to build or test it in some other configuration
-                                       // and suppress the error.
+                                       // flag), we will report the problem then; otherwise, assume that the
+                                       // user is going to build or test this package in some other
+                                       // configuration and suppress the error.
                                        continue
                                }
 
                                base.SetExitStatus(1)
                                if ambiguousErr := (*modload.AmbiguousImportError)(nil); errors.As(err, &ambiguousErr) {
                                        for _, m := range ambiguousErr.Modules {
-                                               relevantMods[m] = struct{}{}
+                                               relevantMods[m] |= hasPkg
                                        }
                                }
                        }
                        if m := modload.PackageModule(pkg); m.Path != "" {
-                               relevantMods[m] = struct{}{}
+                               relevantMods[m] |= hasPkg
+                       }
+               }
+               for _, match := range matches {
+                       for _, pkg := range match.Pkgs {
+                               m := modload.PackageModule(pkg)
+                               relevantMods[m] |= named
                        }
                }
        }
 
-       // Load and report retractions.
-       type retraction struct {
-               m   module.Version
-               err error
-       }
-       retractions := make([]retraction, 0, len(relevantMods))
+       reqs := modload.LoadModFile(ctx)
        for m := range relevantMods {
-               retractions = append(retractions, retraction{m: m})
+               if reqs.IsDirect(m.Path) {
+                       relevantMods[m] |= direct
+               }
        }
-       sort.Slice(retractions, func(i, j int) bool {
-               return retractions[i].m.Path < retractions[j].m.Path
-       })
-       for i := 0; i < len(retractions); i++ {
+
+       // Load retractions for modules mentioned on the command line and modules
+       // needed to build named packages. We care about retractions of indirect
+       // dependencies, since we might be able to upgrade away from them.
+       type modMessage struct {
+               m       module.Version
+               message string
+       }
+       retractions := make([]modMessage, 0, len(relevantMods))
+       for m, flags := range relevantMods {
+               if flags&(resolved|named|hasPkg) != 0 {
+                       retractions = append(retractions, modMessage{m: m})
+               }
+       }
+       sort.Slice(retractions, func(i, j int) bool { return retractions[i].m.Path < retractions[j].m.Path })
+       for i := range retractions {
                i := i
                r.work.Add(func() {
                        err := modload.CheckRetractions(ctx, retractions[i].m)
                        if retractErr := (*modload.ModuleRetractedError)(nil); errors.As(err, &retractErr) {
-                               retractions[i].err = err
+                               retractions[i].message = err.Error()
+                       }
+               })
+       }
+
+       // Load deprecations for modules mentioned on the command line. Only load
+       // deprecations for indirect dependencies if they're also direct dependencies
+       // of the main module. Deprecations of purely indirect dependencies are
+       // not actionable.
+       deprecations := make([]modMessage, 0, len(relevantMods))
+       for m, flags := range relevantMods {
+               if flags&(resolved|named) != 0 || flags&(hasPkg|direct) == hasPkg|direct {
+                       deprecations = append(deprecations, modMessage{m: m})
+               }
+       }
+       sort.Slice(deprecations, func(i, j int) bool { return deprecations[i].m.Path < deprecations[j].m.Path })
+       for i := range deprecations {
+               i := i
+               r.work.Add(func() {
+                       deprecation, err := modload.CheckDeprecation(ctx, deprecations[i].m)
+                       if err != nil || deprecation == "" {
+                               return
+                       }
+                       deprecations[i].message = modload.ShortMessage(deprecation, "")
+               })
+       }
+
+       // Load sums for updated modules that had sums before. When we update a
+       // module, we may update another module in the build list that provides a
+       // package in 'all' that wasn't loaded as part of this 'go get' command.
+       // If we don't add a sum for that module, builds may fail later.
+       // Note that an incidentally updated package could still import packages
+       // from unknown modules or from modules in the build list that we didn't
+       // need previously. We can't handle that case without loading 'all'.
+       sumErrs := make([]error, len(r.buildList))
+       for i := range r.buildList {
+               i := i
+               m := r.buildList[i]
+               mActual := m
+               if mRepl := modload.Replacement(m); mRepl.Path != "" {
+                       mActual = mRepl
+               }
+               old := module.Version{Path: m.Path, Version: r.initialVersion[m.Path]}
+               if old.Version == "" {
+                       continue
+               }
+               oldActual := old
+               if oldRepl := modload.Replacement(old); oldRepl.Path != "" {
+                       oldActual = oldRepl
+               }
+               if mActual == oldActual || mActual.Version == "" || !modfetch.HaveSum(oldActual) {
+                       continue
+               }
+               r.work.Add(func() {
+                       if _, err := modfetch.DownloadZip(ctx, mActual); err != nil {
+                               verb := "upgraded"
+                               if semver.Compare(m.Version, old.Version) < 0 {
+                                       verb = "downgraded"
+                               }
+                               replaced := ""
+                               if mActual != m {
+                                       replaced = fmt.Sprintf(" (replaced by %s)", mActual)
+                               }
+                               err = fmt.Errorf("%s %s %s => %s%s: error finding sum for %s: %v", verb, m.Path, old.Version, m.Version, replaced, mActual, err)
+                               sumErrs[i] = err
                        }
                })
        }
+
        <-r.work.Idle()
+
+       // Report deprecations, then retractions, then errors fetching sums.
+       // Only errors fetching sums are hard errors.
+       for _, mm := range deprecations {
+               if mm.message != "" {
+                       fmt.Fprintf(os.Stderr, "go: module %s is deprecated: %s\n", mm.m.Path, mm.message)
+               }
+       }
        var retractPath string
-       for _, r := range retractions {
-               if r.err != nil {
-                       fmt.Fprintf(os.Stderr, "go: warning: %v\n", r.err)
+       for _, mm := range retractions {
+               if mm.message != "" {
+                       fmt.Fprintf(os.Stderr, "go: warning: %v\n", mm.message)
                        if retractPath == "" {
-                               retractPath = r.m.Path
+                               retractPath = mm.m.Path
                        } else {
                                retractPath = "<module>"
                        }
@@ -1516,6 +1663,12 @@ func (r *resolver) checkPackagesAndRetractions(ctx context.Context, pkgPatterns
        if retractPath != "" {
                fmt.Fprintf(os.Stderr, "go: to switch to the latest unretracted version, run:\n\tgo get %s@latest\n", retractPath)
        }
+       for _, err := range sumErrs {
+               if err != nil {
+                       base.Errorf("go: %v", err)
+               }
+       }
+       base.ExitIfErrors()
 }
 
 // reportChanges logs version changes to os.Stderr.
@@ -1614,11 +1767,10 @@ func (r *resolver) resolve(q *query, m module.Version) {
 //
 // If the additional modules conflict with the resolved versions, they will be
 // downgraded to a non-conflicting version (possibly "none").
+//
+// If the resulting build list is the same as the one resulting from the last
+// call to updateBuildList, updateBuildList returns with changed=false.
 func (r *resolver) updateBuildList(ctx context.Context, additions []module.Version) (changed bool) {
-       if len(additions) == 0 && len(r.resolvedVersion) == r.buildListResolvedVersions {
-               return false
-       }
-
        defer base.ExitIfErrors()
 
        resolved := make([]module.Version, 0, len(r.resolvedVersion))
@@ -1628,7 +1780,8 @@ func (r *resolver) updateBuildList(ctx context.Context, additions []module.Versi
                }
        }
 
-       if err := modload.EditBuildList(ctx, additions, resolved); err != nil {
+       changed, err := modload.EditBuildList(ctx, additions, resolved)
+       if err != nil {
                var constraint *modload.ConstraintError
                if !errors.As(err, &constraint) {
                        base.Errorf("go get: %v", err)
@@ -1647,13 +1800,12 @@ func (r *resolver) updateBuildList(ctx context.Context, additions []module.Versi
                }
                return false
        }
-
-       buildList := modload.LoadAllModules(ctx)
-       r.buildListResolvedVersions = len(r.resolvedVersion)
-       if reflect.DeepEqual(r.buildList, buildList) {
+       if !changed {
                return false
        }
-       r.buildList = buildList
+
+       const defaultGoVersion = ""
+       r.buildList = modload.LoadModGraph(ctx, defaultGoVersion).BuildList()
        r.buildListVersion = make(map[string]string, len(r.buildList))
        for _, m := range r.buildList {
                r.buildListVersion[m.Path] = m.Version
index 897be56397d144f4da6ab296dc636e19c8a82f07..19088352f058baa93bce316dd462b6b37dd9089d 100644 (file)
@@ -10,19 +10,20 @@ import "time"
 // and the fields are documented in the help text in ../list/list.go
 
 type ModulePublic struct {
-       Path      string        `json:",omitempty"` // module path
-       Version   string        `json:",omitempty"` // module version
-       Versions  []string      `json:",omitempty"` // available module versions
-       Replace   *ModulePublic `json:",omitempty"` // replaced by this module
-       Time      *time.Time    `json:",omitempty"` // time version was created
-       Update    *ModulePublic `json:",omitempty"` // available update (with -u)
-       Main      bool          `json:",omitempty"` // is this the main module?
-       Indirect  bool          `json:",omitempty"` // module is only indirectly needed by main module
-       Dir       string        `json:",omitempty"` // directory holding local copy of files, if any
-       GoMod     string        `json:",omitempty"` // path to go.mod file describing module, if any
-       GoVersion string        `json:",omitempty"` // go version used in module
-       Retracted []string      `json:",omitempty"` // retraction information, if any (with -retracted or -u)
-       Error     *ModuleError  `json:",omitempty"` // error loading module
+       Path       string        `json:",omitempty"` // module path
+       Version    string        `json:",omitempty"` // module version
+       Versions   []string      `json:",omitempty"` // available module versions
+       Replace    *ModulePublic `json:",omitempty"` // replaced by this module
+       Time       *time.Time    `json:",omitempty"` // time version was created
+       Update     *ModulePublic `json:",omitempty"` // available update (with -u)
+       Main       bool          `json:",omitempty"` // is this the main module?
+       Indirect   bool          `json:",omitempty"` // module is only indirectly needed by main module
+       Dir        string        `json:",omitempty"` // directory holding local copy of files, if any
+       GoMod      string        `json:",omitempty"` // path to go.mod file describing module, if any
+       GoVersion  string        `json:",omitempty"` // go version used in module
+       Retracted  []string      `json:",omitempty"` // retraction information, if any (with -retracted or -u)
+       Deprecated string        `json:",omitempty"` // deprecation message, if any (with -u)
+       Error      *ModuleError  `json:",omitempty"` // error loading module
 }
 
 type ModuleError struct {
@@ -45,6 +46,9 @@ func (m *ModulePublic) String() string {
                        s += " [" + versionString(m.Update) + "]"
                }
        }
+       if m.Deprecated != "" {
+               s += " (deprecated)"
+       }
        if m.Replace != nil {
                s += " => " + m.Replace.Path
                if m.Replace.Version != "" {
@@ -53,6 +57,9 @@ func (m *ModulePublic) String() string {
                                s += " [" + versionString(m.Replace.Update) + "]"
                        }
                }
+               if m.Replace.Deprecated != "" {
+                       s += " (deprecated)"
+               }
        }
        return s
 }
index d2f8f8670a2d20657dfe40a4848b60373db30671..becf6b87f800543bf36ddaba4717af3b00c26334 100644 (file)
@@ -11,6 +11,7 @@ import (
        "errors"
        "fmt"
        "internal/goroot"
+       "io/fs"
        "os"
        "path/filepath"
        "strings"
@@ -50,17 +51,17 @@ func findStandardImportPath(path string) string {
 // a given package. If modules are not enabled or if the package is in the
 // standard library or if the package was not successfully loaded with
 // LoadPackages or ImportFromFiles, nil is returned.
-func PackageModuleInfo(pkgpath string) *modinfo.ModulePublic {
+func PackageModuleInfo(ctx context.Context, pkgpath string) *modinfo.ModulePublic {
        if isStandardImportPath(pkgpath) || !Enabled() {
                return nil
        }
-       m, ok := findModule(pkgpath)
+       m, ok := findModule(loaded, pkgpath)
        if !ok {
                return nil
        }
-       fromBuildList := true
-       listRetracted := false
-       return moduleInfo(context.TODO(), m, fromBuildList, listRetracted)
+
+       rs := LoadModFile(ctx)
+       return moduleInfo(ctx, rs, m, 0)
 }
 
 func ModuleInfo(ctx context.Context, path string) *modinfo.ModulePublic {
@@ -68,26 +69,38 @@ func ModuleInfo(ctx context.Context, path string) *modinfo.ModulePublic {
                return nil
        }
 
-       listRetracted := false
        if i := strings.Index(path, "@"); i >= 0 {
                m := module.Version{Path: path[:i], Version: path[i+1:]}
-               fromBuildList := false
-               return moduleInfo(ctx, m, fromBuildList, listRetracted)
+               return moduleInfo(ctx, nil, m, 0)
        }
 
-       for _, m := range buildList {
-               if m.Path == path {
-                       fromBuildList := true
-                       return moduleInfo(ctx, m, fromBuildList, listRetracted)
+       rs := LoadModFile(ctx)
+
+       var (
+               v  string
+               ok bool
+       )
+       if rs.depth == lazy {
+               v, ok = rs.rootSelected(path)
+       }
+       if !ok {
+               mg, err := rs.Graph(ctx)
+               if err != nil {
+                       base.Fatalf("go: %v", err)
                }
+               v = mg.Selected(path)
        }
 
-       return &modinfo.ModulePublic{
-               Path: path,
-               Error: &modinfo.ModuleError{
-                       Err: "module not in current build",
-               },
+       if v == "none" {
+               return &modinfo.ModulePublic{
+                       Path: path,
+                       Error: &modinfo.ModuleError{
+                               Err: "module not in current build",
+                       },
+               }
        }
+
+       return moduleInfo(ctx, rs, module.Version{Path: path, Version: v}, 0)
 }
 
 // addUpdate fills in m.Update if an updated version is available.
@@ -96,7 +109,26 @@ func addUpdate(ctx context.Context, m *modinfo.ModulePublic) {
                return
        }
 
-       if info, err := Query(ctx, m.Path, "upgrade", m.Version, CheckAllowed); err == nil && semver.Compare(info.Version, m.Version) > 0 {
+       info, err := Query(ctx, m.Path, "upgrade", m.Version, CheckAllowed)
+       var noVersionErr *NoMatchingVersionError
+       if errors.Is(err, fs.ErrNotExist) || errors.As(err, &noVersionErr) {
+               // Ignore "not found" and "no matching version" errors.
+               // This means the proxy has no matching version or no versions at all.
+               //
+               // We should report other errors though. An attacker that controls the
+               // network shouldn't be able to hide versions by interfering with
+               // the HTTPS connection. An attacker that controls the proxy may still
+               // hide versions, since the "list" and "latest" endpoints are not
+               // authenticated.
+               return
+       } else if err != nil {
+               if m.Error == nil {
+                       m.Error = &modinfo.ModuleError{Err: err.Error()}
+               }
+               return
+       }
+
+       if semver.Compare(info.Version, m.Version) > 0 {
                m.Update = &modinfo.ModulePublic{
                        Path:    m.Path,
                        Version: info.Version,
@@ -113,7 +145,11 @@ func addVersions(ctx context.Context, m *modinfo.ModulePublic, listRetracted boo
        if listRetracted {
                allowed = CheckExclusions
        }
-       m.Versions, _ = versions(ctx, m.Path, allowed)
+       var err error
+       m.Versions, err = versions(ctx, m.Path, allowed)
+       if err != nil && m.Error == nil {
+               m.Error = &modinfo.ModuleError{Err: err.Error()}
+       }
 }
 
 // addRetraction fills in m.Retracted if the module was retracted by its author.
@@ -124,31 +160,72 @@ func addRetraction(ctx context.Context, m *modinfo.ModulePublic) {
        }
 
        err := CheckRetractions(ctx, module.Version{Path: m.Path, Version: m.Version})
-       var rerr *ModuleRetractedError
-       if errors.As(err, &rerr) {
-               if len(rerr.Rationale) == 0 {
+       var noVersionErr *NoMatchingVersionError
+       var retractErr *ModuleRetractedError
+       if err == nil || errors.Is(err, fs.ErrNotExist) || errors.As(err, &noVersionErr) {
+               // Ignore "not found" and "no matching version" errors.
+               // This means the proxy has no matching version or no versions at all.
+               //
+               // We should report other errors though. An attacker that controls the
+               // network shouldn't be able to hide versions by interfering with
+               // the HTTPS connection. An attacker that controls the proxy may still
+               // hide versions, since the "list" and "latest" endpoints are not
+               // authenticated.
+               return
+       } else if errors.As(err, &retractErr) {
+               if len(retractErr.Rationale) == 0 {
                        m.Retracted = []string{"retracted by module author"}
                } else {
-                       m.Retracted = rerr.Rationale
+                       m.Retracted = retractErr.Rationale
                }
-       } else if err != nil && m.Error == nil {
+       } else if m.Error == nil {
                m.Error = &modinfo.ModuleError{Err: err.Error()}
        }
 }
 
-func moduleInfo(ctx context.Context, m module.Version, fromBuildList, listRetracted bool) *modinfo.ModulePublic {
+// addDeprecation fills in m.Deprecated if the module was deprecated by its
+// author. m.Error is set if there's an error loading deprecation information.
+func addDeprecation(ctx context.Context, m *modinfo.ModulePublic) {
+       deprecation, err := CheckDeprecation(ctx, module.Version{Path: m.Path, Version: m.Version})
+       var noVersionErr *NoMatchingVersionError
+       if errors.Is(err, fs.ErrNotExist) || errors.As(err, &noVersionErr) {
+               // Ignore "not found" and "no matching version" errors.
+               // This means the proxy has no matching version or no versions at all.
+               //
+               // We should report other errors though. An attacker that controls the
+               // network shouldn't be able to hide versions by interfering with
+               // the HTTPS connection. An attacker that controls the proxy may still
+               // hide versions, since the "list" and "latest" endpoints are not
+               // authenticated.
+               return
+       }
+       if err != nil {
+               if m.Error == nil {
+                       m.Error = &modinfo.ModuleError{Err: err.Error()}
+               }
+               return
+       }
+       m.Deprecated = deprecation
+}
+
+// moduleInfo returns information about module m, loaded from the requirements
+// in rs (which may be nil to indicate that m was not loaded from a requirement
+// graph).
+func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode ListMode) *modinfo.ModulePublic {
        if m == Target {
                info := &modinfo.ModulePublic{
                        Path:    m.Path,
                        Version: m.Version,
                        Main:    true,
                }
+               if v, ok := rawGoVersion.Load(Target); ok {
+                       info.GoVersion = v.(string)
+               } else {
+                       panic("internal error: GoVersion not set for main module")
+               }
                if HasModRoot() {
                        info.Dir = ModRoot()
                        info.GoMod = ModFilePath()
-                       if modFile.Go != nil {
-                               info.GoVersion = modFile.Go.Version
-                       }
                }
                return info
        }
@@ -156,7 +233,7 @@ func moduleInfo(ctx context.Context, m module.Version, fromBuildList, listRetrac
        info := &modinfo.ModulePublic{
                Path:     m.Path,
                Version:  m.Version,
-               Indirect: fromBuildList && loaded != nil && !loaded.direct[m.Path],
+               Indirect: rs != nil && !rs.direct[m.Path],
        }
        if v, ok := rawGoVersion.Load(m); ok {
                info.GoVersion = v.(string)
@@ -164,7 +241,10 @@ func moduleInfo(ctx context.Context, m module.Version, fromBuildList, listRetrac
 
        // completeFromModCache fills in the extra fields in m using the module cache.
        completeFromModCache := func(m *modinfo.ModulePublic) {
-               mod := module.Version{Path: m.Path, Version: m.Version}
+               checksumOk := func(suffix string) bool {
+                       return rs == nil || m.Version == "" || cfg.BuildMod == "mod" ||
+                               modfetch.HaveSum(module.Version{Path: m.Path, Version: m.Version + suffix})
+               }
 
                if m.Version != "" {
                        if q, err := Query(ctx, m.Path, m.Version, "", nil); err != nil {
@@ -173,31 +253,40 @@ func moduleInfo(ctx context.Context, m module.Version, fromBuildList, listRetrac
                                m.Version = q.Version
                                m.Time = &q.Time
                        }
+               }
+               mod := module.Version{Path: m.Path, Version: m.Version}
+
+               if m.GoVersion == "" && checksumOk("/go.mod") {
+                       // Load the go.mod file to determine the Go version, since it hasn't
+                       // already been populated from rawGoVersion.
+                       if summary, err := rawGoModSummary(mod); err == nil && summary.goVersion != "" {
+                               m.GoVersion = summary.goVersion
+                       }
+               }
 
-                       gomod, err := modfetch.CachePath(mod, "mod")
-                       if err == nil {
-                               if info, err := os.Stat(gomod); err == nil && info.Mode().IsRegular() {
-                                       m.GoMod = gomod
+               if m.Version != "" {
+                       if checksumOk("/go.mod") {
+                               gomod, err := modfetch.CachePath(mod, "mod")
+                               if err == nil {
+                                       if info, err := os.Stat(gomod); err == nil && info.Mode().IsRegular() {
+                                               m.GoMod = gomod
+                                       }
                                }
                        }
-                       dir, err := modfetch.DownloadDir(mod)
-                       if err == nil {
-                               m.Dir = dir
+                       if checksumOk("") {
+                               dir, err := modfetch.DownloadDir(mod)
+                               if err == nil {
+                                       m.Dir = dir
+                               }
                        }
 
-                       if listRetracted {
+                       if mode&ListRetracted != 0 {
                                addRetraction(ctx, m)
                        }
                }
-
-               if m.GoVersion == "" {
-                       if summary, err := rawGoModSummary(mod); err == nil && summary.goVersionV != "" {
-                               m.GoVersion = summary.goVersionV[1:]
-                       }
-               }
        }
 
-       if !fromBuildList {
+       if rs == nil {
                // If this was an explicitly-versioned argument to 'go mod download' or
                // 'go list -m', report the actual requested version, not its replacement.
                completeFromModCache(info) // Will set m.Error in vendor mode.
@@ -255,11 +344,11 @@ func PackageBuildInfo(path string, deps []string) string {
                return ""
        }
 
-       target := mustFindModule(path, path)
+       target := mustFindModule(loaded, path, path)
        mdeps := make(map[module.Version]bool)
        for _, dep := range deps {
                if !isStandardImportPath(dep) {
-                       mdeps[mustFindModule(path, dep)] = true
+                       mdeps[mustFindModule(loaded, path, dep)] = true
                }
        }
        var mods []module.Version
@@ -298,8 +387,8 @@ func PackageBuildInfo(path string, deps []string) string {
 //
 // TODO(jayconrod): remove this. Callers should use findModule and return
 // errors instead of relying on base.Fatalf.
-func mustFindModule(target, path string) module.Version {
-       pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
+func mustFindModule(ld *loader, target, path string) module.Version {
+       pkg, ok := ld.pkgCache.Get(path).(*loadPkg)
        if ok {
                if pkg.err != nil {
                        base.Fatalf("build %v: cannot load %v: %v", target, path, pkg.err)
@@ -318,8 +407,8 @@ func mustFindModule(target, path string) module.Version {
 // findModule searches for the module that contains the package at path.
 // If the package was loaded, its containing module and true are returned.
 // Otherwise, module.Version{} and false are returend.
-func findModule(path string) (module.Version, bool) {
-       if pkg, ok := loaded.pkgCache.Get(path).(*loadPkg); ok {
+func findModule(ld *loader, path string) (module.Version, bool) {
+       if pkg, ok := ld.pkgCache.Get(path).(*loadPkg); ok {
                return pkg.mod, pkg.mod != module.Version{}
        }
        if path == "command-line-arguments" {
index 0ed985384d8f8dcf7e6eaf9d95c706f3fed9ffa0..604a57b4373b28051b0fdf0235b1e52f9051d9c3 100644 (file)
@@ -7,188 +7,501 @@ package modload
 import (
        "cmd/go/internal/base"
        "cmd/go/internal/cfg"
-       "cmd/go/internal/imports"
        "cmd/go/internal/mvs"
+       "cmd/go/internal/par"
        "context"
        "fmt"
-       "go/build"
        "os"
+       "reflect"
+       "runtime"
+       "runtime/debug"
        "strings"
+       "sync"
+       "sync/atomic"
 
-       "golang.org/x/mod/modfile"
        "golang.org/x/mod/module"
        "golang.org/x/mod/semver"
 )
 
-// buildList is the list of modules to use for building packages.
-// It is initialized by calling LoadPackages or ImportFromFiles,
-// each of which uses loaded.load.
-//
-// Ideally, exactly ONE of those functions would be called,
-// and exactly once. Most of the time, that's true.
-// During "go get" it may not be. TODO(rsc): Figure out if
-// that restriction can be established, or else document why not.
-//
-var buildList []module.Version
-
-// additionalExplicitRequirements is a list of modules paths for which
-// WriteGoMod should record explicit requirements, even if they would be
-// selected without those requirements. Each path must also appear in buildList.
-var additionalExplicitRequirements []string
-
 // capVersionSlice returns s with its cap reduced to its length.
 func capVersionSlice(s []module.Version) []module.Version {
        return s[:len(s):len(s)]
 }
 
-// LoadAllModules loads and returns the list of modules matching the "all"
-// module pattern, starting with the Target module and in a deterministic
-// (stable) order, without loading any packages.
+// A Requirements represents a logically-immutable set of root module requirements.
+type Requirements struct {
+       // depth is the depth at which the requirement graph is computed.
+       //
+       // If eager, the graph includes all transitive requirements regardless of depth.
+       //
+       // If lazy, the graph includes only the root modules, the explicit
+       // requirements of those root modules, and the transitive requirements of only
+       // the *non-lazy* root modules.
+       depth modDepth
+
+       // rootModules is the set of module versions explicitly required by the main
+       // module, sorted and capped to length. It may contain duplicates, and may
+       // contain multiple versions for a given module path.
+       rootModules    []module.Version
+       maxRootVersion map[string]string
+
+       // direct is the set of module paths for which we believe the module provides
+       // a package directly imported by a package or test in the main module.
+       //
+       // The "direct" map controls which modules are annotated with "// indirect"
+       // comments in the go.mod file, and may impact which modules are listed as
+       // explicit roots (vs. indirect-only dependencies). However, it should not
+       // have a semantic effect on the build list overall.
+       //
+       // The initial direct map is populated from the existing "// indirect"
+       // comments (or lack thereof) in the go.mod file. It is updated by the
+       // package loader: dependencies may be promoted to direct if new
+       // direct imports are observed, and may be demoted to indirect during
+       // 'go mod tidy' or 'go mod vendor'.
+       //
+       // The direct map is keyed by module paths, not module versions. When a
+       // module's selected version changes, we assume that it remains direct if the
+       // previous version was a direct dependency. That assumption might not hold in
+       // rare cases (such as if a dependency splits out a nested module, or merges a
+       // nested module back into a parent module).
+       direct map[string]bool
+
+       graphOnce sync.Once    // guards writes to (but not reads from) graph
+       graph     atomic.Value // cachedGraph
+}
+
+// A cachedGraph is a non-nil *ModuleGraph, together with any error discovered
+// while loading that graph.
+type cachedGraph struct {
+       mg  *ModuleGraph
+       err error // If err is non-nil, mg may be incomplete (but must still be non-nil).
+}
+
+// requirements is the requirement graph for the main module.
 //
-// Modules are loaded automatically (and lazily) in LoadPackages:
-// LoadAllModules need only be called if LoadPackages is not,
-// typically in commands that care about modules but no particular package.
+// It is always non-nil if the main module's go.mod file has been loaded.
+//
+// This variable should only be read from the loadModFile function, and should
+// only be written in the loadModFile and commitRequirements functions.
+// All other functions that need or produce a *Requirements should
+// accept and/or return an explicit parameter.
+var requirements *Requirements
+
+// newRequirements returns a new requirement set with the given root modules.
+// The dependencies of the roots will be loaded lazily at the first call to the
+// Graph method.
 //
-// The caller must not modify the returned list, but may append to it.
-func LoadAllModules(ctx context.Context) []module.Version {
-       LoadModFile(ctx)
-       ReloadBuildList()
-       WriteGoMod()
-       return capVersionSlice(buildList)
+// The rootModules slice must be sorted according to module.Sort.
+// The caller must not modify the rootModules slice or direct map after passing
+// them to newRequirements.
+//
+// If vendoring is in effect, the caller must invoke initVendor on the returned
+// *Requirements before any other method.
+func newRequirements(depth modDepth, rootModules []module.Version, direct map[string]bool) *Requirements {
+       for i, m := range rootModules {
+               if m == Target {
+                       panic(fmt.Sprintf("newRequirements called with untrimmed build list: rootModules[%v] is Target", i))
+               }
+               if m.Path == "" || m.Version == "" {
+                       panic(fmt.Sprintf("bad requirement: rootModules[%v] = %v", i, m))
+               }
+               if i > 0 {
+                       prev := rootModules[i-1]
+                       if prev.Path > m.Path || (prev.Path == m.Path && semver.Compare(prev.Version, m.Version) > 0) {
+                               panic(fmt.Sprintf("newRequirements called with unsorted roots: %v", rootModules))
+                       }
+               }
+       }
+
+       rs := &Requirements{
+               depth:          depth,
+               rootModules:    capVersionSlice(rootModules),
+               maxRootVersion: make(map[string]string, len(rootModules)),
+               direct:         direct,
+       }
+
+       for _, m := range rootModules {
+               if v, ok := rs.maxRootVersion[m.Path]; ok && cmpVersion(v, m.Version) >= 0 {
+                       continue
+               }
+               rs.maxRootVersion[m.Path] = m.Version
+       }
+       return rs
 }
 
-// Selected returns the selected version of the module with the given path, or
-// the empty string if the given module has no selected version
-// (either because it is not required or because it is the Target module).
-func Selected(path string) (version string) {
+// initVendor initializes rs.graph from the given list of vendored module
+// dependencies, overriding the graph that would normally be loaded from module
+// requirements.
+func (rs *Requirements) initVendor(vendorList []module.Version) {
+       rs.graphOnce.Do(func() {
+               mg := &ModuleGraph{
+                       g: mvs.NewGraph(cmpVersion, []module.Version{Target}),
+               }
+
+               if rs.depth == lazy {
+                       // The roots of a lazy module should already include every module in the
+                       // vendor list, because the vendored modules are the same as those
+                       // maintained as roots by the lazy loading “import invariant”.
+                       //
+                       // Just to be sure, we'll double-check that here.
+                       inconsistent := false
+                       for _, m := range vendorList {
+                               if v, ok := rs.rootSelected(m.Path); !ok || v != m.Version {
+                                       base.Errorf("go: vendored module %v should be required explicitly in go.mod", m)
+                                       inconsistent = true
+                               }
+                       }
+                       if inconsistent {
+                               base.Fatalf("go: %v", errGoModDirty)
+                       }
+
+                       // Now we can treat the rest of the module graph as effectively “pruned
+                       // out”, like a more aggressive version of lazy loading: in vendor mode,
+                       // the root requirements *are* the complete module graph.
+                       mg.g.Require(Target, rs.rootModules)
+               } else {
+                       // The transitive requirements of the main module are not in general available
+                       // from the vendor directory, and we don't actually know how we got from
+                       // the roots to the final build list.
+                       //
+                       // Instead, we'll inject a fake "vendor/modules.txt" module that provides
+                       // those transitive dependencies, and mark it as a dependency of the main
+                       // module. That allows us to elide the actual structure of the module
+                       // graph, but still distinguishes between direct and indirect
+                       // dependencies.
+                       vendorMod := module.Version{Path: "vendor/modules.txt", Version: ""}
+                       mg.g.Require(Target, append(rs.rootModules, vendorMod))
+                       mg.g.Require(vendorMod, vendorList)
+               }
+
+               rs.graph.Store(cachedGraph{mg, nil})
+       })
+}
+
+// rootSelected returns the version of the root dependency with the given module
+// path, or the zero module.Version and ok=false if the module is not a root
+// dependency.
+func (rs *Requirements) rootSelected(path string) (version string, ok bool) {
        if path == Target.Path {
-               return ""
+               return Target.Version, true
        }
-       for _, m := range buildList {
-               if m.Path == path {
-                       return m.Version
-               }
+       if v, ok := rs.maxRootVersion[path]; ok {
+               return v, true
        }
-       return ""
+       return "", false
 }
 
-// EditBuildList edits the global build list by first adding every module in add
-// to the existing build list, then adjusting versions (and adding or removing
-// requirements as needed) until every module in mustSelect is selected at the
-// given version.
+// Graph returns the graph of module requirements loaded from the current
+// root modules (as reported by RootModules).
 //
-// (Note that the newly-added modules might not be selected in the resulting
-// build list: they could be lower than existing requirements or conflict with
-// versions in mustSelect.)
+// Graph always makes a best effort to load the requirement graph despite any
+// errors, and always returns a non-nil *ModuleGraph.
 //
-// If the versions listed in mustSelect are mutually incompatible (due to one of
-// the listed modules requiring a higher version of another), EditBuildList
-// returns a *ConstraintError and leaves the build list in its previous state.
-func EditBuildList(ctx context.Context, add, mustSelect []module.Version) error {
-       var upgraded = capVersionSlice(buildList)
-       if len(add) > 0 {
-               // First, upgrade the build list with any additions.
-               // In theory we could just append the additions to the build list and let
-               // mvs.Downgrade take care of resolving the upgrades too, but the
-               // diagnostics from Upgrade are currently much better in case of errors.
-               var err error
-               upgraded, err = mvs.Upgrade(Target, &mvsReqs{buildList: upgraded}, add...)
-               if err != nil {
-                       return err
+// If the requirements of any relevant module fail to load, Graph also
+// returns a non-nil error of type *mvs.BuildListError.
+func (rs *Requirements) Graph(ctx context.Context) (*ModuleGraph, error) {
+       rs.graphOnce.Do(func() {
+               mg, mgErr := readModGraph(ctx, rs.depth, rs.rootModules)
+               rs.graph.Store(cachedGraph{mg, mgErr})
+       })
+       cached := rs.graph.Load().(cachedGraph)
+       return cached.mg, cached.err
+}
+
+// IsDirect returns whether the given module provides a package directly
+// imported by a package or test in the main module.
+func (rs *Requirements) IsDirect(path string) bool {
+       return rs.direct[path]
+}
+
+// A ModuleGraph represents the complete graph of module dependencies
+// of a main module.
+//
+// If the main module is lazily loaded, the graph does not include
+// transitive dependencies of non-root (implicit) dependencies.
+type ModuleGraph struct {
+       g         *mvs.Graph
+       loadCache par.Cache // module.Version → summaryError
+
+       buildListOnce sync.Once
+       buildList     []module.Version
+}
+
+// A summaryError is either a non-nil modFileSummary or a non-nil error
+// encountered while reading or parsing that summary.
+type summaryError struct {
+       summary *modFileSummary
+       err     error
+}
+
+var readModGraphDebugOnce sync.Once
+
+// readModGraph reads and returns the module dependency graph starting at the
+// given roots.
+//
+// Unlike LoadModGraph, readModGraph does not attempt to diagnose or update
+// inconsistent roots.
+func readModGraph(ctx context.Context, depth modDepth, roots []module.Version) (*ModuleGraph, error) {
+       if depth == lazy {
+               readModGraphDebugOnce.Do(func() {
+                       for _, f := range strings.Split(os.Getenv("GODEBUG"), ",") {
+                               switch f {
+                               case "lazymod=log":
+                                       debug.PrintStack()
+                                       fmt.Fprintf(os.Stderr, "go: read full module graph.\n")
+                               case "lazymod=strict":
+                                       debug.PrintStack()
+                                       base.Fatalf("go: read full module graph (forbidden by GODEBUG=lazymod=strict).")
+                               }
+                       }
+               })
+       }
+
+       var (
+               mu       sync.Mutex // guards mg.g and hasError during loading
+               hasError bool
+               mg       = &ModuleGraph{
+                       g: mvs.NewGraph(cmpVersion, []module.Version{Target}),
                }
+       )
+       mg.g.Require(Target, roots)
+
+       var (
+               loadQueue    = par.NewQueue(runtime.GOMAXPROCS(0))
+               loadingEager sync.Map // module.Version → nil; the set of modules that have been or are being loaded via eager roots
+       )
+
+       // loadOne synchronously loads the explicit requirements for module m.
+       // It does not load the transitive requirements of m even if the go version in
+       // m's go.mod file indicates eager loading.
+       loadOne := func(m module.Version) (*modFileSummary, error) {
+               cached := mg.loadCache.Do(m, func() interface{} {
+                       summary, err := goModSummary(m)
+
+                       mu.Lock()
+                       if err == nil {
+                               mg.g.Require(m, summary.require)
+                       } else {
+                               hasError = true
+                       }
+                       mu.Unlock()
+
+                       return summaryError{summary, err}
+               }).(summaryError)
+
+               return cached.summary, cached.err
        }
 
-       downgraded, err := mvs.Downgrade(Target, &mvsReqs{buildList: append(upgraded, mustSelect...)}, mustSelect...)
-       if err != nil {
-               return err
+       var enqueue func(m module.Version, depth modDepth)
+       enqueue = func(m module.Version, depth modDepth) {
+               if m.Version == "none" {
+                       return
+               }
+
+               if depth == eager {
+                       if _, dup := loadingEager.LoadOrStore(m, nil); dup {
+                               // m has already been enqueued for loading. Since eager loading may
+                               // follow cycles in the the requirement graph, we need to return early
+                               // to avoid making the load queue infinitely long.
+                               return
+                       }
+               }
+
+               loadQueue.Add(func() {
+                       summary, err := loadOne(m)
+                       if err != nil {
+                               return // findError will report the error later.
+                       }
+
+                       // If the version in m's go.mod file implies eager loading, then we cannot
+                       // assume that the explicit requirements of m (added by loadOne) are
+                       // sufficient to build the packages it contains. We must load its full
+                       // transitive dependency graph to be sure that we see all relevant
+                       // dependencies.
+                       if depth == eager || summary.depth == eager {
+                               for _, r := range summary.require {
+                                       enqueue(r, eager)
+                               }
+                       }
+               })
        }
 
-       final, err := mvs.Upgrade(Target, &mvsReqs{buildList: downgraded}, mustSelect...)
-       if err != nil {
-               return err
+       for _, m := range roots {
+               enqueue(m, depth)
        }
+       <-loadQueue.Idle()
 
-       selected := make(map[string]module.Version, len(final))
-       for _, m := range final {
-               selected[m.Path] = m
+       if hasError {
+               return mg, mg.findError()
        }
-       inconsistent := false
-       for _, m := range mustSelect {
-               s, ok := selected[m.Path]
-               if !ok {
-                       if m.Version != "none" {
-                               panic(fmt.Sprintf("internal error: mvs.BuildList lost %v", m))
-                       }
-                       continue
-               }
-               if s.Version != m.Version {
-                       inconsistent = true
-                       break
-               }
+       return mg, nil
+}
+
+// RequiredBy returns the dependencies required by module m in the graph,
+// or ok=false if module m's dependencies are not relevant (such as if they
+// are pruned out by lazy loading).
+//
+// The caller must not modify the returned slice, but may safely append to it
+// and may rely on it not to be modified.
+func (mg *ModuleGraph) RequiredBy(m module.Version) (reqs []module.Version, ok bool) {
+       return mg.g.RequiredBy(m)
+}
+
+// Selected returns the selected version of the module with the given path.
+//
+// If no version is selected, Selected returns version "none".
+func (mg *ModuleGraph) Selected(path string) (version string) {
+       return mg.g.Selected(path)
+}
+
+// WalkBreadthFirst invokes f once, in breadth-first order, for each module
+// version other than "none" that appears in the graph, regardless of whether
+// that version is selected.
+func (mg *ModuleGraph) WalkBreadthFirst(f func(m module.Version)) {
+       mg.g.WalkBreadthFirst(f)
+}
+
+// BuildList returns the selected versions of all modules present in the graph,
+// beginning with Target.
+//
+// The order of the remaining elements in the list is deterministic
+// but arbitrary.
+//
+// The caller must not modify the returned list, but may safely append to it
+// and may rely on it not to be modified.
+func (mg *ModuleGraph) BuildList() []module.Version {
+       mg.buildListOnce.Do(func() {
+               mg.buildList = capVersionSlice(mg.g.BuildList())
+       })
+       return mg.buildList
+}
+
+func (mg *ModuleGraph) findError() error {
+       errStack := mg.g.FindPath(func(m module.Version) bool {
+               cached := mg.loadCache.Get(m)
+               return cached != nil && cached.(summaryError).err != nil
+       })
+       if len(errStack) > 0 {
+               err := mg.loadCache.Get(errStack[len(errStack)-1]).(summaryError).err
+               var noUpgrade func(from, to module.Version) bool
+               return mvs.NewBuildListError(err, errStack, noUpgrade)
        }
 
-       if !inconsistent {
-               buildList = final
-               additionalExplicitRequirements = make([]string, 0, len(mustSelect))
-               for _, m := range mustSelect {
-                       if m.Version != "none" {
-                               additionalExplicitRequirements = append(additionalExplicitRequirements, m.Path)
-                       }
+       return nil
+}
+
+func (mg *ModuleGraph) allRootsSelected() bool {
+       roots, _ := mg.g.RequiredBy(Target)
+       for _, m := range roots {
+               if mg.Selected(m.Path) != m.Version {
+                       return false
                }
-               return nil
        }
+       return true
+}
 
-       // We overshot one or more of the modules in mustSelected, which means that
-       // Downgrade removed something in mustSelect because it conflicted with
-       // something else in mustSelect.
-       //
-       // Walk the requirement graph to find the conflict.
-       //
-       // TODO(bcmills): Ideally, mvs.Downgrade (or a replacement for it) would do
-       // this directly.
+// LoadModGraph loads and returns the graph of module dependencies of the main module,
+// without loading any packages.
+//
+// If the goVersion string is non-empty, the returned graph is the graph
+// as interpreted by the given Go version (instead of the version indicated
+// in the go.mod file).
+//
+// Modules are loaded automatically (and lazily) in LoadPackages:
+// LoadModGraph need only be called if LoadPackages is not,
+// typically in commands that care about modules but no particular package.
+func LoadModGraph(ctx context.Context, goVersion string) *ModuleGraph {
+       rs := LoadModFile(ctx)
 
-       reqs := &mvsReqs{buildList: final}
-       reason := map[module.Version]module.Version{}
-       for _, m := range mustSelect {
-               reason[m] = m
-       }
-       queue := mustSelect[:len(mustSelect):len(mustSelect)]
-       for len(queue) > 0 {
-               var m module.Version
-               m, queue = queue[0], queue[1:]
-               required, err := reqs.Required(m)
-               if err != nil {
-                       return err
+       if goVersion != "" {
+               depth := modDepthFromGoVersion(goVersion)
+               if depth == eager && rs.depth != eager {
+                       // Use newRequirements instead of convertDepth because convertDepth
+                       // also updates roots; here, we want to report the unmodified roots
+                       // even though they may seem inconsistent.
+                       rs = newRequirements(eager, rs.rootModules, rs.direct)
                }
-               for _, r := range required {
-                       if _, ok := reason[r]; !ok {
-                               reason[r] = reason[m]
-                               queue = append(queue, r)
-                       }
+
+               mg, err := rs.Graph(ctx)
+               if err != nil {
+                       base.Fatalf("go: %v", err)
                }
+               return mg
        }
 
-       var conflicts []Conflict
-       for _, m := range mustSelect {
-               s, ok := selected[m.Path]
-               if !ok {
-                       if m.Version != "none" {
-                               panic(fmt.Sprintf("internal error: mvs.BuildList lost %v", m))
-                       }
-                       continue
-               }
-               if s.Version != m.Version {
-                       conflicts = append(conflicts, Conflict{
-                               Source:     reason[s],
-                               Dep:        s,
-                               Constraint: m,
-                       })
+       rs, mg, err := expandGraph(ctx, rs)
+       if err != nil {
+               base.Fatalf("go: %v", err)
+       }
+
+       commitRequirements(ctx, modFileGoVersion(), rs)
+       return mg
+}
+
+// expandGraph loads the complete module graph from rs.
+//
+// If the complete graph reveals that some root of rs is not actually the
+// selected version of its path, expandGraph computes a new set of roots that
+// are consistent. (When lazy loading is implemented, this may result in
+// upgrades to other modules due to requirements that were previously pruned
+// out.)
+//
+// expandGraph returns the updated roots, along with the module graph loaded
+// from those roots and any error encountered while loading that graph.
+// expandGraph returns non-nil requirements and a non-nil graph regardless of
+// errors. On error, the roots might not be updated to be consistent.
+func expandGraph(ctx context.Context, rs *Requirements) (*Requirements, *ModuleGraph, error) {
+       mg, mgErr := rs.Graph(ctx)
+       if mgErr != nil {
+               // Without the graph, we can't update the roots: we don't know which
+               // versions of transitive dependencies would be selected.
+               return rs, mg, mgErr
+       }
+
+       if !mg.allRootsSelected() {
+               // The roots of rs are not consistent with the rest of the graph. Update
+               // them. In an eager module this is a no-op for the build list as a whole —
+               // it just promotes what were previously transitive requirements to be
+               // roots — but in a lazy module it may pull in previously-irrelevant
+               // transitive dependencies.
+
+               newRS, rsErr := updateRoots(ctx, rs.direct, rs, nil, nil, false)
+               if rsErr != nil {
+                       // Failed to update roots, perhaps because of an error in a transitive
+                       // dependency needed for the update. Return the original Requirements
+                       // instead.
+                       return rs, mg, rsErr
                }
+               rs = newRS
+               mg, mgErr = rs.Graph(ctx)
        }
 
-       return &ConstraintError{
-               Conflicts: conflicts,
+       return rs, mg, mgErr
+}
+
+// EditBuildList edits the global build list by first adding every module in add
+// to the existing build list, then adjusting versions (and adding or removing
+// requirements as needed) until every module in mustSelect is selected at the
+// given version.
+//
+// (Note that the newly-added modules might not be selected in the resulting
+// build list: they could be lower than existing requirements or conflict with
+// versions in mustSelect.)
+//
+// If the versions listed in mustSelect are mutually incompatible (due to one of
+// the listed modules requiring a higher version of another), EditBuildList
+// returns a *ConstraintError and leaves the build list in its previous state.
+//
+// On success, EditBuildList reports whether the selected version of any module
+// in the build list may have been changed (possibly to or from "none") as a
+// result.
+func EditBuildList(ctx context.Context, add, mustSelect []module.Version) (changed bool, err error) {
+       rs, changed, err := editRequirements(ctx, LoadModFile(ctx), add, mustSelect)
+       if err != nil {
+               return false, err
        }
+       commitRequirements(ctx, modFileGoVersion(), rs)
+       return changed, err
 }
 
 // A ConstraintError describes inconsistent constraints in EditBuildList
@@ -216,93 +529,574 @@ type Conflict struct {
        Constraint module.Version
 }
 
-// ReloadBuildList resets the state of loaded packages, then loads and returns
-// the build list set by EditBuildList.
-func ReloadBuildList() []module.Version {
-       loaded = loadFromRoots(loaderParams{
-               PackageOpts: PackageOpts{
-                       Tags: imports.Tags(),
-               },
-               listRoots:          func() []string { return nil },
-               allClosesOverTests: index.allPatternClosesOverTests(), // but doesn't matter because the root list is empty.
-       })
-       return capVersionSlice(buildList)
+// tidyRoots trims the root dependencies to the minimal requirements needed to
+// both retain the same versions of all packages in pkgs and satisfy the
+// lazy loading invariants (if applicable).
+func tidyRoots(ctx context.Context, rs *Requirements, pkgs []*loadPkg) (*Requirements, error) {
+       if rs.depth == eager {
+               return tidyEagerRoots(ctx, rs.direct, pkgs)
+       }
+       return tidyLazyRoots(ctx, rs.direct, pkgs)
+}
+
+func updateRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) {
+       if rs.depth == eager {
+               return updateEagerRoots(ctx, direct, rs, add)
+       }
+       return updateLazyRoots(ctx, direct, rs, pkgs, add, rootsImported)
+}
+
+// tidyLazyRoots returns a minimal set of root requirements that maintains the
+// "lazy loading" invariants of the go.mod file for the given packages:
+//
+//     1. For each package marked with pkgInAll, the module path that provided that
+//        package is included as a root.
+//     2. For all packages, the module that provided that package either remains
+//        selected at the same version or is upgraded by the dependencies of a
+//        root.
+//
+// If any module that provided a package has been upgraded above its previous,
+// version, the caller may need to reload and recompute the package graph.
+//
+// To ensure that the loading process eventually converges, the caller should
+// add any needed roots from the tidy root set (without removing existing untidy
+// roots) until the set of roots has converged.
+func tidyLazyRoots(ctx context.Context, direct map[string]bool, pkgs []*loadPkg) (*Requirements, error) {
+       var (
+               roots        []module.Version
+               pathIncluded = map[string]bool{Target.Path: true}
+       )
+       // We start by adding roots for every package in "all".
+       //
+       // Once that is done, we may still need to add more roots to cover upgraded or
+       // otherwise-missing test dependencies for packages in "all". For those test
+       // dependencies, we prefer to add roots for packages with shorter import
+       // stacks first, on the theory that the module requirements for those will
+       // tend to fill in the requirements for their transitive imports (which have
+       // deeper import stacks). So we add the missing dependencies for one depth at
+       // a time, starting with the packages actually in "all" and expanding outwards
+       // until we have scanned every package that was loaded.
+       var (
+               queue  []*loadPkg
+               queued = map[*loadPkg]bool{}
+       )
+       for _, pkg := range pkgs {
+               if !pkg.flags.has(pkgInAll) {
+                       continue
+               }
+               if pkg.fromExternalModule() && !pathIncluded[pkg.mod.Path] {
+                       roots = append(roots, pkg.mod)
+                       pathIncluded[pkg.mod.Path] = true
+               }
+               queue = append(queue, pkg)
+               queued[pkg] = true
+       }
+       module.Sort(roots)
+       tidy := newRequirements(lazy, roots, direct)
+
+       for len(queue) > 0 {
+               roots = tidy.rootModules
+               mg, err := tidy.Graph(ctx)
+               if err != nil {
+                       return nil, err
+               }
+
+               prevQueue := queue
+               queue = nil
+               for _, pkg := range prevQueue {
+                       m := pkg.mod
+                       if m.Path == "" {
+                               continue
+                       }
+                       for _, dep := range pkg.imports {
+                               if !queued[dep] {
+                                       queue = append(queue, dep)
+                                       queued[dep] = true
+                               }
+                       }
+                       if pkg.test != nil && !queued[pkg.test] {
+                               queue = append(queue, pkg.test)
+                               queued[pkg.test] = true
+                       }
+                       if !pathIncluded[m.Path] {
+                               if s := mg.Selected(m.Path); cmpVersion(s, m.Version) < 0 {
+                                       roots = append(roots, m)
+                               }
+                               pathIncluded[m.Path] = true
+                       }
+               }
+
+               if len(roots) > len(tidy.rootModules) {
+                       module.Sort(roots)
+                       tidy = newRequirements(lazy, roots, tidy.direct)
+               }
+       }
+
+       _, err := tidy.Graph(ctx)
+       if err != nil {
+               return nil, err
+       }
+       return tidy, nil
 }
 
-// CheckTidyVersion reports an error to stderr if the Go version indicated by
-// the go.mod file is not supported by this version of the 'go' command.
+// updateLazyRoots returns a set of root requirements that maintains the “lazy
+// loading” invariants of the go.mod file:
+//
+//     1. The selected version of the module providing each package marked with
+//        either pkgInAll or pkgIsRoot is included as a root.
+//        Note that certain root patterns (such as '...') may explode the root set
+//        to contain every module that provides any package imported (or merely
+//        required) by any other module.
+//     2. Each root appears only once, at the selected version of its path
+//        (if rs.graph is non-nil) or at the highest version otherwise present as a
+//        root (otherwise).
+//     3. Every module path that appears as a root in rs remains a root.
+//     4. Every version in add is selected at its given version unless upgraded by
+//        (the dependencies of) an existing root or another module in add.
+//
+// The packages in pkgs are assumed to have been loaded from either the roots of
+// rs or the modules selected in the graph of rs.
+//
+// The above invariants together imply the “lazy loading” invariants for the
+// go.mod file:
+//
+//     1. (The import invariant.) Every module that provides a package transitively
+//        imported by any package or test in the main module is included as a root.
+//        This follows by induction from (1) and (3) above. Transitively-imported
+//        packages loaded during this invocation are marked with pkgInAll (1),
+//        and by hypothesis any transitively-imported packages loaded in previous
+//        invocations were already roots in rs (3).
+//
+//     2. (The argument invariant.) Every module that provides a package matching
+//        an explicit package pattern is included as a root. This follows directly
+//        from (1): packages matching explicit package patterns are marked with
+//        pkgIsRoot.
+//
+//     3. (The completeness invariant.) Every module that contributed any package
+//        to the build is required by either the main module or one of the modules
+//        it requires explicitly. This invariant is left up to the caller, who must
+//        not load packages from outside the module graph but may add roots to the
+//        graph, but is facilited by (3). If the caller adds roots to the graph in
+//        order to resolve missing packages, then updateLazyRoots will retain them,
+//        the selected versions of those roots cannot regress, and they will
+//        eventually be written back to the main module's go.mod file.
 //
-// If allowError is false, such an error terminates the program.
-func CheckTidyVersion(ctx context.Context, allowError bool) {
-       LoadModFile(ctx)
-       if index.goVersionV == "" {
-               return
+// (See https://golang.org/design/36460-lazy-module-loading#invariants for more
+// detail.)
+func updateLazyRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) {
+       roots := rs.rootModules
+       rootsUpgraded := false
+
+       spotCheckRoot := map[module.Version]bool{}
+
+       // “The selected version of the module providing each package marked with
+       // either pkgInAll or pkgIsRoot is included as a root.”
+       needSort := false
+       for _, pkg := range pkgs {
+               if !pkg.fromExternalModule() {
+                       // pkg was not loaded from a module dependency, so we don't need
+                       // to do anything special to maintain that dependency.
+                       continue
+               }
+
+               switch {
+               case pkg.flags.has(pkgInAll):
+                       // pkg is transitively imported by a package or test in the main module.
+                       // We need to promote the module that maintains it to a root: if some
+                       // other module depends on the main module, and that other module also
+                       // uses lazy loading, it will expect to find all of our transitive
+                       // dependencies by reading just our go.mod file, not the go.mod files of
+                       // everything we depend on.
+                       //
+                       // (This is the “import invariant” that makes lazy loading possible.)
+
+               case rootsImported && pkg.flags.has(pkgFromRoot):
+                       // pkg is a transitive dependency of some root, and we are treating the
+                       // roots as if they are imported by the main module (as in 'go get').
+
+               case pkg.flags.has(pkgIsRoot):
+                       // pkg is a root of the package-import graph. (Generally this means that
+                       // it matches a command-line argument.) We want future invocations of the
+                       // 'go' command — such as 'go test' on the same package — to continue to
+                       // use the same versions of its dependencies that we are using right now.
+                       // So we need to bring this package's dependencies inside the lazy-loading
+                       // horizon.
+                       //
+                       // Making the module containing this package a root of the module graph
+                       // does exactly that: if the module containing the package is lazy it
+                       // should satisfy the import invariant itself, so all of its dependencies
+                       // should be in its go.mod file, and if the module containing the package
+                       // is eager then if we make it a root we will load all of its transitive
+                       // dependencies into the module graph.
+                       //
+                       // (This is the “argument invariant” of lazy loading, and is important for
+                       // reproducibility.)
+
+               default:
+                       // pkg is a dependency of some other package outside of the main module.
+                       // As far as we know it's not relevant to the main module (and thus not
+                       // relevant to consumers of the main module either), and its dependencies
+                       // should already be in the module graph — included in the dependencies of
+                       // the package that imported it.
+                       continue
+               }
+
+               if _, ok := rs.rootSelected(pkg.mod.Path); ok {
+                       // It is possible that the main module's go.mod file is incomplete or
+                       // otherwise erroneous — for example, perhaps the author forgot to 'git
+                       // add' their updated go.mod file after adding a new package import, or
+                       // perhaps they made an edit to the go.mod file using a third-party tool
+                       // ('git merge'?) that doesn't maintain consistency for module
+                       // dependencies. If that happens, ideally we want to detect the missing
+                       // requirements and fix them up here.
+                       //
+                       // However, we also need to be careful not to be too aggressive. For
+                       // transitive dependencies of external tests, the go.mod file for the
+                       // module containing the test itself is expected to provide all of the
+                       // relevant dependencies, and we explicitly don't want to pull in
+                       // requirements on *irrelevant* requirements that happen to occur in the
+                       // go.mod files for these transitive-test-only dependencies. (See the test
+                       // in mod_lazy_test_horizon.txt for a concrete example.
+                       //
+                       // The “goldilocks zone” seems to be to spot-check exactly the same
+                       // modules that we promote to explicit roots: namely, those that provide
+                       // packages transitively imported by the main module, and those that
+                       // provide roots of the package-import graph. That will catch erroneous
+                       // edits to the main module's go.mod file and inconsistent requirements in
+                       // dependencies that provide imported packages, but will ignore erroneous
+                       // or misleading requirements in dependencies that aren't obviously
+                       // relevant to the packages in the main module.
+                       spotCheckRoot[pkg.mod] = true
+               } else {
+                       roots = append(roots, pkg.mod)
+                       rootsUpgraded = true
+                       // The roots slice was initially sorted because rs.rootModules was sorted,
+                       // but the root we just added could be out of order.
+                       needSort = true
+               }
        }
 
-       tags := build.Default.ReleaseTags
-       maxGo := tags[len(tags)-1]
-       if !strings.HasPrefix(maxGo, "go") || !modfile.GoVersionRE.MatchString(maxGo[2:]) {
-               base.Fatalf("go: unrecognized go version %q", maxGo)
+       for _, m := range add {
+               if v, ok := rs.rootSelected(m.Path); !ok || cmpVersion(v, m.Version) < 0 {
+                       roots = append(roots, m)
+                       rootsUpgraded = true
+                       needSort = true
+               }
+       }
+       if needSort {
+               module.Sort(roots)
        }
-       max := maxGo[2:]
 
-       if semver.Compare(index.goVersionV, "v"+max) > 0 {
-               have := index.goVersionV[1:]
-               if allowError {
-                       fmt.Fprintf(os.Stderr, "go mod tidy: go.mod file indicates go %s, but maximum supported version is %s\n", have, max)
+       // "Each root appears only once, at the selected version of its path ….”
+       for {
+               var mg *ModuleGraph
+               if rootsUpgraded {
+                       // We've added or upgraded one or more roots, so load the full module
+                       // graph so that we can update those roots to be consistent with other
+                       // requirements.
+                       if cfg.BuildMod != "mod" {
+                               // Our changes to the roots may have moved dependencies into or out of
+                               // the lazy-loading horizon, which could in turn change the selected
+                               // versions of other modules. (Unlike for eager modules, for lazy
+                               // modules adding or removing an explicit root is a semantic change, not
+                               // just a cosmetic one.)
+                               return rs, errGoModDirty
+                       }
+
+                       rs = newRequirements(lazy, roots, direct)
+                       var err error
+                       mg, err = rs.Graph(ctx)
+                       if err != nil {
+                               return rs, err
+                       }
                } else {
-                       base.Fatalf("go mod tidy: go.mod file indicates go %s, but maximum supported version is %s\n", have, max)
+                       // Since none of the roots have been upgraded, we have no reason to
+                       // suspect that they are inconsistent with the requirements of any other
+                       // roots. Only look at the full module graph if we've already loaded it;
+                       // otherwise, just spot-check the explicit requirements of the roots from
+                       // which we loaded packages.
+                       if rs.graph.Load() != nil {
+                               // We've already loaded the full module graph, which includes the
+                               // requirements of all of the root modules — even the transitive
+                               // requirements, if they are eager!
+                               mg, _ = rs.Graph(ctx)
+                       } else if cfg.BuildMod == "vendor" {
+                               // We can't spot-check the requirements of other modules because we
+                               // don't in general have their go.mod files available in the vendor
+                               // directory. (Fortunately this case is impossible, because mg.graph is
+                               // always non-nil in vendor mode!)
+                               panic("internal error: rs.graph is unexpectedly nil with -mod=vendor")
+                       } else if !spotCheckRoots(ctx, rs, spotCheckRoot) {
+                               // We spot-checked the explicit requirements of the roots that are
+                               // relevant to the packages we've loaded. Unfortunately, they're
+                               // inconsistent in some way; we need to load the full module graph
+                               // so that we can fix the roots properly.
+                               var err error
+                               mg, err = rs.Graph(ctx)
+                               if err != nil {
+                                       return rs, err
+                               }
+                       }
+               }
+
+               roots = make([]module.Version, 0, len(rs.rootModules))
+               rootsUpgraded = false
+               inRootPaths := make(map[string]bool, len(rs.rootModules)+1)
+               inRootPaths[Target.Path] = true
+               for _, m := range rs.rootModules {
+                       if inRootPaths[m.Path] {
+                               // This root specifies a redundant path. We already retained the
+                               // selected version of this path when we saw it before, so omit the
+                               // redundant copy regardless of its version.
+                               //
+                               // When we read the full module graph, we include the dependencies of
+                               // every root even if that root is redundant. That better preserves
+                               // reproducibility if, say, some automated tool adds a redundant
+                               // 'require' line and then runs 'go mod tidy' to try to make everything
+                               // consistent, since the requirements of the older version are carried
+                               // over.
+                               //
+                               // So omitting a root that was previously present may *reduce* the
+                               // selected versions of non-roots, but merely removing a requirement
+                               // cannot *increase* the selected versions of other roots as a result —
+                               // we don't need to mark this change as an upgrade. (This particular
+                               // change cannot invalidate any other roots.)
+                               continue
+                       }
+
+                       var v string
+                       if mg == nil {
+                               v, _ = rs.rootSelected(m.Path)
+                       } else {
+                               v = mg.Selected(m.Path)
+                       }
+                       roots = append(roots, module.Version{Path: m.Path, Version: v})
+                       inRootPaths[m.Path] = true
+                       if v != m.Version {
+                               rootsUpgraded = true
+                       }
                }
+               // Note that rs.rootModules was already sorted by module path and version,
+               // and we appended to the roots slice in the same order and guaranteed that
+               // each path has only one version, so roots is also sorted by module path
+               // and (trivially) version.
+
+               if !rootsUpgraded {
+                       // The root set has converged: every root going into this iteration was
+                       // already at its selected version, although we have have removed other
+                       // (redundant) roots for the same path.
+                       break
+               }
+       }
+
+       if rs.depth == lazy && reflect.DeepEqual(roots, rs.rootModules) && reflect.DeepEqual(direct, rs.direct) {
+               // The root set is unchanged and rs was already lazy, so keep rs to
+               // preserve its cached ModuleGraph (if any).
+               return rs, nil
        }
+       return newRequirements(lazy, roots, direct), nil
 }
 
-// TidyBuildList trims the build list to the minimal requirements needed to
-// retain the same versions of all packages from the preceding call to
-// LoadPackages.
-func TidyBuildList() {
-       used := map[module.Version]bool{Target: true}
-       for _, pkg := range loaded.pkgs {
-               used[pkg.mod] = true
+// spotCheckRoots reports whether the versions of the roots in rs satisfy the
+// explicit requirements of the modules in mods.
+func spotCheckRoots(ctx context.Context, rs *Requirements, mods map[module.Version]bool) bool {
+       ctx, cancel := context.WithCancel(ctx)
+       defer cancel()
+
+       work := par.NewQueue(runtime.GOMAXPROCS(0))
+       for m := range mods {
+               m := m
+               work.Add(func() {
+                       if ctx.Err() != nil {
+                               return
+                       }
+
+                       summary, err := goModSummary(m)
+                       if err != nil {
+                               cancel()
+                               return
+                       }
+
+                       for _, r := range summary.require {
+                               if v, ok := rs.rootSelected(r.Path); ok && cmpVersion(v, r.Version) < 0 {
+                                       cancel()
+                                       return
+                               }
+                       }
+               })
+       }
+       <-work.Idle()
+
+       if ctx.Err() != nil {
+               // Either we failed a spot-check, or the caller no longer cares about our
+               // answer anyway.
+               return false
        }
 
-       keep := []module.Version{Target}
-       var direct []string
-       for _, m := range buildList[1:] {
-               if used[m] {
+       return true
+}
+
+// tidyEagerRoots returns a minimal set of root requirements that maintains the
+// selected version of every module that provided a package in pkgs, and
+// includes the selected version of every such module in direct as a root.
+func tidyEagerRoots(ctx context.Context, direct map[string]bool, pkgs []*loadPkg) (*Requirements, error) {
+       var (
+               keep     []module.Version
+               keptPath = map[string]bool{}
+       )
+       var (
+               rootPaths   []string // module paths that should be included as roots
+               inRootPaths = map[string]bool{}
+       )
+       for _, pkg := range pkgs {
+               if !pkg.fromExternalModule() {
+                       continue
+               }
+               if m := pkg.mod; !keptPath[m.Path] {
                        keep = append(keep, m)
-                       if loaded.direct[m.Path] {
-                               direct = append(direct, m.Path)
-                       }
-               } else if cfg.BuildV {
-                       if _, ok := index.require[m]; ok {
-                               fmt.Fprintf(os.Stderr, "unused %s\n", m.Path)
+                       keptPath[m.Path] = true
+                       if direct[m.Path] && !inRootPaths[m.Path] {
+                               rootPaths = append(rootPaths, m.Path)
+                               inRootPaths[m.Path] = true
                        }
                }
        }
 
-       min, err := mvs.Req(Target, direct, &mvsReqs{buildList: keep})
+       min, err := mvs.Req(Target, rootPaths, &mvsReqs{roots: keep})
        if err != nil {
-               base.Fatalf("go: %v", err)
+               return nil, err
        }
-       buildList = append([]module.Version{Target}, min...)
+       return newRequirements(eager, min, direct), nil
 }
 
-// checkMultiplePaths verifies that a given module path is used as itself
-// or as a replacement for another module, but not both at the same time.
+// updateEagerRoots returns a set of root requirements that includes the selected
+// version of every module path in direct as a root, and maintains the selected
+// version of every module selected in the graph of rs.
 //
-// (See https://golang.org/issue/26607 and https://golang.org/issue/34650.)
-func checkMultiplePaths() {
-       firstPath := make(map[module.Version]string, len(buildList))
-       for _, mod := range buildList {
-               src := mod
-               if rep := Replacement(mod); rep.Path != "" {
-                       src = rep
+// The roots are updated such that:
+//
+//     1. The selected version of every module path in direct is included as a root
+//        (if it is not "none").
+//     2. Each root is the selected version of its path. (We say that such a root
+//        set is “consistent”.)
+//     3. Every version selected in the graph of rs remains selected unless upgraded
+//        by a dependency in add.
+//     4. Every version in add is selected at its given version unless upgraded by
+//        (the dependencies of) an existing root or another module in add.
+func updateEagerRoots(ctx context.Context, direct map[string]bool, rs *Requirements, add []module.Version) (*Requirements, error) {
+       mg, err := rs.Graph(ctx)
+       if err != nil {
+               // We can't ignore errors in the module graph even if the user passed the -e
+               // flag to try to push past them. If we can't load the complete module
+               // dependencies, then we can't reliably compute a minimal subset of them.
+               return rs, err
+       }
+
+       if cfg.BuildMod != "mod" {
+               // Instead of actually updating the requirements, just check that no updates
+               // are needed.
+               if rs == nil {
+                       // We're being asked to reconstruct the requirements from scratch,
+                       // but we aren't even allowed to modify them.
+                       return rs, errGoModDirty
                }
-               if prev, ok := firstPath[src]; !ok {
-                       firstPath[src] = mod.Path
-               } else if prev != mod.Path {
-                       base.Errorf("go: %s@%s used for two different module paths (%s and %s)", src.Path, src.Version, prev, mod.Path)
+               for _, m := range rs.rootModules {
+                       if m.Version != mg.Selected(m.Path) {
+                               // The root version v is misleading: the actual selected version is higher.
+                               return rs, errGoModDirty
+                       }
                }
+               for _, m := range add {
+                       if m.Version != mg.Selected(m.Path) {
+                               return rs, errGoModDirty
+                       }
+               }
+               for mPath := range direct {
+                       if _, ok := rs.rootSelected(mPath); !ok {
+                               // Module m is supposed to be listed explicitly, but isn't.
+                               //
+                               // Note that this condition is also detected (and logged with more
+                               // detail) earlier during package loading, so it shouldn't actually be
+                               // possible at this point — this is just a defense in depth.
+                               return rs, errGoModDirty
+                       }
+               }
+
+               // No explicit roots are missing and all roots are already at the versions
+               // we want to keep. Any other changes we would make are purely cosmetic,
+               // such as pruning redundant indirect dependencies. Per issue #34822, we
+               // ignore cosmetic changes when we cannot update the go.mod file.
+               return rs, nil
+       }
+
+       var (
+               rootPaths   []string // module paths that should be included as roots
+               inRootPaths = map[string]bool{}
+       )
+       for _, root := range rs.rootModules {
+               // If the selected version of the root is the same as what was already
+               // listed in the go.mod file, retain it as a root (even if redundant) to
+               // avoid unnecessary churn. (See https://golang.org/issue/34822.)
+               //
+               // We do this even for indirect requirements, since we don't know why they
+               // were added and they could become direct at any time.
+               if !inRootPaths[root.Path] && mg.Selected(root.Path) == root.Version {
+                       rootPaths = append(rootPaths, root.Path)
+                       inRootPaths[root.Path] = true
+               }
+       }
+
+       // “The selected version of every module path in direct is included as a root.”
+       //
+       // This is only for convenience and clarity for end users: in an eager module,
+       // the choice of explicit vs. implicit dependency has no impact on MVS
+       // selection (for itself or any other module).
+       keep := append(mg.BuildList()[1:], add...)
+       for _, m := range keep {
+               if direct[m.Path] && !inRootPaths[m.Path] {
+                       rootPaths = append(rootPaths, m.Path)
+                       inRootPaths[m.Path] = true
+               }
+       }
+
+       min, err := mvs.Req(Target, rootPaths, &mvsReqs{roots: keep})
+       if err != nil {
+               return rs, err
+       }
+       if rs.depth == eager && reflect.DeepEqual(min, rs.rootModules) && reflect.DeepEqual(direct, rs.direct) {
+               // The root set is unchanged and rs was already eager, so keep rs to
+               // preserve its cached ModuleGraph (if any).
+               return rs, nil
+       }
+       return newRequirements(eager, min, direct), nil
+}
+
+// convertDepth returns a version of rs with the given depth.
+// If rs already has the given depth, convertDepth returns rs unmodified.
+func convertDepth(ctx context.Context, rs *Requirements, depth modDepth) (*Requirements, error) {
+       if rs.depth == depth {
+               return rs, nil
+       }
+
+       if depth == eager {
+               // We are converting a lazy module to an eager one. The roots of an eager
+               // module graph are a superset of the roots of a lazy graph, so we don't
+               // need to add any new roots — we just need to prune away the ones that are
+               // redundant given eager loading, which is exactly what updateEagerRoots
+               // does.
+               return updateEagerRoots(ctx, rs.direct, rs, nil)
+       }
+
+       // We are converting an eager module to a lazy one. The module graph of an
+       // eager module includes the transitive dependencies of every module in the
+       // build list.
+       //
+       // Hey, we can express that as a lazy root set! “Include the transitive
+       // dependencies of every module in the build list” is exactly what happens in
+       // a lazy module if we promote every module in the build list to a root!
+       mg, err := rs.Graph(ctx)
+       if err != nil {
+               return rs, err
        }
-       base.ExitIfErrors()
+       return newRequirements(lazy, mg.BuildList()[1:], rs.direct), nil
 }
diff --git a/libgo/go/cmd/go/internal/modload/edit.go b/libgo/go/cmd/go/internal/modload/edit.go
new file mode 100644 (file)
index 0000000..c350b9d
--- /dev/null
@@ -0,0 +1,569 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package modload
+
+import (
+       "cmd/go/internal/mvs"
+       "context"
+       "reflect"
+       "sort"
+
+       "golang.org/x/mod/module"
+       "golang.org/x/mod/semver"
+)
+
+// editRequirements returns an edited version of rs such that:
+//
+//     1. Each module version in mustSelect is selected.
+//
+//     2. Each module version in tryUpgrade is upgraded toward the indicated
+//        version as far as can be done without violating (1).
+//
+//     3. Each module version in rs.rootModules (or rs.graph, if rs.depth is eager)
+//        is downgraded from its original version only to the extent needed to
+//        satisfy (1), or upgraded only to the extent needed to satisfy (1) and
+//        (2).
+//
+//     4. No module is upgraded above the maximum version of its path found in the
+//        dependency graph of rs, the combined dependency graph of the versions in
+//        mustSelect, or the dependencies of each individual module version in
+//        tryUpgrade.
+//
+// Generally, the module versions in mustSelect are due to the module or a
+// package within the module matching an explicit command line argument to 'go
+// get', and the versions in tryUpgrade are transitive dependencies that are
+// either being upgraded by 'go get -u' or being added to satisfy some
+// otherwise-missing package import.
+func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSelect []module.Version) (edited *Requirements, changed bool, err error) {
+       limiter, err := limiterForEdit(ctx, rs, tryUpgrade, mustSelect)
+       if err != nil {
+               return rs, false, err
+       }
+
+       var conflicts []Conflict
+       for _, m := range mustSelect {
+               conflict, err := limiter.Select(m)
+               if err != nil {
+                       return rs, false, err
+               }
+               if conflict.Path != "" {
+                       conflicts = append(conflicts, Conflict{
+                               Source: m,
+                               Dep:    conflict,
+                               Constraint: module.Version{
+                                       Path:    conflict.Path,
+                                       Version: limiter.max[conflict.Path],
+                               },
+                       })
+               }
+       }
+       if len(conflicts) > 0 {
+               return rs, false, &ConstraintError{Conflicts: conflicts}
+       }
+
+       mods, changed, err := selectPotentiallyImportedModules(ctx, limiter, rs, tryUpgrade)
+       if err != nil {
+               return rs, false, err
+       }
+
+       var roots []module.Version
+       if rs.depth == eager {
+               // In an eager module, modules that provide packages imported by the main
+               // module may either be explicit roots or implicit transitive dependencies.
+               // We promote the modules in mustSelect to be explicit requirements.
+               var rootPaths []string
+               for _, m := range mustSelect {
+                       if m.Version != "none" && m.Path != Target.Path {
+                               rootPaths = append(rootPaths, m.Path)
+                       }
+               }
+               if !changed && len(rootPaths) == 0 {
+                       // The build list hasn't changed and we have no new roots to add.
+                       // We don't need to recompute the minimal roots for the module.
+                       return rs, false, nil
+               }
+
+               for _, m := range mods {
+                       if v, ok := rs.rootSelected(m.Path); ok && (v == m.Version || rs.direct[m.Path]) {
+                               // m.Path was formerly a root, and either its version hasn't changed or
+                               // we believe that it provides a package directly imported by a package
+                               // or test in the main module. For now we'll assume that it is still
+                               // relevant enough to remain a root. If we actually load all of the
+                               // packages and tests in the main module (which we are not doing here),
+                               // we can revise the explicit roots at that point.
+                               rootPaths = append(rootPaths, m.Path)
+                       }
+               }
+
+               roots, err = mvs.Req(Target, rootPaths, &mvsReqs{roots: mods})
+               if err != nil {
+                       return nil, false, err
+               }
+       } else {
+               // In a lazy module, every module that provides a package imported by the
+               // main module must be retained as a root.
+               roots = mods
+               if !changed {
+                       // Because the roots we just computed are unchanged, the entire graph must
+                       // be the same as it was before. Save the original rs, since we have
+                       // probably already loaded its requirement graph.
+                       return rs, false, nil
+               }
+       }
+
+       // A module that is not even in the build list necessarily cannot provide
+       // any imported packages. Mark as direct only the direct modules that are
+       // still in the build list.
+       //
+       // TODO(bcmills): Would it make more sense to leave the direct map as-is
+       // but allow it to refer to modules that are no longer in the build list?
+       // That might complicate updateRoots, but it may be cleaner in other ways.
+       direct := make(map[string]bool, len(rs.direct))
+       for _, m := range roots {
+               if rs.direct[m.Path] {
+                       direct[m.Path] = true
+               }
+       }
+       return newRequirements(rs.depth, roots, direct), changed, nil
+}
+
+// limiterForEdit returns a versionLimiter with its max versions set such that
+// the max version for every module path in mustSelect is the version listed
+// there, and the max version for every other module path is the maximum version
+// of its path found in the dependency graph of rs, the combined dependency
+// graph of the versions in mustSelect, or the dependencies of each individual
+// module version in tryUpgrade.
+func limiterForEdit(ctx context.Context, rs *Requirements, tryUpgrade, mustSelect []module.Version) (*versionLimiter, error) {
+       mg, err := rs.Graph(ctx)
+       if err != nil {
+               return nil, err
+       }
+
+       maxVersion := map[string]string{} // module path → version
+       restrictTo := func(m module.Version) {
+               v, ok := maxVersion[m.Path]
+               if !ok || cmpVersion(v, m.Version) > 0 {
+                       maxVersion[m.Path] = m.Version
+               }
+       }
+
+       if rs.depth == eager {
+               // Eager go.mod files don't indicate which transitive dependencies are
+               // actually relevant to the main module, so we have to assume that any module
+               // that could have provided any package — that is, any module whose selected
+               // version was not "none" — may be relevant.
+               for _, m := range mg.BuildList() {
+                       restrictTo(m)
+               }
+       } else {
+               // The go.mod file explicitly records every module that provides a package
+               // imported by the main module.
+               //
+               // If we need to downgrade an existing root or a new root found in
+               // tryUpgrade, we don't want to allow that downgrade to incidentally upgrade
+               // a module imported by the main module to some arbitrary version.
+               // However, we don't particularly care about arbitrary upgrades to modules
+               // that are (at best) only providing packages imported by tests of
+               // dependencies outside the main module.
+               for _, m := range rs.rootModules {
+                       restrictTo(module.Version{
+                               Path:    m.Path,
+                               Version: mg.Selected(m.Path),
+                       })
+               }
+       }
+
+       if err := raiseLimitsForUpgrades(ctx, maxVersion, rs.depth, tryUpgrade, mustSelect); err != nil {
+               return nil, err
+       }
+
+       // The versions in mustSelect override whatever we would naively select —
+       // we will downgrade other modules as needed in order to meet them.
+       for _, m := range mustSelect {
+               restrictTo(m)
+       }
+
+       return newVersionLimiter(rs.depth, maxVersion), nil
+}
+
+// raiseLimitsForUpgrades increases the module versions in maxVersions to the
+// versions that would be needed to allow each of the modules in tryUpgrade
+// (individually) and all of the modules in mustSelect (simultaneously) to be
+// added as roots.
+//
+// Versions not present in maxVersion are unrestricted, and it is assumed that
+// they will not be promoted to root requirements (and thus will not contribute
+// their own dependencies if the main module is lazy).
+//
+// These limits provide an upper bound on how far a module may be upgraded as
+// part of an incidental downgrade, if downgrades are needed in order to select
+// the versions in mustSelect.
+func raiseLimitsForUpgrades(ctx context.Context, maxVersion map[string]string, depth modDepth, tryUpgrade []module.Version, mustSelect []module.Version) error {
+       // allow raises the limit for m.Path to at least m.Version.
+       // If m.Path was already unrestricted, it remains unrestricted.
+       allow := func(m module.Version) {
+               v, ok := maxVersion[m.Path]
+               if !ok {
+                       return // m.Path is unrestricted.
+               }
+               if cmpVersion(v, m.Version) < 0 {
+                       maxVersion[m.Path] = m.Version
+               }
+       }
+
+       var eagerUpgrades []module.Version
+       if depth == eager {
+               eagerUpgrades = tryUpgrade
+       } else {
+               for _, m := range tryUpgrade {
+                       if m.Path == Target.Path {
+                               // Target is already considered to be higher than any possible m, so we
+                               // won't be upgrading to it anyway and there is no point scanning its
+                               // dependencies.
+                               continue
+                       }
+
+                       summary, err := goModSummary(m)
+                       if err != nil {
+                               return err
+                       }
+                       if summary.depth == eager {
+                               // For efficiency, we'll load all of the eager upgrades as one big
+                               // graph, rather than loading the (potentially-overlapping) subgraph for
+                               // each upgrade individually.
+                               eagerUpgrades = append(eagerUpgrades, m)
+                               continue
+                       }
+
+                       for _, r := range summary.require {
+                               allow(r)
+                       }
+               }
+       }
+
+       if len(eagerUpgrades) > 0 {
+               // Compute the max versions for eager upgrades all together.
+               // Since these modules are eager, we'll end up scanning all of their
+               // transitive dependencies no matter which versions end up selected,
+               // and since we have a large dependency graph to scan we might get
+               // a significant benefit from not revisiting dependencies that are at
+               // common versions among multiple upgrades.
+               upgradeGraph, err := readModGraph(ctx, eager, eagerUpgrades)
+               if err != nil {
+                       if go117LazyTODO {
+                               // Compute the requirement path from a module path in tryUpgrade to the
+                               // error, and the requirement path (if any) from rs.rootModules to the
+                               // tryUpgrade module path. Return a *mvs.BuildListError showing the
+                               // concatenation of the paths (with an upgrade in the middle).
+                       }
+                       return err
+               }
+
+               for _, r := range upgradeGraph.BuildList() {
+                       // Upgrading to m would upgrade to r, and the caller requested that we
+                       // try to upgrade to m, so it's ok to upgrade to r.
+                       allow(r)
+               }
+       }
+
+       if len(mustSelect) > 0 {
+               mustGraph, err := readModGraph(ctx, depth, mustSelect)
+               if err != nil {
+                       return err
+               }
+
+               for _, r := range mustGraph.BuildList() {
+                       // Some module in mustSelect requires r, so we must allow at least r.Version
+                       // unless it conflicts with an entry in mustSelect.
+                       allow(r)
+               }
+       }
+
+       return nil
+}
+
+// selectPotentiallyImportedModules increases the limiter-selected version of
+// every module in rs that potentially provides a package imported (directly or
+// indirectly) by the main module, and every module in tryUpgrade, toward the
+// highest version seen in rs or tryUpgrade, but not above the maximums enforced
+// by the limiter.
+//
+// It returns the list of module versions selected by the limiter, sorted by
+// path, along with a boolean indicating whether that list is different from the
+// list of modules read from rs.
+func selectPotentiallyImportedModules(ctx context.Context, limiter *versionLimiter, rs *Requirements, tryUpgrade []module.Version) (mods []module.Version, changed bool, err error) {
+       for _, m := range tryUpgrade {
+               if err := limiter.UpgradeToward(ctx, m); err != nil {
+                       return nil, false, err
+               }
+       }
+
+       var initial []module.Version
+       if rs.depth == eager {
+               mg, err := rs.Graph(ctx)
+               if err != nil {
+                       return nil, false, err
+               }
+               initial = mg.BuildList()[1:]
+       } else {
+               initial = rs.rootModules
+       }
+       for _, m := range initial {
+               if err := limiter.UpgradeToward(ctx, m); err != nil {
+                       return nil, false, err
+               }
+       }
+
+       mods = make([]module.Version, 0, len(limiter.selected))
+       for path, v := range limiter.selected {
+               if v != "none" && path != Target.Path {
+                       mods = append(mods, module.Version{Path: path, Version: v})
+               }
+       }
+
+       // We've identified acceptable versions for each of the modules, but those
+       // versions are not necessarily consistent with each other: one upgraded or
+       // downgraded module may require a higher (but still allowed) version of
+       // another. The lower version may require extraneous dependencies that aren't
+       // actually relevant, so we need to compute the actual selected versions.
+       mg, err := readModGraph(ctx, rs.depth, mods)
+       if err != nil {
+               return nil, false, err
+       }
+       mods = make([]module.Version, 0, len(limiter.selected))
+       for path, _ := range limiter.selected {
+               if path != Target.Path {
+                       if v := mg.Selected(path); v != "none" {
+                               mods = append(mods, module.Version{Path: path, Version: v})
+                       }
+               }
+       }
+       module.Sort(mods)
+
+       changed = !reflect.DeepEqual(mods, initial)
+
+       return mods, changed, err
+}
+
+// A versionLimiter tracks the versions that may be selected for each module
+// subject to constraints on the maximum versions of transitive dependencies.
+type versionLimiter struct {
+       // depth is the depth at which the dependencies of the modules passed to
+       // Select and UpgradeToward are loaded.
+       depth modDepth
+
+       // max maps each module path to the maximum version that may be selected for
+       // that path.
+       //
+       // Paths with no entry are unrestricted, and we assume that they will not be
+       // promoted to root dependencies (so will not contribute dependencies if the
+       // main module is lazy).
+       max map[string]string
+
+       // selected maps each module path to a version of that path (if known) whose
+       // transitive dependencies do not violate any max version. The version kept
+       // is the highest one found during any call to UpgradeToward for the given
+       // module path.
+       //
+       // If a higher acceptable version is found during a call to UpgradeToward for
+       // some *other* module path, that does not update the selected version.
+       // Ignoring those versions keeps the downgrades computed for two modules
+       // together close to the individual downgrades that would be computed for each
+       // module in isolation. (The only way one module can affect another is if the
+       // final downgraded version of the one module explicitly requires a higher
+       // version of the other.)
+       //
+       // Version "none" of every module is always known not to violate any max
+       // version, so paths at version "none" are omitted.
+       selected map[string]string
+
+       // dqReason records whether and why each each encountered version is
+       // disqualified.
+       dqReason map[module.Version]dqState
+
+       // requiring maps each not-yet-disqualified module version to the versions
+       // that directly require it. If that version becomes disqualified, the
+       // disqualification will be propagated to all of the versions in the list.
+       requiring map[module.Version][]module.Version
+}
+
+// A dqState indicates whether and why a module version is “disqualified” from
+// being used in a way that would incorporate its requirements.
+//
+// The zero dqState indicates that the module version is not known to be
+// disqualified, either because it is ok or because we are currently traversing
+// a cycle that includes it.
+type dqState struct {
+       err      error          // if non-nil, disqualified because the requirements of the module could not be read
+       conflict module.Version // disqualified because the module (transitively) requires dep, which exceeds the maximum version constraint for its path
+}
+
+func (dq dqState) isDisqualified() bool {
+       return dq != dqState{}
+}
+
+// newVersionLimiter returns a versionLimiter that restricts the module paths
+// that appear as keys in max.
+//
+// max maps each module path to its maximum version; paths that are not present
+// in the map are unrestricted. The limiter assumes that unrestricted paths will
+// not be promoted to root dependencies.
+//
+// If depth is lazy, then if a module passed to UpgradeToward or Select is
+// itself lazy, its unrestricted dependencies are skipped when scanning
+// requirements.
+func newVersionLimiter(depth modDepth, max map[string]string) *versionLimiter {
+       return &versionLimiter{
+               depth:     depth,
+               max:       max,
+               selected:  map[string]string{Target.Path: Target.Version},
+               dqReason:  map[module.Version]dqState{},
+               requiring: map[module.Version][]module.Version{},
+       }
+}
+
+// UpgradeToward attempts to upgrade the selected version of m.Path as close as
+// possible to m.Version without violating l's maximum version limits.
+//
+// If depth is lazy and m itself is lazy, the the dependencies of unrestricted
+// dependencies of m will not be followed.
+func (l *versionLimiter) UpgradeToward(ctx context.Context, m module.Version) error {
+       selected, ok := l.selected[m.Path]
+       if ok {
+               if cmpVersion(selected, m.Version) >= 0 {
+                       // The selected version is already at least m, so no upgrade is needed.
+                       return nil
+               }
+       } else {
+               selected = "none"
+       }
+
+       if l.check(m, l.depth).isDisqualified() {
+               candidates, err := versions(ctx, m.Path, CheckAllowed)
+               if err != nil {
+                       // This is likely a transient error reaching the repository,
+                       // rather than a permanent error with the retrieved version.
+                       //
+                       // TODO(golang.org/issue/31730, golang.org/issue/30134):
+                       // decode what to do based on the actual error.
+                       return err
+               }
+
+               // Skip to candidates < m.Version.
+               i := sort.Search(len(candidates), func(i int) bool {
+                       return semver.Compare(candidates[i], m.Version) >= 0
+               })
+               candidates = candidates[:i]
+
+               for l.check(m, l.depth).isDisqualified() {
+                       n := len(candidates)
+                       if n == 0 || cmpVersion(selected, candidates[n-1]) >= 0 {
+                               // We couldn't find a suitable candidate above the already-selected version.
+                               // Retain that version unmodified.
+                               return nil
+                       }
+                       m.Version, candidates = candidates[n-1], candidates[:n-1]
+               }
+       }
+
+       l.selected[m.Path] = m.Version
+       return nil
+}
+
+// Select attempts to set the selected version of m.Path to exactly m.Version.
+func (l *versionLimiter) Select(m module.Version) (conflict module.Version, err error) {
+       dq := l.check(m, l.depth)
+       if !dq.isDisqualified() {
+               l.selected[m.Path] = m.Version
+       }
+       return dq.conflict, dq.err
+}
+
+// check determines whether m (or its transitive dependencies) would violate l's
+// maximum version limits if added to the module requirement graph.
+//
+// If depth is lazy and m itself is lazy, then the dependencies of unrestricted
+// dependencies of m will not be followed. If the lazy loading invariants hold
+// for the main module up to this point, the packages in those modules are at
+// best only imported by tests of dependencies that are themselves loaded from
+// outside modules. Although we would like to keep 'go test all' as reproducible
+// as is feasible, we don't want to retain test dependencies that are only
+// marginally relevant at best.
+func (l *versionLimiter) check(m module.Version, depth modDepth) dqState {
+       if m.Version == "none" || m == Target {
+               // version "none" has no requirements, and the dependencies of Target are
+               // tautological.
+               return dqState{}
+       }
+
+       if dq, seen := l.dqReason[m]; seen {
+               return dq
+       }
+       l.dqReason[m] = dqState{}
+
+       if max, ok := l.max[m.Path]; ok && cmpVersion(m.Version, max) > 0 {
+               return l.disqualify(m, dqState{conflict: m})
+       }
+
+       summary, err := goModSummary(m)
+       if err != nil {
+               // If we can't load the requirements, we couldn't load the go.mod file.
+               // There are a number of reasons this can happen, but this usually
+               // means an older version of the module had a missing or invalid
+               // go.mod file. For example, if example.com/mod released v2.0.0 before
+               // migrating to modules (v2.0.0+incompatible), then added a valid go.mod
+               // in v2.0.1, downgrading from v2.0.1 would cause this error.
+               //
+               // TODO(golang.org/issue/31730, golang.org/issue/30134): if the error
+               // is transient (we couldn't download go.mod), return the error from
+               // Downgrade. Currently, we can't tell what kind of error it is.
+               return l.disqualify(m, dqState{err: err})
+       }
+
+       if summary.depth == eager {
+               depth = eager
+       }
+       for _, r := range summary.require {
+               if depth == lazy {
+                       if _, restricted := l.max[r.Path]; !restricted {
+                               // r.Path is unrestricted, so we don't care at what version it is
+                               // selected. We assume that r.Path will not become a root dependency, so
+                               // since m is lazy, r's dependencies won't be followed.
+                               continue
+                       }
+               }
+
+               if dq := l.check(r, depth); dq.isDisqualified() {
+                       return l.disqualify(m, dq)
+               }
+
+               // r and its dependencies are (perhaps provisionally) ok.
+               //
+               // However, if there are cycles in the requirement graph, we may have only
+               // checked a portion of the requirement graph so far, and r (and thus m) may
+               // yet be disqualified by some path we have not yet visited. Remember this edge
+               // so that we can disqualify m and its dependents if that occurs.
+               l.requiring[r] = append(l.requiring[r], m)
+       }
+
+       return dqState{}
+}
+
+// disqualify records that m (or one of its transitive dependencies)
+// violates l's maximum version limits.
+func (l *versionLimiter) disqualify(m module.Version, dq dqState) dqState {
+       if dq := l.dqReason[m]; dq.isDisqualified() {
+               return dq
+       }
+       l.dqReason[m] = dq
+
+       for _, p := range l.requiring[m] {
+               l.disqualify(p, dqState{conflict: m})
+       }
+       // Now that we have disqualified the modules that depend on m, we can forget
+       // about them — we won't need to disqualify them again.
+       delete(l.requiring, m)
+       return dq
+}
index fd39ddd94ec62d6f21533a7ea7dff02c8eeb2ecb..886ad62bd90cb6a64113732336d9affe117a98ef 100644 (file)
@@ -46,7 +46,7 @@ marking the root of the main (current) module.
 The go.mod file format is described in detail at
 https://golang.org/ref/mod#go-mod-file.
 
-To create a new go.mod file, use 'go help init'. For details see
+To create a new go.mod file, use 'go mod init'. For details see
 'go help mod init' or https://golang.org/ref/mod#go-mod-init.
 
 To add missing module requirements or remove unneeded requirements,
index 995641c9f1f36d8a65192f6448e0c6f18c502fe4..d2bbe5cbe0b1eae58ac5a041792d0b4d0e8a3c85 100644 (file)
@@ -12,6 +12,7 @@ import (
        "internal/goroot"
        "io/fs"
        "os"
+       pathpkg "path"
        "path/filepath"
        "sort"
        "strings"
@@ -60,7 +61,7 @@ func (e *ImportMissingError) Error() string {
 
                if e.replaced.Path != "" {
                        suggestArg := e.replaced.Path
-                       if !modfetch.IsZeroPseudoVersion(e.replaced.Version) {
+                       if !module.IsZeroPseudoVersion(e.replaced.Version) {
                                suggestArg = e.replaced.String()
                        }
                        return fmt.Sprintf("module %s provides package %s and is replaced but not required; to add it:\n\tgo get %s", e.replaced.Path, e.Path, suggestArg)
@@ -127,6 +128,23 @@ func (e *AmbiguousImportError) Error() string {
        return buf.String()
 }
 
+// A DirectImportFromImplicitDependencyError indicates a package directly
+// imported by a package or test in the main module that is satisfied by a
+// dependency that is not explicit in the main module's go.mod file.
+type DirectImportFromImplicitDependencyError struct {
+       ImporterPath string
+       ImportedPath string
+       Module       module.Version
+}
+
+func (e *DirectImportFromImplicitDependencyError) Error() string {
+       return fmt.Sprintf("package %s imports %s from implicitly required module; to add missing requirements, run:\n\tgo get %s@%s", e.ImporterPath, e.ImportedPath, e.Module.Path, e.Module.Version)
+}
+
+func (e *DirectImportFromImplicitDependencyError) ImportPath() string {
+       return e.ImporterPath
+}
+
 // ImportMissingSumError is reported in readonly mode when we need to check
 // if a module contains a package, but we don't have a sum for its .zip file.
 // We might need sums for multiple modules to verify the package is unique.
@@ -160,11 +178,13 @@ func (e *ImportMissingSumError) Error() string {
                // Importing package is unknown, or the missing package was named on the
                // command line. Recommend 'go mod download' for the modules that could
                // provide the package, since that shouldn't change go.mod.
-               args := make([]string, len(e.mods))
-               for i, mod := range e.mods {
-                       args[i] = mod.Path
+               if len(e.mods) > 0 {
+                       args := make([]string, len(e.mods))
+                       for i, mod := range e.mods {
+                               args[i] = mod.Path
+                       }
+                       hint = fmt.Sprintf("; to add:\n\tgo mod download %s", strings.Join(args, " "))
                }
-               hint = fmt.Sprintf("; to add:\n\tgo mod download %s", strings.Join(args, " "))
        } else {
                // Importing package is known (common case). Recommend 'go get' on the
                // current version of the importing package.
@@ -202,28 +222,31 @@ func (e *invalidImportError) Unwrap() error {
        return e.err
 }
 
-// importFromBuildList finds the module and directory in the build list
-// containing the package with the given import path. The answer must be unique:
-// importFromBuildList returns an error if multiple modules attempt to provide
-// the same package.
+// importFromModules finds the module and directory in the dependency graph of
+// rs containing the package with the given import path. If mg is nil,
+// importFromModules attempts to locate the module using only the main module
+// and the roots of rs before it loads the full graph.
 //
-// importFromBuildList can return a module with an empty m.Path, for packages in
+// The answer must be unique: importFromModules returns an error if multiple
+// modules are observed to provide the same package.
+//
+// importFromModules can return a module with an empty m.Path, for packages in
 // the standard library.
 //
-// importFromBuildList can return an empty directory string, for fake packages
+// importFromModules can return an empty directory string, for fake packages
 // like "C" and "unsafe".
 //
-// If the package cannot be found in buildList,
-// importFromBuildList returns an *ImportMissingError.
-func importFromBuildList(ctx context.Context, path string, buildList []module.Version) (m module.Version, dir string, err error) {
+// If the package is not present in any module selected from the requirement
+// graph, importFromModules returns an *ImportMissingError.
+func importFromModules(ctx context.Context, path string, rs *Requirements, mg *ModuleGraph) (m module.Version, dir string, err error) {
        if strings.Contains(path, "@") {
                return module.Version{}, "", fmt.Errorf("import path should not have @version")
        }
        if build.IsLocalImport(path) {
                return module.Version{}, "", fmt.Errorf("relative import not supported")
        }
-       if path == "C" || path == "unsafe" {
-               // There's no directory for import "C" or import "unsafe".
+       if path == "C" {
+               // There's no directory for import "C".
                return module.Version{}, "", nil
        }
        // Before any further lookup, check that the path is valid.
@@ -269,58 +292,114 @@ func importFromBuildList(ctx context.Context, path string, buildList []module.Ve
        // Check each module on the build list.
        var dirs []string
        var mods []module.Version
-       var sumErrMods []module.Version
-       for _, m := range buildList {
-               if !maybeInModule(path, m.Path) {
-                       // Avoid possibly downloading irrelevant modules.
-                       continue
-               }
-               needSum := true
-               root, isLocal, err := fetch(ctx, m, needSum)
-               if err != nil {
-                       if sumErr := (*sumMissingError)(nil); errors.As(err, &sumErr) {
-                               // We are missing a sum needed to fetch a module in the build list.
-                               // We can't verify that the package is unique, and we may not find
-                               // the package at all. Keep checking other modules to decide which
-                               // error to report. Multiple sums may be missing if we need to look in
-                               // multiple nested modules to resolve the import.
-                               sumErrMods = append(sumErrMods, m)
+
+       // Iterate over possible modules for the path, not all selected modules.
+       // Iterating over selected modules would make the overall loading time
+       // O(M × P) for M modules providing P imported packages, whereas iterating
+       // over path prefixes is only O(P × k) with maximum path depth k. For
+       // large projects both M and P may be very large (note that M ≤ P), but k
+       // will tend to remain smallish (if for no other reason than filesystem
+       // path limitations).
+       //
+       // We perform this iteration either one or two times. If mg is initially nil,
+       // then we first attempt to load the package using only the main module and
+       // its root requirements. If that does not identify the package, or if mg is
+       // already non-nil, then we attempt to load the package using the full
+       // requirements in mg.
+       for {
+               var sumErrMods []module.Version
+               for prefix := path; prefix != "."; prefix = pathpkg.Dir(prefix) {
+                       var (
+                               v  string
+                               ok bool
+                       )
+                       if mg == nil {
+                               v, ok = rs.rootSelected(prefix)
+                       } else {
+                               v, ok = mg.Selected(prefix), true
+                       }
+                       if !ok || v == "none" {
                                continue
                        }
-                       // Report fetch error.
-                       // Note that we don't know for sure this module is necessary,
-                       // but it certainly _could_ provide the package, and even if we
-                       // continue the loop and find the package in some other module,
-                       // we need to look at this module to make sure the import is
-                       // not ambiguous.
-                       return module.Version{}, "", err
+                       m := module.Version{Path: prefix, Version: v}
+
+                       needSum := true
+                       root, isLocal, err := fetch(ctx, m, needSum)
+                       if err != nil {
+                               if sumErr := (*sumMissingError)(nil); errors.As(err, &sumErr) {
+                                       // We are missing a sum needed to fetch a module in the build list.
+                                       // We can't verify that the package is unique, and we may not find
+                                       // the package at all. Keep checking other modules to decide which
+                                       // error to report. Multiple sums may be missing if we need to look in
+                                       // multiple nested modules to resolve the import; we'll report them all.
+                                       sumErrMods = append(sumErrMods, m)
+                                       continue
+                               }
+                               // Report fetch error.
+                               // Note that we don't know for sure this module is necessary,
+                               // but it certainly _could_ provide the package, and even if we
+                               // continue the loop and find the package in some other module,
+                               // we need to look at this module to make sure the import is
+                               // not ambiguous.
+                               return module.Version{}, "", err
+                       }
+                       if dir, ok, err := dirInModule(path, m.Path, root, isLocal); err != nil {
+                               return module.Version{}, "", err
+                       } else if ok {
+                               mods = append(mods, m)
+                               dirs = append(dirs, dir)
+                       }
                }
-               if dir, ok, err := dirInModule(path, m.Path, root, isLocal); err != nil {
-                       return module.Version{}, "", err
-               } else if ok {
-                       mods = append(mods, m)
-                       dirs = append(dirs, dir)
+
+               if len(mods) > 1 {
+                       // We produce the list of directories from longest to shortest candidate
+                       // module path, but the AmbiguousImportError should report them from
+                       // shortest to longest. Reverse them now.
+                       for i := 0; i < len(mods)/2; i++ {
+                               j := len(mods) - 1 - i
+                               mods[i], mods[j] = mods[j], mods[i]
+                               dirs[i], dirs[j] = dirs[j], dirs[i]
+                       }
+                       return module.Version{}, "", &AmbiguousImportError{importPath: path, Dirs: dirs, Modules: mods}
                }
-       }
-       if len(mods) > 1 {
-               return module.Version{}, "", &AmbiguousImportError{importPath: path, Dirs: dirs, Modules: mods}
-       }
-       if len(sumErrMods) > 0 {
-               return module.Version{}, "", &ImportMissingSumError{
-                       importPath: path,
-                       mods:       sumErrMods,
-                       found:      len(mods) > 0,
+
+               if len(sumErrMods) > 0 {
+                       for i := 0; i < len(sumErrMods)/2; i++ {
+                               j := len(sumErrMods) - 1 - i
+                               sumErrMods[i], sumErrMods[j] = sumErrMods[j], sumErrMods[i]
+                       }
+                       return module.Version{}, "", &ImportMissingSumError{
+                               importPath: path,
+                               mods:       sumErrMods,
+                               found:      len(mods) > 0,
+                       }
                }
-       }
-       if len(mods) == 1 {
-               return mods[0], dirs[0], nil
-       }
 
-       var queryErr error
-       if !HasModRoot() {
-               queryErr = ErrNoModRoot
+               if len(mods) == 1 {
+                       return mods[0], dirs[0], nil
+               }
+
+               if mg != nil {
+                       // We checked the full module graph and still didn't find the
+                       // requested package.
+                       var queryErr error
+                       if !HasModRoot() {
+                               queryErr = ErrNoModRoot
+                       }
+                       return module.Version{}, "", &ImportMissingError{Path: path, QueryErr: queryErr, isStd: pathIsStd}
+               }
+
+               // So far we've checked the root dependencies.
+               // Load the full module graph and try again.
+               mg, err = rs.Graph(ctx)
+               if err != nil {
+                       // We might be missing one or more transitive (implicit) dependencies from
+                       // the module graph, so we can't return an ImportMissingError here — one
+                       // of the missing modules might actually contain the package in question,
+                       // in which case we shouldn't go looking for it in some new dependency.
+                       return module.Version{}, "", err
+               }
        }
-       return module.Version{}, "", &ImportMissingError{Path: path, QueryErr: queryErr, isStd: pathIsStd}
 }
 
 // queryImport attempts to locate a module that can be added to the current
@@ -328,7 +407,7 @@ func importFromBuildList(ctx context.Context, path string, buildList []module.Ve
 //
 // Unlike QueryPattern, queryImport prefers to add a replaced version of a
 // module *before* checking the proxies for a version to add.
-func queryImport(ctx context.Context, path string) (module.Version, error) {
+func queryImport(ctx context.Context, path string, rs *Requirements) (module.Version, error) {
        // To avoid spurious remote fetches, try the latest replacement for each
        // module (golang.org/issue/26241).
        if index != nil {
@@ -344,11 +423,20 @@ func queryImport(ctx context.Context, path string) (module.Version, error) {
                                // used from within some other module, the user will be able to upgrade
                                // the requirement to any real version they choose.
                                if _, pathMajor, ok := module.SplitPathVersion(mp); ok && len(pathMajor) > 0 {
-                                       mv = modfetch.ZeroPseudoVersion(pathMajor[1:])
+                                       mv = module.ZeroPseudoVersion(pathMajor[1:])
                                } else {
-                                       mv = modfetch.ZeroPseudoVersion("v0")
+                                       mv = module.ZeroPseudoVersion("v0")
                                }
                        }
+                       mg, err := rs.Graph(ctx)
+                       if err != nil {
+                               return module.Version{}, err
+                       }
+                       if cmpVersion(mg.Selected(mp), mv) >= 0 {
+                               // We can't resolve the import by adding mp@mv to the module graph,
+                               // because the selected version of mp is already at least mv.
+                               continue
+                       }
                        mods = append(mods, module.Version{Path: mp, Version: mv})
                }
 
@@ -417,7 +505,12 @@ func queryImport(ctx context.Context, path string) (module.Version, error) {
        // and return m, dir, ImpportMissingError.
        fmt.Fprintf(os.Stderr, "go: finding module for package %s\n", path)
 
-       candidates, err := QueryPackages(ctx, path, "latest", Selected, CheckAllowed)
+       mg, err := rs.Graph(ctx)
+       if err != nil {
+               return module.Version{}, err
+       }
+
+       candidates, err := QueryPackages(ctx, path, "latest", mg.Selected, CheckAllowed)
        if err != nil {
                if errors.Is(err, fs.ErrNotExist) {
                        // Return "cannot find module providing package […]" instead of whatever
@@ -430,28 +523,21 @@ func queryImport(ctx context.Context, path string) (module.Version, error) {
 
        candidate0MissingVersion := ""
        for i, c := range candidates {
-               cm := c.Mod
-               canAdd := true
-               for _, bm := range buildList {
-                       if bm.Path == cm.Path && semver.Compare(bm.Version, cm.Version) > 0 {
-                               // QueryPattern proposed that we add module cm to provide the package,
-                               // but we already depend on a newer version of that module (and we don't
-                               // have the package).
-                               //
-                               // This typically happens when a package is present at the "@latest"
-                               // version (e.g., v1.0.0) of a module, but we have a newer version
-                               // of the same module in the build list (e.g., v1.0.1-beta), and
-                               // the package is not present there.
-                               canAdd = false
-                               if i == 0 {
-                                       candidate0MissingVersion = bm.Version
-                               }
-                               break
+               if v := mg.Selected(c.Mod.Path); semver.Compare(v, c.Mod.Version) > 0 {
+                       // QueryPattern proposed that we add module c.Mod to provide the package,
+                       // but we already depend on a newer version of that module (and that
+                       // version doesn't have the package).
+                       //
+                       // This typically happens when a package is present at the "@latest"
+                       // version (e.g., v1.0.0) of a module, but we have a newer version
+                       // of the same module in the build list (e.g., v1.0.1-beta), and
+                       // the package is not present there.
+                       if i == 0 {
+                               candidate0MissingVersion = v
                        }
+                       continue
                }
-               if canAdd {
-                       return cm, nil
-               }
+               return c.Mod, nil
        }
        return module.Version{}, &ImportMissingError{
                Path:              path,
index 9420dc56460d1060b7723d6763c66e816956408b..98145887e9dcc5c6b18aa071f08c27ce7c4681ca 100644 (file)
@@ -69,11 +69,12 @@ func TestQueryImport(t *testing.T) {
        RootMode = NoRoot
 
        ctx := context.Background()
+       rs := newRequirements(eager, nil, nil)
 
        for _, tt := range importTests {
                t.Run(strings.ReplaceAll(tt.path, "/", "_"), func(t *testing.T) {
                        // Note that there is no build list, so Import should always fail.
-                       m, err := queryImport(ctx, tt.path)
+                       m, err := queryImport(ctx, tt.path, rs)
 
                        if tt.err == "" {
                                if err != nil {
index 8ec1c8681a9c8f2376c16c2e070dc533cee0ba49..a8cbd9fe16d1862d673de85f4f9e301461ab07d3 100644 (file)
@@ -15,10 +15,8 @@ import (
        "os"
        "path"
        "path/filepath"
-       "sort"
        "strconv"
        "strings"
-       "sync"
 
        "cmd/go/internal/base"
        "cmd/go/internal/cfg"
@@ -26,20 +24,37 @@ import (
        "cmd/go/internal/lockedfile"
        "cmd/go/internal/modconv"
        "cmd/go/internal/modfetch"
-       "cmd/go/internal/mvs"
        "cmd/go/internal/search"
-       "cmd/go/internal/str"
 
        "golang.org/x/mod/modfile"
        "golang.org/x/mod/module"
        "golang.org/x/mod/semver"
 )
 
+// Variables set by other packages.
+//
+// TODO(#40775): See if these can be plumbed as explicit parameters.
+var (
+       // RootMode determines whether a module root is needed.
+       RootMode Root
+
+       // ForceUseModules may be set to force modules to be enabled when
+       // GO111MODULE=auto or to report an error when GO111MODULE=off.
+       ForceUseModules bool
+
+       allowMissingModuleImports bool
+)
+
+// Variables set in Init.
 var (
        initialized bool
+       modRoot     string
+       gopath      string
+)
 
-       modRoot string
-       Target  module.Version
+// Variables set in initTarget (during {Load,Create}ModFile).
+var (
+       Target module.Version
 
        // targetPrefix is the path prefix for packages in Target, without a trailing
        // slash. For most modules, targetPrefix is just Target.Path, but the
@@ -49,17 +64,6 @@ var (
        // targetInGorootSrc caches whether modRoot is within GOROOT/src.
        // The "std" module is special within GOROOT/src, but not otherwise.
        targetInGorootSrc bool
-
-       gopath string
-
-       // RootMode determines whether a module root is needed.
-       RootMode Root
-
-       // ForceUseModules may be set to force modules to be enabled when
-       // GO111MODULE=auto or to report an error when GO111MODULE=off.
-       ForceUseModules bool
-
-       allowMissingModuleImports bool
 )
 
 type Root int
@@ -67,7 +71,7 @@ type Root int
 const (
        // AutoRoot is the default for most commands. modload.Init will look for
        // a go.mod file in the current directory or any parent. If none is found,
-       // modules may be disabled (GO111MODULE=on) or commands may run in a
+       // modules may be disabled (GO111MODULE=auto) or commands may run in a
        // limited module mode.
        AutoRoot Root = iota
 
@@ -82,7 +86,7 @@ const (
 
 // ModFile returns the parsed go.mod file.
 //
-// Note that after calling LoadPackages or LoadAllModules,
+// Note that after calling LoadPackages or LoadModGraph,
 // the require statements in the modfile.File are no longer
 // the source of truth and will be ignored: edits made directly
 // will be lost at the next call to WriteGoMod.
@@ -131,7 +135,7 @@ func Init() {
                return
        }
 
-       if err := fsys.Init(base.Cwd); err != nil {
+       if err := fsys.Init(base.Cwd()); err != nil {
                base.Fatalf("go: %v", err)
        }
 
@@ -159,7 +163,11 @@ func Init() {
        // assume they know what they are doing and don't step on it.
        // But default to turning off ControlMaster.
        if os.Getenv("GIT_SSH") == "" && os.Getenv("GIT_SSH_COMMAND") == "" {
-               os.Setenv("GIT_SSH_COMMAND", "ssh -o ControlMaster=no")
+               os.Setenv("GIT_SSH_COMMAND", "ssh -o ControlMaster=no -o BatchMode=yes")
+       }
+
+       if os.Getenv("GCM_INTERACTIVE") == "" {
+               os.Setenv("GCM_INTERACTIVE", "never")
        }
 
        if modRoot != "" {
@@ -171,7 +179,7 @@ func Init() {
                }
                modRoot = ""
        } else {
-               modRoot = findModuleRoot(base.Cwd)
+               modRoot = findModuleRoot(base.Cwd())
                if modRoot == "" {
                        if cfg.ModFile != "" {
                                base.Fatalf("go: cannot find main module, but -modfile was set.\n\t-modfile cannot be used to set the module root directory.")
@@ -268,7 +276,7 @@ func WillBeEnabled() bool {
                return false
        }
 
-       if modRoot := findModuleRoot(base.Cwd); modRoot == "" {
+       if modRoot := findModuleRoot(base.Cwd()); modRoot == "" {
                // GO111MODULE is 'auto', and we can't find a module root.
                // Stay in GOPATH mode.
                return false
@@ -327,8 +335,8 @@ func die() {
        if cfg.Getenv("GO111MODULE") == "off" {
                base.Fatalf("go: modules disabled by GO111MODULE=off; see 'go help modules'")
        }
-       if dir, name := findAltConfig(base.Cwd); dir != "" {
-               rel, err := filepath.Rel(base.Cwd, dir)
+       if dir, name := findAltConfig(base.Cwd()); dir != "" {
+               rel, err := filepath.Rel(base.Cwd(), dir)
                if err != nil {
                        rel = dir
                }
@@ -343,30 +351,77 @@ func die() {
 
 var ErrNoModRoot = errors.New("go.mod file not found in current directory or any parent directory; see 'go help modules'")
 
+type goModDirtyError struct{}
+
+func (goModDirtyError) Error() string {
+       if cfg.BuildModExplicit {
+               return fmt.Sprintf("updates to go.mod needed, disabled by -mod=%v; to update it:\n\tgo mod tidy", cfg.BuildMod)
+       }
+       if cfg.BuildModReason != "" {
+               return fmt.Sprintf("updates to go.mod needed, disabled by -mod=%s\n\t(%s)\n\tto update it:\n\tgo mod tidy", cfg.BuildMod, cfg.BuildModReason)
+       }
+       return "updates to go.mod needed; to update it:\n\tgo mod tidy"
+}
+
+var errGoModDirty error = goModDirtyError{}
+
 // LoadModFile sets Target and, if there is a main module, parses the initial
 // build list from its go.mod file.
 //
 // LoadModFile may make changes in memory, like adding a go directive and
-// ensuring requirements are consistent. WriteGoMod should be called later to
-// write changes out to disk or report errors in readonly mode.
+// ensuring requirements are consistent, and will write those changes back to
+// disk unless DisallowWriteGoMod is in effect.
 //
 // As a side-effect, LoadModFile may change cfg.BuildMod to "vendor" if
 // -mod wasn't set explicitly and automatic vendoring should be enabled.
-func LoadModFile(ctx context.Context) {
-       if len(buildList) > 0 {
-               return
+//
+// If LoadModFile or CreateModFile has already been called, LoadModFile returns
+// the existing in-memory requirements (rather than re-reading them from disk).
+//
+// LoadModFile checks the roots of the module graph for consistency with each
+// other, but unlike LoadModGraph does not load the full module graph or check
+// it for global consistency. Most callers outside of the modload package should
+// use LoadModGraph instead.
+func LoadModFile(ctx context.Context) *Requirements {
+       rs, needCommit := loadModFile(ctx)
+       if needCommit {
+               commitRequirements(ctx, modFileGoVersion(), rs)
+       }
+       return rs
+}
+
+// loadModFile is like LoadModFile, but does not implicitly commit the
+// requirements back to disk after fixing inconsistencies.
+//
+// If needCommit is true, after the caller makes any other needed changes to the
+// returned requirements they should invoke commitRequirements to fix any
+// inconsistencies that may be present in the on-disk go.mod file.
+func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) {
+       if requirements != nil {
+               return requirements, false
        }
 
        Init()
        if modRoot == "" {
                Target = module.Version{Path: "command-line-arguments"}
                targetPrefix = "command-line-arguments"
-               buildList = []module.Version{Target}
-               return
+               goVersion := LatestGoVersion()
+               rawGoVersion.Store(Target, goVersion)
+               requirements = newRequirements(modDepthFromGoVersion(goVersion), nil, nil)
+               return requirements, false
        }
 
        gomod := ModFilePath()
-       data, err := lockedfile.Read(gomod)
+       var data []byte
+       var err error
+       if gomodActual, ok := fsys.OverlayPath(gomod); ok {
+               // Don't lock go.mod if it's part of the overlay.
+               // On Plan 9, locking requires chmod, and we don't want to modify any file
+               // in the overlay. See #44700.
+               data, err = os.ReadFile(gomodActual)
+       } else {
+               data, err = lockedfile.Read(gomodActual)
+       }
        if err != nil {
                base.Fatalf("go: %v", err)
        }
@@ -377,24 +432,53 @@ func LoadModFile(ctx context.Context) {
                // Errors returned by modfile.Parse begin with file:line.
                base.Fatalf("go: errors parsing go.mod:\n%s\n", err)
        }
-       modFile = f
-       index = indexModFile(data, f, fixed)
-
        if f.Module == nil {
                // No module declaration. Must add module path.
                base.Fatalf("go: no module declaration in go.mod. To specify the module path:\n\tgo mod edit -module=example.com/mod")
        }
 
-       if err := checkModulePathLax(f.Module.Mod.Path); err != nil {
+       modFile = f
+       initTarget(f.Module.Mod)
+       index = indexModFile(data, f, fixed)
+
+       if err := module.CheckImportPath(f.Module.Mod.Path); err != nil {
+               if pathErr, ok := err.(*module.InvalidPathError); ok {
+                       pathErr.Kind = "module"
+               }
                base.Fatalf("go: %v", err)
        }
 
        setDefaultBuildMod() // possibly enable automatic vendoring
-       modFileToBuildList()
+       rs = requirementsFromModFile(ctx)
+
        if cfg.BuildMod == "vendor" {
                readVendorList()
                checkVendorConsistency()
+               rs.initVendor(vendorList)
+       }
+       if index.goVersionV == "" {
+               // TODO(#45551): Do something more principled instead of checking
+               // cfg.CmdName directly here.
+               if cfg.BuildMod == "mod" && cfg.CmdName != "mod graph" && cfg.CmdName != "mod why" {
+                       addGoStmt(LatestGoVersion())
+                       if go117EnableLazyLoading {
+                               // We need to add a 'go' version to the go.mod file, but we must assume
+                               // that its existing contents match something between Go 1.11 and 1.16.
+                               // Go 1.11 through 1.16 have eager requirements, but the latest Go
+                               // version uses lazy requirements instead — so we need to cnvert the
+                               // requirements to be lazy.
+                               rs, err = convertDepth(ctx, rs, lazy)
+                               if err != nil {
+                                       base.Fatalf("go: %v", err)
+                               }
+                       }
+               } else {
+                       rawGoVersion.Store(Target, modFileGoVersion())
+               }
        }
+
+       requirements = rs
+       return requirements, true
 }
 
 // CreateModFile initializes a new module by creating a go.mod file.
@@ -407,7 +491,7 @@ func LoadModFile(ctx context.Context) {
 // exactly the same as in the legacy configuration (for example, we can't get
 // packages at multiple versions from the same module).
 func CreateModFile(ctx context.Context, modPath string) {
-       modRoot = base.Cwd
+       modRoot = base.Cwd()
        Init()
        modFilePath := ModFilePath()
        if _, err := fsys.Stat(modFilePath); err == nil {
@@ -420,14 +504,23 @@ func CreateModFile(ctx context.Context, modPath string) {
                if err != nil {
                        base.Fatalf("go: %v", err)
                }
-       } else if err := checkModulePathLax(modPath); err != nil {
+       } else if err := module.CheckImportPath(modPath); err != nil {
+               if pathErr, ok := err.(*module.InvalidPathError); ok {
+                       pathErr.Kind = "module"
+                       // Same as build.IsLocalPath()
+                       if pathErr.Path == "." || pathErr.Path == ".." ||
+                               strings.HasPrefix(pathErr.Path, "./") || strings.HasPrefix(pathErr.Path, "../") {
+                               pathErr.Err = errors.New("is a local import path")
+                       }
+               }
                base.Fatalf("go: %v", err)
        }
 
        fmt.Fprintf(os.Stderr, "go: creating new go.mod: module %s\n", modPath)
        modFile = new(modfile.File)
        modFile.AddModuleStmt(modPath)
-       addGoStmt() // Add the go directive before converted module requirements.
+       initTarget(modFile.Module.Mod)
+       addGoStmt(LatestGoVersion()) // Add the go directive before converted module requirements.
 
        convertedFrom, err := convertLegacyConfig(modPath)
        if convertedFrom != "" {
@@ -437,8 +530,7 @@ func CreateModFile(ctx context.Context, modPath string) {
                base.Fatalf("go: %v", err)
        }
 
-       modFileToBuildList()
-       WriteGoMod()
+       commitRequirements(ctx, modFileGoVersion(), requirementsFromModFile(ctx))
 
        // Suggest running 'go mod tidy' unless the project is empty. Even if we
        // imported all the correct requirements above, we're probably missing
@@ -464,49 +556,6 @@ func CreateModFile(ctx context.Context, modPath string) {
        }
 }
 
-// checkModulePathLax checks that the path meets some minimum requirements
-// to avoid confusing users or the module cache. The requirements are weaker
-// than those of module.CheckPath to allow room for weakening module path
-// requirements in the future, but strong enough to help users avoid significant
-// problems.
-func checkModulePathLax(p string) error {
-       // TODO(matloob): Replace calls of this function in this CL with calls
-       // to module.CheckImportPath once it's been laxened, if it becomes laxened.
-       // See golang.org/issue/29101 for a discussion about whether to make CheckImportPath
-       // more lax or more strict.
-
-       errorf := func(format string, args ...interface{}) error {
-               return fmt.Errorf("invalid module path %q: %s", p, fmt.Sprintf(format, args...))
-       }
-
-       // Disallow shell characters " ' * < > ? ` | to avoid triggering bugs
-       // with file systems and subcommands. Disallow file path separators : and \
-       // because path separators other than / will confuse the module cache.
-       // See fileNameOK in golang.org/x/mod/module/module.go.
-       shellChars := "`" + `\"'*<>?|`
-       fsChars := `\:`
-       if i := strings.IndexAny(p, shellChars); i >= 0 {
-               return errorf("contains disallowed shell character %q", p[i])
-       }
-       if i := strings.IndexAny(p, fsChars); i >= 0 {
-               return errorf("contains disallowed path separator character %q", p[i])
-       }
-
-       // Ensure path.IsAbs and build.IsLocalImport are false, and that the path is
-       // invariant under path.Clean, also to avoid confusing the module cache.
-       if path.IsAbs(p) {
-               return errorf("is an absolute path")
-       }
-       if build.IsLocalImport(p) {
-               return errorf("is a local import path")
-       }
-       if path.Clean(p) != p {
-               return errorf("is not clean")
-       }
-
-       return nil
-}
-
 // fixVersion returns a modfile.VersionFixer implemented using the Query function.
 //
 // It resolves commit hashes and branch names to versions,
@@ -559,22 +608,43 @@ func fixVersion(ctx context.Context, fixed *bool) modfile.VersionFixer {
 // when there is no module root. Normally, this is forbidden because it's slow
 // and there's no way to make the result reproducible, but some commands
 // like 'go get' are expected to do this.
+//
+// This function affects the default cfg.BuildMod when outside of a module,
+// so it can only be called prior to Init.
 func AllowMissingModuleImports() {
+       if initialized {
+               panic("AllowMissingModuleImports after Init")
+       }
        allowMissingModuleImports = true
 }
 
-// modFileToBuildList initializes buildList from the modFile.
-func modFileToBuildList() {
-       Target = modFile.Module.Mod
-       targetPrefix = Target.Path
-       if rel := search.InDir(base.Cwd, cfg.GOROOTsrc); rel != "" {
+// initTarget sets Target and associated variables according to modFile,
+func initTarget(m module.Version) {
+       Target = m
+       targetPrefix = m.Path
+
+       if rel := search.InDir(base.Cwd(), cfg.GOROOTsrc); rel != "" {
                targetInGorootSrc = true
-               if Target.Path == "std" {
+               if m.Path == "std" {
+                       // The "std" module in GOROOT/src is the Go standard library. Unlike other
+                       // modules, the packages in the "std" module have no import-path prefix.
+                       //
+                       // Modules named "std" outside of GOROOT/src do not receive this special
+                       // treatment, so it is possible to run 'go test .' in other GOROOTs to
+                       // test individual packages using a combination of the modified package
+                       // and the ordinary standard library.
+                       // (See https://golang.org/issue/30756.)
                        targetPrefix = ""
                }
        }
+}
 
-       list := []module.Version{Target}
+// requirementsFromModFile returns the set of non-excluded requirements from
+// the global modFile.
+func requirementsFromModFile(ctx context.Context) *Requirements {
+       roots := make([]module.Version, 0, len(modFile.Require))
+       mPathCount := map[string]int{Target.Path: 1}
+       direct := map[string]bool{}
        for _, r := range modFile.Require {
                if index != nil && index.exclude[r.Mod] {
                        if cfg.BuildMod == "mod" {
@@ -582,11 +652,33 @@ func modFileToBuildList() {
                        } else {
                                fmt.Fprintf(os.Stderr, "go: ignoring requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version)
                        }
-               } else {
-                       list = append(list, r.Mod)
+                       continue
+               }
+
+               roots = append(roots, r.Mod)
+               mPathCount[r.Mod.Path]++
+               if !r.Indirect {
+                       direct[r.Mod.Path] = true
+               }
+       }
+       module.Sort(roots)
+       rs := newRequirements(modDepthFromGoVersion(modFileGoVersion()), roots, direct)
+
+       // If any module path appears more than once in the roots, we know that the
+       // go.mod file needs to be updated even though we have not yet loaded any
+       // transitive dependencies.
+       for _, n := range mPathCount {
+               if n > 1 {
+                       var err error
+                       rs, err = updateRoots(ctx, rs.direct, rs, nil, nil, false)
+                       if err != nil {
+                               base.Fatalf("go: %v", err)
+                       }
+                       break
                }
        }
-       buildList = list
+
+       return rs
 }
 
 // setDefaultBuildMod sets a default value for cfg.BuildMod if the -mod flag
@@ -605,7 +697,11 @@ func setDefaultBuildMod() {
                return
        }
        if modRoot == "" {
-               cfg.BuildMod = "readonly"
+               if allowMissingModuleImports {
+                       cfg.BuildMod = "mod"
+               } else {
+                       cfg.BuildMod = "readonly"
+               }
                return
        }
 
@@ -634,6 +730,17 @@ func setDefaultBuildMod() {
 // convertLegacyConfig imports module requirements from a legacy vendoring
 // configuration file, if one is present.
 func convertLegacyConfig(modPath string) (from string, err error) {
+       noneSelected := func(path string) (version string) { return "none" }
+       queryPackage := func(path, rev string) (module.Version, error) {
+               pkgMods, modOnly, err := QueryPattern(context.Background(), path, rev, noneSelected, nil)
+               if err != nil {
+                       return module.Version{}, err
+               }
+               if len(pkgMods) > 0 {
+                       return pkgMods[0].Mod, nil
+               }
+               return modOnly.Mod, nil
+       }
        for _, name := range altConfigs {
                cfg := filepath.Join(modRoot, name)
                data, err := os.ReadFile(cfg)
@@ -643,27 +750,57 @@ func convertLegacyConfig(modPath string) (from string, err error) {
                                return "", nil
                        }
                        cfg = filepath.ToSlash(cfg)
-                       err := modconv.ConvertLegacyConfig(modFile, cfg, data)
+                       err := modconv.ConvertLegacyConfig(modFile, cfg, data, queryPackage)
                        return name, err
                }
        }
        return "", nil
 }
 
-// addGoStmt adds a go directive to the go.mod file if it does not already include one.
-// The 'go' version added, if any, is the latest version supported by this toolchain.
-func addGoStmt() {
+// addGoStmt adds a go directive to the go.mod file if it does not already
+// include one. The 'go' version added, if any, is the latest version supported
+// by this toolchain.
+func addGoStmt(v string) {
        if modFile.Go != nil && modFile.Go.Version != "" {
                return
        }
+       if err := modFile.AddGoStmt(v); err != nil {
+               base.Fatalf("go: internal error: %v", err)
+       }
+       rawGoVersion.Store(Target, v)
+}
+
+// LatestGoVersion returns the latest version of the Go language supported by
+// this toolchain, like "1.17".
+func LatestGoVersion() string {
        tags := build.Default.ReleaseTags
        version := tags[len(tags)-1]
        if !strings.HasPrefix(version, "go") || !modfile.GoVersionRE.MatchString(version[2:]) {
-               base.Fatalf("go: unrecognized default version %q", version)
+               base.Fatalf("go: internal error: unrecognized default version %q", version)
        }
-       if err := modFile.AddGoStmt(version[2:]); err != nil {
-               base.Fatalf("go: internal error: %v", err)
+       return version[2:]
+}
+
+// priorGoVersion returns the Go major release immediately preceding v,
+// or v itself if v is the first Go major release (1.0) or not a supported
+// Go version.
+func priorGoVersion(v string) string {
+       vTag := "go" + v
+       tags := build.Default.ReleaseTags
+       for i, tag := range tags {
+               if tag == vTag {
+                       if i == 0 {
+                               return v
+                       }
+
+                       version := tags[i-1]
+                       if !strings.HasPrefix(version, "go") || !modfile.GoVersionRE.MatchString(version[2:]) {
+                               base.Fatalf("go: internal error: unrecognized version %q", version)
+                       }
+                       return version[2:]
+               }
        }
+       return v
 }
 
 var altConfigs = []string{
@@ -780,14 +917,8 @@ func findModulePath(dir string) (string, error) {
                }
                if rel := search.InDir(dir, filepath.Join(gpdir, "src")); rel != "" && rel != "." {
                        path := filepath.ToSlash(rel)
-                       // TODO(matloob): replace this with module.CheckImportPath
-                       // once it's been laxened.
-                       // Only checkModulePathLax here. There are some unpublishable
-                       // module names that are compatible with checkModulePathLax
-                       // but they already work in GOPATH so don't break users
-                       // trying to do a build with modules. gorelease will alert users
-                       // publishing their modules to fix their paths.
-                       if err := checkModulePathLax(path); err != nil {
+                       // gorelease will alert users publishing their modules to fix their paths.
+                       if err := module.CheckImportPath(path); err != nil {
                                badPathErr = err
                                break
                        }
@@ -847,71 +978,51 @@ func AllowWriteGoMod() {
        allowWriteGoMod = true
 }
 
-// MinReqs returns a Reqs with minimal additional dependencies of Target,
-// as will be written to go.mod.
-func MinReqs() mvs.Reqs {
-       retain := append([]string{}, additionalExplicitRequirements...)
-       for _, m := range buildList[1:] {
-               _, explicit := index.require[m]
-               if explicit || loaded.direct[m.Path] {
-                       retain = append(retain, m.Path)
-               }
-       }
-       sort.Strings(retain)
-       str.Uniq(&retain)
-       min, err := mvs.Req(Target, retain, &mvsReqs{buildList: buildList})
-       if err != nil {
-               base.Fatalf("go: %v", err)
+// WriteGoMod writes the current build list back to go.mod.
+func WriteGoMod(ctx context.Context) {
+       if !allowWriteGoMod {
+               panic("WriteGoMod called while disallowed")
        }
-       return &mvsReqs{buildList: append([]module.Version{Target}, min...)}
+       commitRequirements(ctx, modFileGoVersion(), LoadModFile(ctx))
 }
 
-// WriteGoMod writes the current build list back to go.mod.
-func WriteGoMod() {
-       // If we're using -mod=vendor we basically ignored
-       // go.mod, so definitely don't try to write back our
-       // incomplete view of the world.
-       if !allowWriteGoMod || cfg.BuildMod == "vendor" {
+// commitRequirements writes sets the global requirements variable to rs and
+// writes its contents back to the go.mod file on disk.
+func commitRequirements(ctx context.Context, goVersion string, rs *Requirements) {
+       requirements = rs
+
+       if !allowWriteGoMod {
+               // Some package outside of modload promised to update the go.mod file later.
                return
        }
 
-       // If we aren't in a module, we don't have anywhere to write a go.mod file.
        if modRoot == "" {
+               // We aren't in a module, so we don't have anywhere to write a go.mod file.
                return
        }
 
-       if cfg.BuildMod != "readonly" {
-               addGoStmt()
+       var list []*modfile.Require
+       for _, m := range rs.rootModules {
+               list = append(list, &modfile.Require{
+                       Mod:      m,
+                       Indirect: !rs.direct[m.Path],
+               })
        }
-
-       if loaded != nil {
-               reqs := MinReqs()
-               min, err := reqs.Required(Target)
-               if err != nil {
-                       base.Fatalf("go: %v", err)
-               }
-               var list []*modfile.Require
-               for _, m := range min {
-                       list = append(list, &modfile.Require{
-                               Mod:      m,
-                               Indirect: !loaded.direct[m.Path],
-                       })
-               }
+       if goVersion != "" {
+               modFile.AddGoStmt(goVersion)
+       }
+       if semver.Compare("v"+modFileGoVersion(), separateIndirectVersionV) < 0 {
                modFile.SetRequire(list)
+       } else {
+               modFile.SetRequireSeparateIndirect(list)
        }
        modFile.Cleanup()
 
        dirty := index.modFileIsDirty(modFile)
-       if dirty && cfg.BuildMod == "readonly" {
+       if dirty && cfg.BuildMod != "mod" {
                // If we're about to fail due to -mod=readonly,
                // prefer to report a dirty go.mod over a dirty go.sum
-               if cfg.BuildModExplicit {
-                       base.Fatalf("go: updates to go.mod needed, disabled by -mod=readonly")
-               } else if cfg.BuildModReason != "" {
-                       base.Fatalf("go: updates to go.mod needed, disabled by -mod=readonly\n\t(%s)", cfg.BuildModReason)
-               } else {
-                       base.Fatalf("go: updates to go.mod needed; to update it:\n\tgo mod tidy")
-               }
+               base.Fatalf("go: %v", errGoModDirty)
        }
 
        if !dirty && cfg.CmdName != "mod tidy" {
@@ -920,7 +1031,14 @@ func WriteGoMod() {
                // Don't write go.mod, but write go.sum in case we added or trimmed sums.
                // 'go mod init' shouldn't write go.sum, since it will be incomplete.
                if cfg.CmdName != "mod init" {
-                       modfetch.WriteGoSum(keepSums(true))
+                       modfetch.WriteGoSum(keepSums(ctx, loaded, rs, addBuildListZipSums))
+               }
+               return
+       }
+       gomod := ModFilePath()
+       if _, ok := fsys.OverlayPath(gomod); ok {
+               if dirty {
+                       base.Fatalf("go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay")
                }
                return
        }
@@ -936,7 +1054,7 @@ func WriteGoMod() {
                // Update go.sum after releasing the side lock and refreshing the index.
                // 'go mod init' shouldn't write go.sum, since it will be incomplete.
                if cfg.CmdName != "mod init" {
-                       modfetch.WriteGoSum(keepSums(true))
+                       modfetch.WriteGoSum(keepSums(ctx, loaded, rs, addBuildListZipSums))
                }
        }()
 
@@ -973,100 +1091,99 @@ func WriteGoMod() {
        }
 }
 
-// keepSums returns a set of module sums to preserve in go.sum. The set
-// includes entries for all modules used to load packages (according to
-// the last load function such as LoadPackages or ImportFromFiles).
-// It also contains entries for go.mod files needed for MVS (the version
-// of these entries ends with "/go.mod").
-//
-// If keepBuildListZips is true, the set also includes sums for zip files for
-// all modules in the build list with replacements applied. 'go get' and
-// 'go mod download' may add sums to this set when adding a requirement on a
-// module without a root package or when downloading a direct or indirect
-// dependency.
-func keepSums(keepBuildListZips bool) map[module.Version]bool {
-       // Re-derive the build list using the current list of direct requirements.
-       // Keep the sum for the go.mod of each visited module version (or its
-       // replacement).
-       modkey := func(m module.Version) module.Version {
-               return module.Version{Path: m.Path, Version: m.Version + "/go.mod"}
-       }
+// keepSums returns the set of modules (and go.mod file entries) for which
+// checksums would be needed in order to reload the same set of packages
+// loaded by the most recent call to LoadPackages or ImportFromFiles,
+// including any go.mod files needed to reconstruct the MVS result,
+// in addition to the checksums for every module in keepMods.
+func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums) map[module.Version]bool {
+       // Every module in the full module graph contributes its requirements,
+       // so in order to ensure that the build list itself is reproducible,
+       // we need sums for every go.mod in the graph (regardless of whether
+       // that version is selected).
        keep := make(map[module.Version]bool)
-       var mu sync.Mutex
-       reqs := &keepSumReqs{
-               Reqs: &mvsReqs{buildList: buildList},
-               visit: func(m module.Version) {
-                       // If we build using a replacement module, keep the sum for the replacement,
-                       // since that's the code we'll actually use during a build.
-                       mu.Lock()
-                       r := Replacement(m)
-                       if r.Path == "" {
-                               keep[modkey(m)] = true
-                       } else {
-                               keep[modkey(r)] = true
-                       }
-                       mu.Unlock()
-               },
-       }
-       buildList, err := mvs.BuildList(Target, reqs)
-       if err != nil {
-               panic(fmt.Sprintf("unexpected error reloading build list: %v", err))
-       }
-
-       actualMods := make(map[string]module.Version)
-       for _, m := range buildList[1:] {
-               if r := Replacement(m); r.Path != "" {
-                       actualMods[m.Path] = r
-               } else {
-                       actualMods[m.Path] = m
-               }
-       }
 
        // Add entries for modules in the build list with paths that are prefixes of
-       // paths of loaded packages. We need to retain sums for modules needed to
-       // report ambiguous import errors. We use our re-derived build list,
-       // since the global build list may have been tidied.
-       if loaded != nil {
-               for _, pkg := range loaded.pkgs {
-                       if pkg.testOf != nil || pkg.inStd || module.CheckImportPath(pkg.path) != nil {
+       // paths of loaded packages. We need to retain sums for all of these modules —
+       // not just the modules containing the actual packages — in order to rule out
+       // ambiguous import errors the next time we load the package.
+       if ld != nil {
+               for _, pkg := range ld.pkgs {
+                       // We check pkg.mod.Path here instead of pkg.inStd because the
+                       // pseudo-package "C" is not in std, but not provided by any module (and
+                       // shouldn't force loading the whole module graph).
+                       if pkg.testOf != nil || (pkg.mod.Path == "" && pkg.err == nil) || module.CheckImportPath(pkg.path) != nil {
                                continue
                        }
+
+                       if rs.depth == lazy && pkg.mod.Path != "" {
+                               if v, ok := rs.rootSelected(pkg.mod.Path); ok && v == pkg.mod.Version {
+                                       // pkg was loaded from a root module, and because the main module is
+                                       // lazy we do not check non-root modules for conflicts for packages
+                                       // that can be found in roots. So we only need the checksums for the
+                                       // root modules that may contain pkg, not all possible modules.
+                                       for prefix := pkg.path; prefix != "."; prefix = path.Dir(prefix) {
+                                               if v, ok := rs.rootSelected(prefix); ok && v != "none" {
+                                                       m := module.Version{Path: prefix, Version: v}
+                                                       keep[resolveReplacement(m)] = true
+                                               }
+                                       }
+                                       continue
+                               }
+                       }
+
+                       mg, _ := rs.Graph(ctx)
                        for prefix := pkg.path; prefix != "."; prefix = path.Dir(prefix) {
-                               if m, ok := actualMods[prefix]; ok {
-                                       keep[m] = true
+                               if v := mg.Selected(prefix); v != "none" {
+                                       m := module.Version{Path: prefix, Version: v}
+                                       keep[resolveReplacement(m)] = true
                                }
                        }
                }
        }
 
-       // Add entries for the zip of each module in the build list.
-       // We might not need all of these (tidy does not add them), but they may be
-       // added by a specific 'go get' or 'go mod download' command to resolve
-       // missing import sum errors.
-       if keepBuildListZips {
-               for _, m := range actualMods {
-                       keep[m] = true
+       if rs.graph.Load() == nil {
+               // The module graph was not loaded, possibly because the main module is lazy
+               // or possibly because we haven't needed to load the graph yet.
+               // Save sums for the root modules (or their replacements), but don't
+               // incur the cost of loading the graph just to find and retain the sums.
+               for _, m := range rs.rootModules {
+                       r := resolveReplacement(m)
+                       keep[modkey(r)] = true
+                       if which == addBuildListZipSums {
+                               keep[r] = true
+                       }
+               }
+       } else {
+               mg, _ := rs.Graph(ctx)
+               mg.WalkBreadthFirst(func(m module.Version) {
+                       if _, ok := mg.RequiredBy(m); ok {
+                               // The requirements from m's go.mod file are present in the module graph,
+                               // so they are relevant to the MVS result regardless of whether m was
+                               // actually selected.
+                               keep[modkey(resolveReplacement(m))] = true
+                       }
+               })
+
+               if which == addBuildListZipSums {
+                       for _, m := range mg.BuildList() {
+                               keep[resolveReplacement(m)] = true
+                       }
                }
        }
 
        return keep
 }
 
-// keepSumReqs embeds another Reqs implementation. The Required method
-// calls visit for each version in the module graph.
-type keepSumReqs struct {
-       mvs.Reqs
-       visit func(module.Version)
-}
+type whichSums int8
 
-func (r *keepSumReqs) Required(m module.Version) ([]module.Version, error) {
-       r.visit(m)
-       return r.Reqs.Required(m)
-}
+const (
+       loadedZipSumsOnly = whichSums(iota)
+       addBuildListZipSums
+)
 
-func TrimGoSum() {
-       // Don't retain sums for the zip file of every module in the build list.
-       // We may not need them all to build the main module's packages.
-       keepBuildListZips := false
-       modfetch.TrimGoSum(keepSums(keepBuildListZips))
+// modKey returns the module.Version under which the checksum for m's go.mod
+// file is stored in the go.sum file.
+func modkey(m module.Version) module.Version {
+       return module.Version{Path: m.Path, Version: m.Version + "/go.mod"}
 }
index 7b1aa7fd41311b966290d1e1f28ce4e2d6ce802a..ccdeb9b1d11e8650ec420169723ba7d1aae4c2ba 100644 (file)
@@ -20,25 +20,42 @@ import (
        "golang.org/x/mod/module"
 )
 
-func ListModules(ctx context.Context, args []string, listU, listVersions, listRetracted bool) []*modinfo.ModulePublic {
-       mods := listModules(ctx, args, listVersions, listRetracted)
+type ListMode int
+
+const (
+       ListU ListMode = 1 << iota
+       ListRetracted
+       ListDeprecated
+       ListVersions
+       ListRetractedVersions
+)
+
+// ListModules returns a description of the modules matching args, if known,
+// along with any error preventing additional matches from being identified.
+//
+// The returned slice can be nonempty even if the error is non-nil.
+func ListModules(ctx context.Context, args []string, mode ListMode) ([]*modinfo.ModulePublic, error) {
+       rs, mods, err := listModules(ctx, LoadModFile(ctx), args, mode)
 
        type token struct{}
        sem := make(chan token, runtime.GOMAXPROCS(0))
-       if listU || listVersions || listRetracted {
+       if mode != 0 {
                for _, m := range mods {
                        add := func(m *modinfo.ModulePublic) {
                                sem <- token{}
                                go func() {
-                                       if listU {
+                                       if mode&ListU != 0 {
                                                addUpdate(ctx, m)
                                        }
-                                       if listVersions {
-                                               addVersions(ctx, m, listRetracted)
+                                       if mode&ListVersions != 0 {
+                                               addVersions(ctx, m, mode&ListRetractedVersions != 0)
                                        }
-                                       if listRetracted || listU {
+                                       if mode&ListRetracted != 0 {
                                                addRetraction(ctx, m)
                                        }
+                                       if mode&ListDeprecated != 0 {
+                                               addDeprecation(ctx, m)
+                                       }
                                        <-sem
                                }()
                        }
@@ -54,17 +71,18 @@ func ListModules(ctx context.Context, args []string, listU, listVersions, listRe
                sem <- token{}
        }
 
-       return mods
+       if err == nil {
+               commitRequirements(ctx, modFileGoVersion(), rs)
+       }
+       return mods, err
 }
 
-func listModules(ctx context.Context, args []string, listVersions, listRetracted bool) []*modinfo.ModulePublic {
-       LoadAllModules(ctx)
+func listModules(ctx context.Context, rs *Requirements, args []string, mode ListMode) (_ *Requirements, mods []*modinfo.ModulePublic, mgErr error) {
        if len(args) == 0 {
-               return []*modinfo.ModulePublic{moduleInfo(ctx, buildList[0], true, listRetracted)}
+               return rs, []*modinfo.ModulePublic{moduleInfo(ctx, rs, Target, mode)}, nil
        }
 
-       var mods []*modinfo.ModulePublic
-       matchedBuildList := make([]bool, len(buildList))
+       needFullGraph := false
        for _, arg := range args {
                if strings.Contains(arg, `\`) {
                        base.Fatalf("go: module paths never use backslash")
@@ -72,22 +90,62 @@ func listModules(ctx context.Context, args []string, listVersions, listRetracted
                if search.IsRelativePath(arg) {
                        base.Fatalf("go: cannot use relative path %s to specify module", arg)
                }
-               if !HasModRoot() && (arg == "all" || strings.Contains(arg, "...")) {
-                       base.Fatalf("go: cannot match %q: %v", arg, ErrNoModRoot)
+               if arg == "all" || strings.Contains(arg, "...") {
+                       needFullGraph = true
+                       if !HasModRoot() {
+                               base.Fatalf("go: cannot match %q: %v", arg, ErrNoModRoot)
+                       }
+                       continue
                }
                if i := strings.Index(arg, "@"); i >= 0 {
                        path := arg[:i]
                        vers := arg[i+1:]
+                       if vers == "upgrade" || vers == "patch" {
+                               if _, ok := rs.rootSelected(path); !ok || rs.depth == eager {
+                                       needFullGraph = true
+                                       if !HasModRoot() {
+                                               base.Fatalf("go: cannot match %q: %v", arg, ErrNoModRoot)
+                                       }
+                               }
+                       }
+                       continue
+               }
+               if _, ok := rs.rootSelected(arg); !ok || rs.depth == eager {
+                       needFullGraph = true
+                       if mode&ListVersions == 0 && !HasModRoot() {
+                               base.Fatalf("go: cannot match %q without -versions or an explicit version: %v", arg, ErrNoModRoot)
+                       }
+               }
+       }
+
+       var mg *ModuleGraph
+       if needFullGraph {
+               rs, mg, mgErr = expandGraph(ctx, rs)
+       }
+
+       matchedModule := map[module.Version]bool{}
+       for _, arg := range args {
+               if i := strings.Index(arg, "@"); i >= 0 {
+                       path := arg[:i]
+                       vers := arg[i+1:]
+
                        var current string
-                       for _, m := range buildList {
-                               if m.Path == path {
-                                       current = m.Version
-                                       break
+                       if mg == nil {
+                               current, _ = rs.rootSelected(path)
+                       } else {
+                               current = mg.Selected(path)
+                       }
+                       if current == "none" && mgErr != nil {
+                               if vers == "upgrade" || vers == "patch" {
+                                       // The module graph is incomplete, so we don't know what version we're
+                                       // actually upgrading from.
+                                       // mgErr is already set, so just skip this module.
+                                       continue
                                }
                        }
 
                        allowed := CheckAllowed
-                       if IsRevisionQuery(vers) || listRetracted {
+                       if IsRevisionQuery(vers) || mode&ListRetracted != 0 {
                                // Allow excluded and retracted versions if the user asked for a
                                // specific revision or used 'go list -retracted'.
                                allowed = nil
@@ -101,75 +159,79 @@ func listModules(ctx context.Context, args []string, listVersions, listRetracted
                                })
                                continue
                        }
-                       mod := moduleInfo(ctx, module.Version{Path: path, Version: info.Version}, false, listRetracted)
+
+                       // Indicate that m was resolved from outside of rs by passing a nil
+                       // *Requirements instead.
+                       var noRS *Requirements
+
+                       mod := moduleInfo(ctx, noRS, module.Version{Path: path, Version: info.Version}, mode)
                        mods = append(mods, mod)
                        continue
                }
 
                // Module path or pattern.
                var match func(string) bool
-               var literal bool
                if arg == "all" {
                        match = func(string) bool { return true }
                } else if strings.Contains(arg, "...") {
                        match = search.MatchPattern(arg)
                } else {
-                       match = func(p string) bool { return arg == p }
-                       literal = true
-               }
-               matched := false
-               for i, m := range buildList {
-                       if i == 0 && !HasModRoot() {
-                               // The root module doesn't actually exist: omit it.
+                       var v string
+                       if mg == nil {
+                               var ok bool
+                               v, ok = rs.rootSelected(arg)
+                               if !ok {
+                                       // We checked rootSelected(arg) in the earlier args loop, so if there
+                                       // is no such root we should have loaded a non-nil mg.
+                                       panic(fmt.Sprintf("internal error: root requirement expected but not found for %v", arg))
+                               }
+                       } else {
+                               v = mg.Selected(arg)
+                       }
+                       if v == "none" && mgErr != nil {
+                               // mgErr is already set, so just skip this module.
                                continue
                        }
+                       if v != "none" {
+                               mods = append(mods, moduleInfo(ctx, rs, module.Version{Path: arg, Version: v}, mode))
+                       } else if cfg.BuildMod == "vendor" {
+                               // In vendor mode, we can't determine whether a missing module is “a
+                               // known dependency” because the module graph is incomplete.
+                               // Give a more explicit error message.
+                               mods = append(mods, &modinfo.ModulePublic{
+                                       Path:  arg,
+                                       Error: modinfoError(arg, "", errors.New("can't resolve module using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)")),
+                               })
+                       } else if mode&ListVersions != 0 {
+                               // Don't make the user provide an explicit '@latest' when they're
+                               // explicitly asking what the available versions are. Instead, return a
+                               // module with version "none", to which we can add the requested list.
+                               mods = append(mods, &modinfo.ModulePublic{Path: arg})
+                       } else {
+                               mods = append(mods, &modinfo.ModulePublic{
+                                       Path:  arg,
+                                       Error: modinfoError(arg, "", errors.New("not a known dependency")),
+                               })
+                       }
+                       continue
+               }
+
+               matched := false
+               for _, m := range mg.BuildList() {
                        if match(m.Path) {
                                matched = true
-                               if !matchedBuildList[i] {
-                                       matchedBuildList[i] = true
-                                       mods = append(mods, moduleInfo(ctx, m, true, listRetracted))
+                               if !matchedModule[m] {
+                                       matchedModule[m] = true
+                                       mods = append(mods, moduleInfo(ctx, rs, m, mode))
                                }
                        }
                }
                if !matched {
-                       if literal {
-                               if listVersions {
-                                       // Don't make the user provide an explicit '@latest' when they're
-                                       // explicitly asking what the available versions are.
-                                       // Instead, resolve the module, even if it isn't an existing dependency.
-                                       info, err := Query(ctx, arg, "latest", "", nil)
-                                       if err == nil {
-                                               mod := moduleInfo(ctx, module.Version{Path: arg, Version: info.Version}, false, listRetracted)
-                                               mods = append(mods, mod)
-                                       } else {
-                                               mods = append(mods, &modinfo.ModulePublic{
-                                                       Path:  arg,
-                                                       Error: modinfoError(arg, "", err),
-                                               })
-                                       }
-                                       continue
-                               }
-                               if cfg.BuildMod == "vendor" {
-                                       // In vendor mode, we can't determine whether a missing module is “a
-                                       // known dependency” because the module graph is incomplete.
-                                       // Give a more explicit error message.
-                                       mods = append(mods, &modinfo.ModulePublic{
-                                               Path:  arg,
-                                               Error: modinfoError(arg, "", errors.New("can't resolve module using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)")),
-                                       })
-                               } else {
-                                       mods = append(mods, &modinfo.ModulePublic{
-                                               Path:  arg,
-                                               Error: modinfoError(arg, "", errors.New("not a known dependency")),
-                                       })
-                               }
-                       } else {
-                               fmt.Fprintf(os.Stderr, "warning: pattern %q matched no module dependencies\n", arg)
-                       }
+                       fmt.Fprintf(os.Stderr, "warning: pattern %q matched no module dependencies\n", arg)
                }
        }
 
-       return mods
+       return rs, mods, mgErr
 }
 
 // modinfoError wraps an error to create an error message in
index 154fc3c6f0afc6bba814240e3504ef0a94d290ed..bce9ad85f42e6c593724c6e05bbfb31db6b57521 100644 (file)
@@ -49,7 +49,7 @@ package modload
 // Because "go mod vendor" prunes out the tests of vendored packages, the
 // behavior of the "all" pattern with -mod=vendor in Go 1.11–1.15 is the same
 // as the "all" pattern (regardless of the -mod flag) in 1.16+.
-// The allClosesOverTests parameter to the loader indicates whether the "all"
+// The loader uses the GoVersion parameter to determine whether the "all"
 // pattern should close over tests (as in Go 1.11–1.15) or stop at only those
 // packages transitively imported by the packages and tests in the main module
 // ("all" in Go 1.16+ and "go mod vendor" in Go 1.11+).
@@ -121,19 +121,49 @@ import (
        "cmd/go/internal/str"
 
        "golang.org/x/mod/module"
+       "golang.org/x/mod/semver"
 )
 
 // loaded is the most recently-used package loader.
 // It holds details about individual packages.
+//
+// This variable should only be accessed directly in top-level exported
+// functions. All other functions that require or produce a *loader should pass
+// or return it as an explicit parameter.
 var loaded *loader
 
 // PackageOpts control the behavior of the LoadPackages function.
 type PackageOpts struct {
+       // GoVersion is the Go version to which the go.mod file should be updated
+       // after packages have been loaded.
+       //
+       // An empty GoVersion means to use the Go version already specified in the
+       // main module's go.mod file, or the latest Go version if there is no main
+       // module.
+       GoVersion string
+
        // Tags are the build tags in effect (as interpreted by the
        // cmd/go/internal/imports package).
        // If nil, treated as equivalent to imports.Tags().
        Tags map[string]bool
 
+       // Tidy, if true, requests that the build list and go.sum file be reduced to
+       // the minimial dependencies needed to reproducibly reload the requested
+       // packages.
+       Tidy bool
+
+       // TidyCompatibleVersion is the oldest Go version that must be able to
+       // reproducibly reload the requested packages.
+       //
+       // If empty, the compatible version is the Go version immediately prior to the
+       // 'go' version listed in the go.mod file.
+       TidyCompatibleVersion string
+
+       // VendorModulesInGOROOTSrc indicates that if we are within a module in
+       // GOROOT/src, packages in the module's vendor directory should be resolved as
+       // actual module dependencies (instead of standard-library packages).
+       VendorModulesInGOROOTSrc bool
+
        // ResolveMissingImports indicates that we should attempt to add module
        // dependencies as needed to resolve imports of packages that are not found.
        //
@@ -141,6 +171,11 @@ type PackageOpts struct {
        // if the flag is set to "readonly" (the default) or "vendor".
        ResolveMissingImports bool
 
+       // AssumeRootsImported indicates that the transitive dependencies of the root
+       // packages should be treated as if those roots will be imported by the main
+       // module.
+       AssumeRootsImported bool
+
        // AllowPackage, if non-nil, is called after identifying the module providing
        // each package. If AllowPackage returns a non-nil error, that error is set
        // for the package, and the imports and test of that package will not be
@@ -166,9 +201,16 @@ type PackageOpts struct {
        // an error occurs.
        AllowErrors bool
 
-       // SilenceErrors indicates that LoadPackages should not print errors
-       // that occur while loading packages. SilenceErrors implies AllowErrors.
-       SilenceErrors bool
+       // SilencePackageErrors indicates that LoadPackages should not print errors
+       // that occur while matching or loading packages, and should not terminate the
+       // process if such an error occurs.
+       //
+       // Errors encountered in the module graph will still be reported.
+       //
+       // The caller may retrieve the silenced package errors using the Lookup
+       // function, and matching errors are still populated in the Errs field of the
+       // associated search.Match.)
+       SilencePackageErrors bool
 
        // SilenceMissingStdImports indicates that LoadPackages should not print
        // errors or terminate the process if an imported package is missing, and the
@@ -176,6 +218,15 @@ type PackageOpts struct {
        // future version).
        SilenceMissingStdImports bool
 
+       // SilenceNoGoErrors indicates that LoadPackages should not print
+       // imports.ErrNoGo errors.
+       // This allows the caller to invoke LoadPackages (and report other errors)
+       // without knowing whether the requested packages exist for the given tags.
+       //
+       // Note that if a requested package does not exist *at all*, it will fail
+       // during module resolution and the error will not be suppressed.
+       SilenceNoGoErrors bool
+
        // SilenceUnmatchedWarnings suppresses the warnings normally emitted for
        // patterns that did not match any packages.
        SilenceUnmatchedWarnings bool
@@ -184,7 +235,6 @@ type PackageOpts struct {
 // LoadPackages identifies the set of packages matching the given patterns and
 // loads the packages in the import graph rooted at that set.
 func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (matches []*search.Match, loadedPackages []string) {
-       LoadModFile(ctx)
        if opts.Tags == nil {
                opts.Tags = imports.Tags()
        }
@@ -199,13 +249,13 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
                }
        }
 
-       updateMatches := func(ld *loader) {
+       updateMatches := func(rs *Requirements, ld *loader) {
                for _, m := range matches {
                        switch {
                        case m.IsLocal():
                                // Evaluate list of file system directories on first iteration.
                                if m.Dirs == nil {
-                                       matchLocalDirs(m)
+                                       matchLocalDirs(ctx, m, rs)
                                }
 
                                // Make a copy of the directory list and translate to import paths.
@@ -216,7 +266,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
                                // the loader iterations.
                                m.Pkgs = m.Pkgs[:0]
                                for _, dir := range m.Dirs {
-                                       pkg, err := resolveLocalPackage(dir)
+                                       pkg, err := resolveLocalPackage(ctx, dir, rs)
                                        if err != nil {
                                                if !m.IsLiteral() && (err == errPkgIsBuiltin || err == errPkgIsGorootSrc) {
                                                        continue // Don't include "builtin" or GOROOT/src in wildcard patterns.
@@ -239,7 +289,17 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
 
                        case strings.Contains(m.Pattern(), "..."):
                                m.Errs = m.Errs[:0]
-                               matchPackages(ctx, m, opts.Tags, includeStd, buildList)
+                               mg, err := rs.Graph(ctx)
+                               if err != nil {
+                                       // The module graph is (or may be) incomplete — perhaps we failed to
+                                       // load the requirements of some module. This is an error in matching
+                                       // the patterns to packages, because we may be missing some packages
+                                       // or we may erroneously match packages in the wrong versions of
+                                       // modules. However, for cases like 'go list -e', the error should not
+                                       // necessarily prevent us from loading the packages we could find.
+                                       m.Errs = append(m.Errs, err)
+                               }
+                               matchPackages(ctx, m, opts.Tags, includeStd, mg.BuildList())
 
                        case m.Pattern() == "all":
                                if ld == nil {
@@ -264,14 +324,16 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
                }
        }
 
-       loaded = loadFromRoots(loaderParams{
-               PackageOpts: opts,
+       initialRS, _ := loadModFile(ctx) // Ignore needCommit — we're going to commit at the end regardless.
 
-               allClosesOverTests: index.allPatternClosesOverTests() && !opts.UseVendorAll,
-               allPatternIsRoot:   allPatternIsRoot,
+       ld := loadFromRoots(ctx, loaderParams{
+               PackageOpts:  opts,
+               requirements: initialRS,
 
-               listRoots: func() (roots []string) {
-                       updateMatches(nil)
+               allPatternIsRoot: allPatternIsRoot,
+
+               listRoots: func(rs *Requirements) (roots []string) {
+                       updateMatches(rs, nil)
                        for _, m := range matches {
                                roots = append(roots, m.Pkgs...)
                        }
@@ -280,47 +342,14 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
        })
 
        // One last pass to finalize wildcards.
-       updateMatches(loaded)
-
-       // Report errors, if any.
-       checkMultiplePaths()
-       for _, pkg := range loaded.pkgs {
-               if pkg.err != nil {
-                       if sumErr := (*ImportMissingSumError)(nil); errors.As(pkg.err, &sumErr) {
-                               if importer := pkg.stack; importer != nil {
-                                       sumErr.importer = importer.path
-                                       sumErr.importerVersion = importer.mod.Version
-                                       sumErr.importerIsTest = importer.testOf != nil
-                               }
-                       }
-                       silence := opts.SilenceErrors
-                       if stdErr := (*ImportMissingError)(nil); errors.As(pkg.err, &stdErr) &&
-                               stdErr.isStd && opts.SilenceMissingStdImports {
-                               silence = true
-                       }
+       updateMatches(ld.requirements, ld)
 
-                       if !silence {
-                               if opts.AllowErrors {
-                                       fmt.Fprintf(os.Stderr, "%s: %v\n", pkg.stackText(), pkg.err)
-                               } else {
-                                       base.Errorf("%s: %v", pkg.stackText(), pkg.err)
-                               }
-                       }
-               }
-               if !pkg.isTest() {
-                       loadedPackages = append(loadedPackages, pkg.path)
-               }
-       }
-       if !opts.SilenceErrors {
-               // Also list errors in matching patterns (such as directory permission
-               // errors for wildcard patterns).
+       // List errors in matching patterns (such as directory permission
+       // errors for wildcard patterns).
+       if !ld.SilencePackageErrors {
                for _, match := range matches {
                        for _, err := range match.Errs {
-                               if opts.AllowErrors {
-                                       fmt.Fprintf(os.Stderr, "%v\n", err)
-                               } else {
-                                       base.Errorf("%v", err)
-                               }
+                               ld.errorf("%v\n", err)
                        }
                }
        }
@@ -330,15 +359,68 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
                search.WarnUnmatched(matches)
        }
 
-       // Success! Update go.mod (if needed) and return the results.
-       WriteGoMod()
+       if opts.Tidy {
+               if cfg.BuildV {
+                       mg, _ := ld.requirements.Graph(ctx)
+
+                       for _, m := range initialRS.rootModules {
+                               var unused bool
+                               if ld.requirements.depth == eager {
+                                       // m is unused if it was dropped from the module graph entirely. If it
+                                       // was only demoted from direct to indirect, it may still be in use via
+                                       // a transitive import.
+                                       unused = mg.Selected(m.Path) == "none"
+                               } else {
+                                       // m is unused if it was dropped from the roots. If it is still present
+                                       // as a transitive dependency, that transitive dependency is not needed
+                                       // by any package or test in the main module.
+                                       _, ok := ld.requirements.rootSelected(m.Path)
+                                       unused = !ok
+                               }
+                               if unused {
+                                       fmt.Fprintf(os.Stderr, "unused %s\n", m.Path)
+                               }
+                       }
+               }
+
+               keep := keepSums(ctx, ld, ld.requirements, loadedZipSumsOnly)
+               if compatDepth := modDepthFromGoVersion(ld.TidyCompatibleVersion); compatDepth != ld.requirements.depth {
+                       compatRS := newRequirements(compatDepth, ld.requirements.rootModules, ld.requirements.direct)
+                       ld.checkTidyCompatibility(ctx, compatRS)
+
+                       for m := range keepSums(ctx, ld, compatRS, loadedZipSumsOnly) {
+                               keep[m] = true
+                       }
+               }
+
+               if allowWriteGoMod {
+                       modfetch.TrimGoSum(keep)
+
+                       // commitRequirements below will also call WriteGoSum, but the "keep" map
+                       // we have here could be strictly larger: commitRequirements only commits
+                       // loaded.requirements, but here we may have also loaded (and want to
+                       // preserve checksums for) additional entities from compatRS, which are
+                       // only needed for compatibility with ld.TidyCompatibleVersion.
+                       modfetch.WriteGoSum(keep)
+               }
+       }
+
+       // Success! Update go.mod and go.sum (if needed) and return the results.
+       loaded = ld
+       commitRequirements(ctx, loaded.GoVersion, loaded.requirements)
+
+       for _, pkg := range ld.pkgs {
+               if !pkg.isTest() {
+                       loadedPackages = append(loadedPackages, pkg.path)
+               }
+       }
        sort.Strings(loadedPackages)
        return matches, loadedPackages
 }
 
 // matchLocalDirs is like m.MatchDirs, but tries to avoid scanning directories
 // outside of the standard library and active modules.
-func matchLocalDirs(m *search.Match) {
+func matchLocalDirs(ctx context.Context, m *search.Match, rs *Requirements) {
        if !m.IsLocal() {
                panic(fmt.Sprintf("internal error: resolveLocalDirs on non-local pattern %s", m.Pattern()))
        }
@@ -352,9 +434,9 @@ func matchLocalDirs(m *search.Match) {
                dir := filepath.Dir(filepath.Clean(m.Pattern()[:i+3]))
                absDir := dir
                if !filepath.IsAbs(dir) {
-                       absDir = filepath.Join(base.Cwd, dir)
+                       absDir = filepath.Join(base.Cwd(), dir)
                }
-               if search.InDir(absDir, cfg.GOROOTsrc) == "" && search.InDir(absDir, ModRoot()) == "" && pathInModuleCache(absDir) == "" {
+               if search.InDir(absDir, cfg.GOROOTsrc) == "" && search.InDir(absDir, ModRoot()) == "" && pathInModuleCache(ctx, absDir, rs) == "" {
                        m.Dirs = []string{}
                        m.AddError(fmt.Errorf("directory prefix %s outside available modules", base.ShortPath(absDir)))
                        return
@@ -365,12 +447,12 @@ func matchLocalDirs(m *search.Match) {
 }
 
 // resolveLocalPackage resolves a filesystem path to a package path.
-func resolveLocalPackage(dir string) (string, error) {
+func resolveLocalPackage(ctx context.Context, dir string, rs *Requirements) (string, error) {
        var absDir string
        if filepath.IsAbs(dir) {
                absDir = filepath.Clean(dir)
        } else {
-               absDir = filepath.Join(base.Cwd, dir)
+               absDir = filepath.Join(base.Cwd(), dir)
        }
 
        bp, err := cfg.BuildContext.ImportDir(absDir, 0)
@@ -456,7 +538,7 @@ func resolveLocalPackage(dir string) (string, error) {
                return pkg, nil
        }
 
-       pkg := pathInModuleCache(absDir)
+       pkg := pathInModuleCache(ctx, absDir, rs)
        if pkg == "" {
                return "", fmt.Errorf("directory %s outside available modules", base.ShortPath(absDir))
        }
@@ -471,7 +553,7 @@ var (
 
 // pathInModuleCache returns the import path of the directory dir,
 // if dir is in the module cache copy of a module in our build list.
-func pathInModuleCache(dir string) string {
+func pathInModuleCache(ctx context.Context, dir string, rs *Requirements) string {
        tryMod := func(m module.Version) (string, bool) {
                var root string
                var err error
@@ -501,20 +583,48 @@ func pathInModuleCache(dir string) string {
                return path.Join(m.Path, filepath.ToSlash(sub)), true
        }
 
-       for _, m := range buildList[1:] {
-               if importPath, ok := tryMod(m); ok {
-                       // checkMultiplePaths ensures that a module can be used for at most one
-                       // requirement, so this must be it.
-                       return importPath
+       if rs.depth == lazy {
+               for _, m := range rs.rootModules {
+                       if v, _ := rs.rootSelected(m.Path); v != m.Version {
+                               continue // m is a root, but we have a higher root for the same path.
+                       }
+                       if importPath, ok := tryMod(m); ok {
+                               // checkMultiplePaths ensures that a module can be used for at most one
+                               // requirement, so this must be it.
+                               return importPath
+                       }
+               }
+       }
+
+       // None of the roots contained dir, or we're in eager mode and want to load
+       // the full module graph more aggressively. Either way, check the full graph
+       // to see if the directory is a non-root dependency.
+       //
+       // If the roots are not consistent with the full module graph, the selected
+       // versions of root modules may differ from what we already checked above.
+       // Re-check those paths too.
+
+       mg, _ := rs.Graph(ctx)
+       var importPath string
+       for _, m := range mg.BuildList() {
+               var found bool
+               importPath, found = tryMod(m)
+               if found {
+                       break
                }
        }
-       return ""
+       return importPath
 }
 
 // ImportFromFiles adds modules to the build list as needed
 // to satisfy the imports in the named Go source files.
+//
+// Errors in missing dependencies are silenced.
+//
+// TODO(bcmills): Silencing errors seems off. Take a closer look at this and
+// figure out what the error-reporting actually ought to be.
 func ImportFromFiles(ctx context.Context, gofiles []string) {
-       LoadModFile(ctx)
+       rs := LoadModFile(ctx)
 
        tags := imports.Tags()
        imports, testImports, err := imports.ScanFiles(gofiles, tags)
@@ -522,31 +632,32 @@ func ImportFromFiles(ctx context.Context, gofiles []string) {
                base.Fatalf("go: %v", err)
        }
 
-       loaded = loadFromRoots(loaderParams{
+       loaded = loadFromRoots(ctx, loaderParams{
                PackageOpts: PackageOpts{
                        Tags:                  tags,
                        ResolveMissingImports: true,
+                       SilencePackageErrors:  true,
                },
-               allClosesOverTests: index.allPatternClosesOverTests(),
-               listRoots: func() (roots []string) {
+               requirements: rs,
+               listRoots: func(*Requirements) (roots []string) {
                        roots = append(roots, imports...)
                        roots = append(roots, testImports...)
                        return roots
                },
        })
-       WriteGoMod()
+       commitRequirements(ctx, loaded.GoVersion, loaded.requirements)
 }
 
 // DirImportPath returns the effective import path for dir,
 // provided it is within the main module, or else returns ".".
-func DirImportPath(dir string) string {
+func DirImportPath(ctx context.Context, dir string) string {
        if !HasModRoot() {
                return "."
        }
-       LoadModFile(context.TODO())
+       LoadModFile(ctx) // Sets targetPrefix.
 
        if !filepath.IsAbs(dir) {
-               dir = filepath.Join(base.Cwd, dir)
+               dir = filepath.Join(base.Cwd(), dir)
        } else {
                dir = filepath.Clean(dir)
        }
@@ -564,20 +675,6 @@ func DirImportPath(dir string) string {
        return "."
 }
 
-// TargetPackages returns the list of packages in the target (top-level) module
-// matching pattern, which may be relative to the working directory, under all
-// build tag settings.
-func TargetPackages(ctx context.Context, pattern string) *search.Match {
-       // TargetPackages is relative to the main module, so ensure that the main
-       // module is a thing that can contain packages.
-       LoadModFile(ctx)
-       ModRoot()
-
-       m := search.NewMatch(pattern)
-       matchPackages(ctx, m, imports.AnyTags(), omitStd, []module.Version{Target})
-       return m
-}
-
 // ImportMap returns the actual package import path
 // for an import path found in source code.
 // If the given import path does not appear in the source code
@@ -609,29 +706,6 @@ func PackageModule(path string) module.Version {
        return pkg.mod
 }
 
-// PackageImports returns the imports for the package named by the import path.
-// Test imports will be returned as well if tests were loaded for the package
-// (i.e., if "all" was loaded or if LoadTests was set and the path was matched
-// by a command line argument). PackageImports will return nil for
-// unknown package paths.
-func PackageImports(path string) (imports, testImports []string) {
-       pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
-       if !ok {
-               return nil, nil
-       }
-       imports = make([]string, len(pkg.imports))
-       for i, p := range pkg.imports {
-               imports[i] = p.path
-       }
-       if pkg.test != nil {
-               testImports = make([]string, len(pkg.test.imports))
-               for i, p := range pkg.test.imports {
-                       testImports[i] = p.path
-               }
-       }
-       return imports, testImports
-}
-
 // Lookup returns the source directory, import path, and any loading error for
 // the package at path as imported from the package in parentDir.
 // Lookup requires that one of the Load functions in this package has already
@@ -670,26 +744,29 @@ func Lookup(parentPath string, parentIsStd bool, path string) (dir, realPath str
 type loader struct {
        loaderParams
 
+       // allClosesOverTests indicates whether the "all" pattern includes
+       // dependencies of tests outside the main module (as in Go 1.11–1.15).
+       // (Otherwise — as in Go 1.16+ — the "all" pattern includes only the packages
+       // transitively *imported by* the packages and tests in the main module.)
+       allClosesOverTests bool
+
        work *par.Queue
 
        // reset on each iteration
        roots    []*loadPkg
        pkgCache *par.Cache // package path (string) → *loadPkg
        pkgs     []*loadPkg // transitive closure of loaded packages and tests; populated in buildStacks
-
-       // computed at end of iterations
-       direct map[string]bool // imported directly by main module
 }
 
 // loaderParams configure the packages loaded by, and the properties reported
 // by, a loader instance.
 type loaderParams struct {
        PackageOpts
+       requirements *Requirements
 
-       allClosesOverTests bool // Does the "all" pattern include the transitive closure of tests of packages in "all"?
-       allPatternIsRoot   bool // Is the "all" pattern an additional root?
+       allPatternIsRoot bool // Is the "all" pattern an additional root?
 
-       listRoots func() []string
+       listRoots func(rs *Requirements) []string
 }
 
 func (ld *loader) reset() {
@@ -704,6 +781,16 @@ func (ld *loader) reset() {
        ld.pkgs = nil
 }
 
+// errorf reports an error via either os.Stderr or base.Errorf,
+// according to whether ld.AllowErrors is set.
+func (ld *loader) errorf(format string, args ...interface{}) {
+       if ld.AllowErrors {
+               fmt.Fprintf(os.Stderr, format, args...)
+       } else {
+               base.Errorf(format, args...)
+       }
+}
+
 // A loadPkg records information about a single loaded package.
 type loadPkg struct {
        // Populated at construction time:
@@ -756,6 +843,11 @@ const (
        // are also roots (and must be marked pkgIsRoot).
        pkgIsRoot
 
+       // pkgFromRoot indicates that the package is in the transitive closure of
+       // imports starting at the roots. (Note that every package marked as pkgIsRoot
+       // is also trivially marked pkgFromRoot.)
+       pkgFromRoot
+
        // pkgImportsLoaded indicates that the imports and testImports fields of a
        // loadPkg have been populated.
        pkgImportsLoaded
@@ -796,6 +888,18 @@ func (pkg *loadPkg) isTest() bool {
        return pkg.testOf != nil
 }
 
+// fromExternalModule reports whether pkg was loaded from a module other than
+// the main module.
+func (pkg *loadPkg) fromExternalModule() bool {
+       if pkg.mod.Path == "" {
+               return false // loaded from the standard library, not a module
+       }
+       if pkg.mod.Path == Target.Path {
+               return false // loaded from the main module.
+       }
+       return true
+}
+
 var errMissing = errors.New("cannot find package")
 
 // loadFromRoots attempts to load the build graph needed to process a set of
@@ -804,20 +908,52 @@ var errMissing = errors.New("cannot find package")
 // The set of root packages is returned by the params.listRoots function, and
 // expanded to the full set of packages by tracing imports (and possibly tests)
 // as needed.
-func loadFromRoots(params loaderParams) *loader {
+func loadFromRoots(ctx context.Context, params loaderParams) *loader {
        ld := &loader{
                loaderParams: params,
                work:         par.NewQueue(runtime.GOMAXPROCS(0)),
        }
 
+       if ld.GoVersion == "" {
+               ld.GoVersion = modFileGoVersion()
+
+               if ld.Tidy && semver.Compare("v"+ld.GoVersion, "v"+LatestGoVersion()) > 0 {
+                       ld.errorf("go mod tidy: go.mod file indicates go %s, but maximum supported version is %s\n", ld.GoVersion, LatestGoVersion())
+                       base.ExitIfErrors()
+               }
+       }
+
+       if ld.Tidy {
+               if ld.TidyCompatibleVersion == "" {
+                       ld.TidyCompatibleVersion = priorGoVersion(ld.GoVersion)
+               } else if semver.Compare("v"+ld.TidyCompatibleVersion, "v"+ld.GoVersion) > 0 {
+                       // Each version of the Go toolchain knows how to interpret go.mod and
+                       // go.sum files produced by all previous versions, so a compatibility
+                       // version higher than the go.mod version adds nothing.
+                       ld.TidyCompatibleVersion = ld.GoVersion
+               }
+       }
+
+       if semver.Compare("v"+ld.GoVersion, narrowAllVersionV) < 0 && !ld.UseVendorAll {
+               // The module's go version explicitly predates the change in "all" for lazy
+               // loading, so continue to use the older interpretation.
+               ld.allClosesOverTests = true
+       }
+
        var err error
-       reqs := &mvsReqs{buildList: buildList}
-       buildList, err = mvs.BuildList(Target, reqs)
+       ld.requirements, err = convertDepth(ctx, ld.requirements, modDepthFromGoVersion(ld.GoVersion))
        if err != nil {
-               base.Fatalf("go: %v", err)
+               ld.errorf("go: %v\n", err)
+       }
+
+       if ld.requirements.depth == eager {
+               var err error
+               ld.requirements, _, err = expandGraph(ctx, ld.requirements)
+               if err != nil {
+                       ld.errorf("go: %v\n", err)
+               }
        }
 
-       addedModuleFor := make(map[string]bool)
        for {
                ld.reset()
 
@@ -825,9 +961,29 @@ func loadFromRoots(params loaderParams) *loader {
                // Note: the returned roots can change on each iteration,
                // since the expansion of package patterns depends on the
                // build list we're using.
+               rootPkgs := ld.listRoots(ld.requirements)
+
+               if ld.requirements.depth == lazy && cfg.BuildMod == "mod" {
+                       // Before we start loading transitive imports of packages, locate all of
+                       // the root packages and promote their containing modules to root modules
+                       // dependencies. If their go.mod files are tidy (the common case) and the
+                       // set of root packages does not change then we can select the correct
+                       // versions of all transitive imports on the first try and complete
+                       // loading in a single iteration.
+                       changedBuildList := ld.preloadRootModules(ctx, rootPkgs)
+                       if changedBuildList {
+                               // The build list has changed, so the set of root packages may have also
+                               // changed. Start over to pick up the changes. (Preloading roots is much
+                               // cheaper than loading the full import graph, so we would rather pay
+                               // for an extra iteration of preloading than potentially end up
+                               // discarding the result of a full iteration of loading.)
+                               continue
+                       }
+               }
+
                inRoots := map[*loadPkg]bool{}
-               for _, path := range ld.listRoots() {
-                       root := ld.pkg(path, pkgIsRoot)
+               for _, path := range rootPkgs {
+                       root := ld.pkg(ctx, path, pkgIsRoot)
                        if !inRoots[root] {
                                ld.roots = append(ld.roots, root)
                                inRoots[root] = true
@@ -843,77 +999,314 @@ func loadFromRoots(params loaderParams) *loader {
 
                ld.buildStacks()
 
+               changed, err := ld.updateRequirements(ctx)
+               if err != nil {
+                       ld.errorf("go: %v\n", err)
+                       break
+               }
+               if changed {
+                       // Don't resolve missing imports until the module graph have stabilized.
+                       // If the roots are still changing, they may turn out to specify a
+                       // requirement on the missing package(s), and we would rather use a
+                       // version specified by a new root than add a new dependency on an
+                       // unrelated version.
+                       continue
+               }
+
                if !ld.ResolveMissingImports || (!HasModRoot() && !allowMissingModuleImports) {
                        // We've loaded as much as we can without resolving missing imports.
                        break
                }
-               modAddedBy := ld.resolveMissingImports(addedModuleFor)
+
+               modAddedBy := ld.resolveMissingImports(ctx)
                if len(modAddedBy) == 0 {
+                       // The roots are stable, and we've resolved all of the missing packages
+                       // that we can.
                        break
                }
 
-               // Recompute buildList with all our additions.
-               reqs = &mvsReqs{buildList: buildList}
-               buildList, err = mvs.BuildList(Target, reqs)
+               toAdd := make([]module.Version, 0, len(modAddedBy))
+               for m, _ := range modAddedBy {
+                       toAdd = append(toAdd, m)
+               }
+               module.Sort(toAdd) // to make errors deterministic
+
+               // We ran updateRequirements before resolving missing imports and it didn't
+               // make any changes, so we know that the requirement graph is already
+               // consistent with ld.pkgs: we don't need to pass ld.pkgs to updateRoots
+               // again. (That would waste time looking for changes that we have already
+               // applied.)
+               var noPkgs []*loadPkg
+               // We also know that we're going to call updateRequirements again next
+               // iteration so we don't need to also update it here. (That would waste time
+               // computing a "direct" map that we'll have to recompute later anyway.)
+               direct := ld.requirements.direct
+               rs, err := updateRoots(ctx, direct, ld.requirements, noPkgs, toAdd, ld.AssumeRootsImported)
                if err != nil {
                        // If an error was found in a newly added module, report the package
                        // import stack instead of the module requirement stack. Packages
                        // are more descriptive.
                        if err, ok := err.(*mvs.BuildListError); ok {
                                if pkg := modAddedBy[err.Module()]; pkg != nil {
-                                       base.Fatalf("go: %s: %v", pkg.stackText(), err.Err)
+                                       ld.errorf("go: %s: %v\n", pkg.stackText(), err.Err)
+                                       break
                                }
                        }
-                       base.Fatalf("go: %v", err)
+                       ld.errorf("go: %v\n", err)
+                       break
                }
+               if reflect.DeepEqual(rs.rootModules, ld.requirements.rootModules) {
+                       // Something is deeply wrong. resolveMissingImports gave us a non-empty
+                       // set of modules to add to the graph, but adding those modules had no
+                       // effect — either they were already in the graph, or updateRoots did not
+                       // add them as requested.
+                       panic(fmt.Sprintf("internal error: adding %v to module graph had no effect on root requirements (%v)", toAdd, rs.rootModules))
+               }
+               ld.requirements = rs
        }
-       base.ExitIfErrors()
+       base.ExitIfErrors() // TODO(bcmills): Is this actually needed?
 
-       // Compute directly referenced dependency modules.
-       ld.direct = make(map[string]bool)
-       for _, pkg := range ld.pkgs {
-               if pkg.mod == Target {
-                       for _, dep := range pkg.imports {
-                               if dep.mod.Path != "" && dep.mod.Path != Target.Path && index != nil {
-                                       _, explicit := index.require[dep.mod]
-                                       if allowWriteGoMod && cfg.BuildMod == "readonly" && !explicit {
-                                               // TODO(#40775): attach error to package instead of using
-                                               // base.Errorf. Ideally, 'go list' should not fail because of this,
-                                               // but today, LoadPackages calls WriteGoMod unconditionally, which
-                                               // would fail with a less clear message.
-                                               base.Errorf("go: %[1]s: package %[2]s imported from implicitly required module; to add missing requirements, run:\n\tgo get %[2]s@%[3]s", pkg.path, dep.path, dep.mod.Version)
-                                       }
-                                       ld.direct[dep.mod.Path] = true
+       // Tidy the build list, if applicable, before we report errors.
+       // (The process of tidying may remove errors from irrelevant dependencies.)
+       if ld.Tidy {
+               rs, err := tidyRoots(ctx, ld.requirements, ld.pkgs)
+               if err != nil {
+                       ld.errorf("go: %v\n", err)
+               }
+
+               if ld.requirements.depth == lazy {
+                       // We continuously add tidy roots to ld.requirements during loading, so at
+                       // this point the tidy roots should be a subset of the roots of
+                       // ld.requirements, ensuring that no new dependencies are brought inside
+                       // the lazy-loading horizon.
+                       // If that is not the case, there is a bug in the loading loop above.
+                       for _, m := range rs.rootModules {
+                               if v, ok := ld.requirements.rootSelected(m.Path); !ok || v != m.Version {
+                                       ld.errorf("go mod tidy: internal error: a requirement on %v is needed but was not added during package loading\n", m)
+                                       base.ExitIfErrors()
                                }
                        }
                }
+               ld.requirements = rs
        }
-       base.ExitIfErrors()
+
+       // Report errors, if any.
+       for _, pkg := range ld.pkgs {
+               if pkg.err == nil {
+                       continue
+               }
+
+               // Add importer information to checksum errors.
+               if sumErr := (*ImportMissingSumError)(nil); errors.As(pkg.err, &sumErr) {
+                       if importer := pkg.stack; importer != nil {
+                               sumErr.importer = importer.path
+                               sumErr.importerVersion = importer.mod.Version
+                               sumErr.importerIsTest = importer.testOf != nil
+                       }
+               }
+
+               if ld.SilencePackageErrors {
+                       continue
+               }
+               if stdErr := (*ImportMissingError)(nil); errors.As(pkg.err, &stdErr) &&
+                       stdErr.isStd && ld.SilenceMissingStdImports {
+                       continue
+               }
+               if ld.SilenceNoGoErrors && errors.Is(pkg.err, imports.ErrNoGo) {
+                       continue
+               }
+
+               ld.errorf("%s: %v\n", pkg.stackText(), pkg.err)
+       }
+
+       ld.checkMultiplePaths()
+       return ld
+}
+
+// updateRequirements ensures that ld.requirements is consistent with the
+// information gained from ld.pkgs and includes the modules in add as roots at
+// at least the given versions.
+//
+// In particular:
+//
+//     - Modules that provide packages directly imported from the main module are
+//       marked as direct, and are promoted to explicit roots. If a needed root
+//       cannot be promoted due to -mod=readonly or -mod=vendor, the importing
+//       package is marked with an error.
+//
+//     - If ld scanned the "all" pattern independent of build constraints, it is
+//       guaranteed to have seen every direct import. Module dependencies that did
+//       not provide any directly-imported package are then marked as indirect.
+//
+//     - Root dependencies are updated to their selected versions.
+//
+// The "changed" return value reports whether the update changed the selected
+// version of any module that either provided a loaded package or may now
+// provide a package that was previously unresolved.
+func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err error) {
+       rs := ld.requirements
+
+       // direct contains the set of modules believed to provide packages directly
+       // imported by the main module.
+       var direct map[string]bool
 
        // If we didn't scan all of the imports from the main module, or didn't use
        // imports.AnyTags, then we didn't necessarily load every package that
-       // contributes “direct” imports — so we can't safely mark existing
-       // dependencies as indirect-only.
-       // Conservatively mark those dependencies as direct.
-       if modFile != nil && (!ld.allPatternIsRoot || !reflect.DeepEqual(ld.Tags, imports.AnyTags())) {
-               for _, r := range modFile.Require {
-                       if !r.Indirect {
-                               ld.direct[r.Mod.Path] = true
+       // contributes “direct” imports — so we can't safely mark existing direct
+       // dependencies in ld.requirements as indirect-only. Propagate them as direct.
+       loadedDirect := ld.allPatternIsRoot && reflect.DeepEqual(ld.Tags, imports.AnyTags())
+       if loadedDirect {
+               direct = make(map[string]bool)
+       } else {
+               // TODO(bcmills): It seems like a shame to allocate and copy a map here when
+               // it will only rarely actually vary from rs.direct. Measure this cost and
+               // maybe avoid the copy.
+               direct = make(map[string]bool, len(rs.direct))
+               for mPath := range rs.direct {
+                       direct[mPath] = true
+               }
+       }
+
+       for _, pkg := range ld.pkgs {
+               if pkg.mod != Target {
+                       continue
+               }
+               for _, dep := range pkg.imports {
+                       if !dep.fromExternalModule() {
+                               continue
+                       }
+
+                       if pkg.err == nil && cfg.BuildMod != "mod" {
+                               if v, ok := rs.rootSelected(dep.mod.Path); !ok || v != dep.mod.Version {
+                                       // dep.mod is not an explicit dependency, but needs to be.
+                                       // Because we are not in "mod" mode, we will not be able to update it.
+                                       // Instead, mark the importing package with an error.
+                                       //
+                                       // TODO(#41688): The resulting error message fails to include the file
+                                       // position of the import statement (because that information is not
+                                       // tracked by the module loader). Figure out how to plumb the import
+                                       // position through.
+                                       pkg.err = &DirectImportFromImplicitDependencyError{
+                                               ImporterPath: pkg.path,
+                                               ImportedPath: dep.path,
+                                               Module:       dep.mod,
+                                       }
+                                       // cfg.BuildMod does not allow us to change dep.mod to be a direct
+                                       // dependency, so don't mark it as such.
+                                       continue
+                               }
                        }
+
+                       // dep is a package directly imported by a package or test in the main
+                       // module and loaded from some other module (not the standard library).
+                       // Mark its module as a direct dependency.
+                       direct[dep.mod.Path] = true
                }
        }
 
-       return ld
+       var addRoots []module.Version
+       if ld.Tidy {
+               // When we are tidying a lazy module, we may need to add roots to preserve
+               // the versions of indirect, test-only dependencies that are upgraded
+               // above or otherwise missing from the go.mod files of direct
+               // dependencies. (For example, the direct dependency might be a very
+               // stable codebase that predates modules and thus lacks a go.mod file, or
+               // the author of the direct dependency may have forgotten to commit a
+               // change to the go.mod file, or may have made an erroneous hand-edit that
+               // causes it to be untidy.)
+               //
+               // Promoting an indirect dependency to a root adds the next layer of its
+               // dependencies to the module graph, which may increase the selected
+               // versions of other modules from which we have already loaded packages.
+               // So after we promote an indirect dependency to a root, we need to reload
+               // packages, which means another iteration of loading.
+               //
+               // As an extra wrinkle, the upgrades due to promoting a root can cause
+               // previously-resolved packages to become unresolved. For example, the
+               // module providing an unstable package might be upgraded to a version
+               // that no longer contains that package. If we then resolve the missing
+               // package, we might add yet another root that upgrades away some other
+               // dependency. (The tests in mod_tidy_convergence*.txt illustrate some
+               // particularly worrisome cases.)
+               //
+               // To ensure that this process of promoting, adding, and upgrading roots
+               // eventually terminates, during iteration we only ever add modules to the
+               // root set — we only remove irrelevant roots at the very end of
+               // iteration, after we have already added every root that we plan to need
+               // in the (eventual) tidy root set.
+               //
+               // Since we do not remove any roots during iteration, even if they no
+               // longer provide any imported packages, the selected versions of the
+               // roots can only increase and the set of roots can only expand. The set
+               // of extant root paths is finite and the set of versions of each path is
+               // finite, so the iteration *must* reach a stable fixed-point.
+               tidy, err := tidyRoots(ctx, rs, ld.pkgs)
+               if err != nil {
+                       return false, err
+               }
+               addRoots = tidy.rootModules
+       }
+
+       rs, err = updateRoots(ctx, direct, rs, ld.pkgs, addRoots, ld.AssumeRootsImported)
+       if err != nil {
+               // We don't actually know what even the root requirements are supposed to be,
+               // so we can't proceed with loading. Return the error to the caller
+               return false, err
+       }
+
+       if rs != ld.requirements && !reflect.DeepEqual(rs.rootModules, ld.requirements.rootModules) {
+               // The roots of the module graph have changed in some way (not just the
+               // "direct" markings). Check whether the changes affected any of the loaded
+               // packages.
+               mg, err := rs.Graph(ctx)
+               if err != nil {
+                       return false, err
+               }
+               for _, pkg := range ld.pkgs {
+                       if pkg.fromExternalModule() && mg.Selected(pkg.mod.Path) != pkg.mod.Version {
+                               changed = true
+                               break
+                       }
+                       if pkg.err != nil {
+                               // Promoting a module to a root may resolve an import that was
+                               // previously missing (by pulling in a previously-prune dependency that
+                               // provides it) or ambiguous (by promoting exactly one of the
+                               // alternatives to a root and ignoring the second-level alternatives) or
+                               // otherwise errored out (by upgrading from a version that cannot be
+                               // fetched to one that can be).
+                               //
+                               // Instead of enumerating all of the possible errors, we'll just check
+                               // whether importFromModules returns nil for the package.
+                               // False-positives are ok: if we have a false-positive here, we'll do an
+                               // extra iteration of package loading this time, but we'll still
+                               // converge when the root set stops changing.
+                               //
+                               // In some sense, we can think of this as ‘upgraded the module providing
+                               // pkg.path from "none" to a version higher than "none"’.
+                               if _, _, err = importFromModules(ctx, pkg.path, rs, nil); err == nil {
+                                       changed = true
+                                       break
+                               }
+                       }
+               }
+       }
+
+       ld.requirements = rs
+       return changed, nil
 }
 
-// resolveMissingImports adds module dependencies to the global build list
-// in order to resolve missing packages from pkgs.
+// resolveMissingImports returns a set of modules that could be added as
+// dependencies in order to resolve missing packages from pkgs.
 //
 // The newly-resolved packages are added to the addedModuleFor map, and
-// resolveMissingImports returns a map from each newly-added module version to
-// the first package for which that module was added.
-func (ld *loader) resolveMissingImports(addedModuleFor map[string]bool) (modAddedBy map[module.Version]*loadPkg) {
-       var needPkgs []*loadPkg
+// resolveMissingImports returns a map from each new module version to
+// the first missing package that module would resolve.
+func (ld *loader) resolveMissingImports(ctx context.Context) (modAddedBy map[module.Version]*loadPkg) {
+       type pkgMod struct {
+               pkg *loadPkg
+               mod *module.Version
+       }
+       var pkgMods []pkgMod
        for _, pkg := range ld.pkgs {
                if pkg.err == nil {
                        continue
@@ -928,30 +1321,47 @@ func (ld *loader) resolveMissingImports(addedModuleFor map[string]bool) (modAdde
                        continue
                }
 
-               needPkgs = append(needPkgs, pkg)
-
                pkg := pkg
+               var mod module.Version
                ld.work.Add(func() {
-                       pkg.mod, pkg.err = queryImport(context.TODO(), pkg.path)
+                       var err error
+                       mod, err = queryImport(ctx, pkg.path, ld.requirements)
+                       if err != nil {
+                               // pkg.err was already non-nil, so we can reasonably attribute the error
+                               // for pkg to either the original error or the one returned by
+                               // queryImport. The existing error indicates only that we couldn't find
+                               // the package, whereas the query error also explains why we didn't fix
+                               // the problem — so we prefer the latter.
+                               pkg.err = err
+                       }
+
+                       // err is nil, but we intentionally leave pkg.err non-nil and pkg.mod
+                       // unset: we still haven't satisfied other invariants of a
+                       // successfully-loaded package, such as scanning and loading the imports
+                       // of that package. If we succeed in resolving the new dependency graph,
+                       // the caller can reload pkg and update the error at that point.
+                       //
+                       // Even then, the package might not be loaded from the version we've
+                       // identified here. The module may be upgraded by some other dependency,
+                       // or by a transitive dependency of mod itself, or — less likely — the
+                       // package may be rejected by an AllowPackage hook or rendered ambiguous
+                       // by some other newly-added or newly-upgraded dependency.
                })
+
+               pkgMods = append(pkgMods, pkgMod{pkg: pkg, mod: &mod})
        }
        <-ld.work.Idle()
 
        modAddedBy = map[module.Version]*loadPkg{}
-       for _, pkg := range needPkgs {
-               if pkg.err != nil {
+       for _, pm := range pkgMods {
+               pkg, mod := pm.pkg, *pm.mod
+               if mod.Path == "" {
                        continue
                }
 
-               fmt.Fprintf(os.Stderr, "go: found %s in %s %s\n", pkg.path, pkg.mod.Path, pkg.mod.Version)
-               if addedModuleFor[pkg.path] {
-                       // TODO(bcmills): This should only be an error if pkg.mod is the same
-                       // version we already tried to add previously.
-                       base.Fatalf("go: %s: looping trying to add package", pkg.stackText())
-               }
-               if modAddedBy[pkg.mod] == nil {
-                       modAddedBy[pkg.mod] = pkg
-                       buildList = append(buildList, pkg.mod)
+               fmt.Fprintf(os.Stderr, "go: found %s in %s %s\n", pkg.path, mod.Path, mod.Version)
+               if modAddedBy[mod] == nil {
+                       modAddedBy[mod] = pkg
                }
        }
 
@@ -965,7 +1375,7 @@ func (ld *loader) resolveMissingImports(addedModuleFor map[string]bool) (modAdde
 // ld.work queue, and its test (if requested) will also be populated once
 // imports have been resolved. When ld.work goes idle, all transitive imports of
 // the requested package (and its test, if requested) will have been loaded.
-func (ld *loader) pkg(path string, flags loadPkgFlags) *loadPkg {
+func (ld *loader) pkg(ctx context.Context, path string, flags loadPkgFlags) *loadPkg {
        if flags.has(pkgImportsLoaded) {
                panic("internal error: (*loader).pkg called with pkgImportsLoaded flag set")
        }
@@ -974,20 +1384,20 @@ func (ld *loader) pkg(path string, flags loadPkgFlags) *loadPkg {
                pkg := &loadPkg{
                        path: path,
                }
-               ld.applyPkgFlags(pkg, flags)
+               ld.applyPkgFlags(ctx, pkg, flags)
 
-               ld.work.Add(func() { ld.load(pkg) })
+               ld.work.Add(func() { ld.load(ctx, pkg) })
                return pkg
        }).(*loadPkg)
 
-       ld.applyPkgFlags(pkg, flags)
+       ld.applyPkgFlags(ctx, pkg, flags)
        return pkg
 }
 
 // applyPkgFlags updates pkg.flags to set the given flags and propagate the
 // (transitive) effects of those flags, possibly loading or enqueueing further
 // packages as a result.
-func (ld *loader) applyPkgFlags(pkg *loadPkg, flags loadPkgFlags) {
+func (ld *loader) applyPkgFlags(ctx context.Context, pkg *loadPkg, flags loadPkgFlags) {
        if flags == 0 {
                return
        }
@@ -996,6 +1406,9 @@ func (ld *loader) applyPkgFlags(pkg *loadPkg, flags loadPkgFlags) {
                // This package matches a root pattern by virtue of being in "all".
                flags |= pkgIsRoot
        }
+       if flags.has(pkgIsRoot) {
+               flags |= pkgFromRoot
+       }
 
        old := pkg.flags.update(flags)
        new := old | flags
@@ -1039,7 +1452,7 @@ func (ld *loader) applyPkgFlags(pkg *loadPkg, flags loadPkgFlags) {
                                // of packages in "all" if "all" closes over test dependencies.
                                testFlags |= pkgInAll
                        }
-                       ld.pkgTest(pkg, testFlags)
+                       ld.pkgTest(ctx, pkg, testFlags)
                }
        }
 
@@ -1047,13 +1460,100 @@ func (ld *loader) applyPkgFlags(pkg *loadPkg, flags loadPkgFlags) {
                // We have just marked pkg with pkgInAll, or we have just loaded its
                // imports, or both. Now is the time to propagate pkgInAll to the imports.
                for _, dep := range pkg.imports {
-                       ld.applyPkgFlags(dep, pkgInAll)
+                       ld.applyPkgFlags(ctx, dep, pkgInAll)
                }
        }
+
+       if new.has(pkgFromRoot) && !old.has(pkgFromRoot|pkgImportsLoaded) {
+               for _, dep := range pkg.imports {
+                       ld.applyPkgFlags(ctx, dep, pkgFromRoot)
+               }
+       }
+}
+
+// preloadRootModules loads the module requirements needed to identify the
+// selected version of each module providing a package in rootPkgs,
+// adding new root modules to the module graph if needed.
+func (ld *loader) preloadRootModules(ctx context.Context, rootPkgs []string) (changedBuildList bool) {
+       needc := make(chan map[module.Version]bool, 1)
+       needc <- map[module.Version]bool{}
+       for _, path := range rootPkgs {
+               path := path
+               ld.work.Add(func() {
+                       // First, try to identify the module containing the package using only roots.
+                       //
+                       // If the main module is tidy and the package is in "all" — or if we're
+                       // lucky — we can identify all of its imports without actually loading the
+                       // full module graph.
+                       m, _, err := importFromModules(ctx, path, ld.requirements, nil)
+                       if err != nil {
+                               var missing *ImportMissingError
+                               if errors.As(err, &missing) && ld.ResolveMissingImports {
+                                       // This package isn't provided by any selected module.
+                                       // If we can find it, it will be a new root dependency.
+                                       m, err = queryImport(ctx, path, ld.requirements)
+                               }
+                               if err != nil {
+                                       // We couldn't identify the root module containing this package.
+                                       // Leave it unresolved; we will report it during loading.
+                                       return
+                               }
+                       }
+                       if m.Path == "" {
+                               // The package is in std or cmd. We don't need to change the root set.
+                               return
+                       }
+
+                       v, ok := ld.requirements.rootSelected(m.Path)
+                       if !ok || v != m.Version {
+                               // We found the requested package in m, but m is not a root, so
+                               // loadModGraph will not load its requirements. We need to promote the
+                               // module to a root to ensure that any other packages this package
+                               // imports are resolved from correct dependency versions.
+                               //
+                               // (This is the “argument invariant” from the lazy loading design.)
+                               need := <-needc
+                               need[m] = true
+                               needc <- need
+                       }
+               })
+       }
+       <-ld.work.Idle()
+
+       need := <-needc
+       if len(need) == 0 {
+               return false // No roots to add.
+       }
+
+       toAdd := make([]module.Version, 0, len(need))
+       for m := range need {
+               toAdd = append(toAdd, m)
+       }
+       module.Sort(toAdd)
+
+       rs, err := updateRoots(ctx, ld.requirements.direct, ld.requirements, nil, toAdd, ld.AssumeRootsImported)
+       if err != nil {
+               // We are missing some root dependency, and for some reason we can't load
+               // enough of the module dependency graph to add the missing root. Package
+               // loading is doomed to fail, so fail quickly.
+               ld.errorf("go: %v\n", err)
+               base.ExitIfErrors()
+               return false
+       }
+       if reflect.DeepEqual(rs.rootModules, ld.requirements.rootModules) {
+               // Something is deeply wrong. resolveMissingImports gave us a non-empty
+               // set of modules to add to the graph, but adding those modules had no
+               // effect — either they were already in the graph, or updateRoots did not
+               // add them as requested.
+               panic(fmt.Sprintf("internal error: adding %v to module graph had no effect on root requirements (%v)", toAdd, rs.rootModules))
+       }
+
+       ld.requirements = rs
+       return true
 }
 
 // load loads an individual package.
-func (ld *loader) load(pkg *loadPkg) {
+func (ld *loader) load(ctx context.Context, pkg *loadPkg) {
        if strings.Contains(pkg.path, "@") {
                // Leave for error during load.
                return
@@ -1072,7 +1572,24 @@ func (ld *loader) load(pkg *loadPkg) {
                return
        }
 
-       pkg.mod, pkg.dir, pkg.err = importFromBuildList(context.TODO(), pkg.path, buildList)
+       var mg *ModuleGraph
+       if ld.requirements.depth == eager {
+               var err error
+               mg, err = ld.requirements.Graph(ctx)
+               if err != nil {
+                       // We already checked the error from Graph in loadFromRoots and/or
+                       // updateRequirements, so we ignored the error on purpose and we should
+                       // keep trying to push past it.
+                       //
+                       // However, because mg may be incomplete (and thus may select inaccurate
+                       // versions), we shouldn't use it to load packages. Instead, we pass a nil
+                       // *ModuleGraph, which will cause mg to first try loading from only the
+                       // main module and root dependencies.
+                       mg = nil
+               }
+       }
+
+       pkg.mod, pkg.dir, pkg.err = importFromModules(ctx, pkg.path, ld.requirements, mg)
        if pkg.dir == "" {
                return
        }
@@ -1086,10 +1603,10 @@ func (ld *loader) load(pkg *loadPkg) {
                // about (by reducing churn on the flag bits of dependencies), and costs
                // essentially nothing (these atomic flag ops are essentially free compared
                // to scanning source code for imports).
-               ld.applyPkgFlags(pkg, pkgInAll)
+               ld.applyPkgFlags(ctx, pkg, pkgInAll)
        }
        if ld.AllowPackage != nil {
-               if err := ld.AllowPackage(context.TODO(), pkg.path, pkg.mod); err != nil {
+               if err := ld.AllowPackage(ctx, pkg.path, pkg.mod); err != nil {
                        pkg.err = err
                }
        }
@@ -1120,11 +1637,11 @@ func (ld *loader) load(pkg *loadPkg) {
                        // GOROOT/src/vendor even when "std" is not the main module.
                        path = ld.stdVendor(pkg.path, path)
                }
-               pkg.imports = append(pkg.imports, ld.pkg(path, importFlags))
+               pkg.imports = append(pkg.imports, ld.pkg(ctx, path, importFlags))
        }
        pkg.testImports = testImports
 
-       ld.applyPkgFlags(pkg, pkgImportsLoaded)
+       ld.applyPkgFlags(ctx, pkg, pkgImportsLoaded)
 }
 
 // pkgTest locates the test of pkg, creating it if needed, and updates its state
@@ -1132,7 +1649,7 @@ func (ld *loader) load(pkg *loadPkg) {
 //
 // pkgTest requires that the imports of pkg have already been loaded (flagged
 // with pkgImportsLoaded).
-func (ld *loader) pkgTest(pkg *loadPkg, testFlags loadPkgFlags) *loadPkg {
+func (ld *loader) pkgTest(ctx context.Context, pkg *loadPkg, testFlags loadPkgFlags) *loadPkg {
        if pkg.isTest() {
                panic("pkgTest called on a test package")
        }
@@ -1147,7 +1664,7 @@ func (ld *loader) pkgTest(pkg *loadPkg, testFlags loadPkgFlags) *loadPkg {
                        err:    pkg.err,
                        inStd:  pkg.inStd,
                }
-               ld.applyPkgFlags(pkg.test, testFlags)
+               ld.applyPkgFlags(ctx, pkg.test, testFlags)
                createdTest = true
        })
 
@@ -1162,12 +1679,12 @@ func (ld *loader) pkgTest(pkg *loadPkg, testFlags loadPkgFlags) *loadPkg {
                        if pkg.inStd {
                                path = ld.stdVendor(test.path, path)
                        }
-                       test.imports = append(test.imports, ld.pkg(path, importFlags))
+                       test.imports = append(test.imports, ld.pkg(ctx, path, importFlags))
                }
                pkg.testImports = nil
-               ld.applyPkgFlags(test, pkgImportsLoaded)
+               ld.applyPkgFlags(ctx, test, pkgImportsLoaded)
        } else {
-               ld.applyPkgFlags(test, testFlags)
+               ld.applyPkgFlags(ctx, test, testFlags)
        }
 
        return test
@@ -1181,13 +1698,13 @@ func (ld *loader) stdVendor(parentPath, path string) string {
        }
 
        if str.HasPathPrefix(parentPath, "cmd") {
-               if Target.Path != "cmd" {
+               if !ld.VendorModulesInGOROOTSrc || Target.Path != "cmd" {
                        vendorPath := pathpkg.Join("cmd", "vendor", path)
                        if _, err := os.Stat(filepath.Join(cfg.GOROOTsrc, filepath.FromSlash(vendorPath))); err == nil {
                                return vendorPath
                        }
                }
-       } else if Target.Path != "std" || str.HasPathPrefix(parentPath, "vendor") {
+       } else if !ld.VendorModulesInGOROOTSrc || Target.Path != "std" || str.HasPathPrefix(parentPath, "vendor") {
                // If we are outside of the 'std' module, resolve imports from within 'std'
                // to the vendor directory.
                //
@@ -1222,6 +1739,242 @@ func (ld *loader) computePatternAll() (all []string) {
        return all
 }
 
+// checkMultiplePaths verifies that a given module path is used as itself
+// or as a replacement for another module, but not both at the same time.
+//
+// (See https://golang.org/issue/26607 and https://golang.org/issue/34650.)
+func (ld *loader) checkMultiplePaths() {
+       mods := ld.requirements.rootModules
+       if cached := ld.requirements.graph.Load(); cached != nil {
+               if mg := cached.(cachedGraph).mg; mg != nil {
+                       mods = mg.BuildList()
+               }
+       }
+
+       firstPath := map[module.Version]string{}
+       for _, mod := range mods {
+               src := resolveReplacement(mod)
+               if prev, ok := firstPath[src]; !ok {
+                       firstPath[src] = mod.Path
+               } else if prev != mod.Path {
+                       ld.errorf("go: %s@%s used for two different module paths (%s and %s)\n", src.Path, src.Version, prev, mod.Path)
+               }
+       }
+}
+
+// checkTidyCompatibility emits an error if any package would be loaded from a
+// different module under rs than under ld.requirements.
+func (ld *loader) checkTidyCompatibility(ctx context.Context, rs *Requirements) {
+       suggestUpgrade := false
+       suggestEFlag := false
+       suggestFixes := func() {
+               if ld.AllowErrors {
+                       // The user is explicitly ignoring these errors, so don't bother them with
+                       // other options.
+                       return
+               }
+
+               // We print directly to os.Stderr because this information is advice about
+               // how to fix errors, not actually an error itself.
+               // (The actual errors should have been logged already.)
+
+               fmt.Fprintln(os.Stderr)
+
+               goFlag := ""
+               if ld.GoVersion != modFileGoVersion() {
+                       goFlag = " -go=" + ld.GoVersion
+               }
+
+               compatFlag := ""
+               if ld.TidyCompatibleVersion != priorGoVersion(ld.GoVersion) {
+                       compatFlag = " -compat=" + ld.TidyCompatibleVersion
+               }
+               if suggestUpgrade {
+                       eDesc := ""
+                       eFlag := ""
+                       if suggestEFlag {
+                               eDesc = ", leaving some packages unresolved"
+                               eFlag = " -e"
+                       }
+                       fmt.Fprintf(os.Stderr, "To upgrade to the versions selected by go %s%s:\n\tgo mod tidy%s -go=%s && go mod tidy%s -go=%s%s\n", ld.TidyCompatibleVersion, eDesc, eFlag, ld.TidyCompatibleVersion, eFlag, ld.GoVersion, compatFlag)
+               } else if suggestEFlag {
+                       // If some packages are missing but no package is upgraded, then we
+                       // shouldn't suggest upgrading to the Go 1.16 versions explicitly — that
+                       // wouldn't actually fix anything for Go 1.16 users, and *would* break
+                       // something for Go 1.17 users.
+                       fmt.Fprintf(os.Stderr, "To proceed despite packages unresolved in go %s:\n\tgo mod tidy -e%s%s\n", ld.TidyCompatibleVersion, goFlag, compatFlag)
+               }
+
+               fmt.Fprintf(os.Stderr, "If reproducibility with go %s is not needed:\n\tgo mod tidy%s -compat=%s\n", ld.TidyCompatibleVersion, goFlag, ld.GoVersion)
+
+               // TODO(#46141): Populate the linked wiki page.
+               fmt.Fprintf(os.Stderr, "For other options, see:\n\thttps://golang.org/doc/modules/pruning\n")
+       }
+
+       mg, err := rs.Graph(ctx)
+       if err != nil {
+               ld.errorf("go mod tidy: error loading go %s module graph: %v\n", ld.TidyCompatibleVersion, err)
+               suggestFixes()
+               return
+       }
+
+       // Re-resolve packages in parallel.
+       //
+       // We re-resolve each package — rather than just checking versions — to ensure
+       // that we have fetched module source code (and, importantly, checksums for
+       // that source code) for all modules that are necessary to ensure that imports
+       // are unambiguous. That also produces clearer diagnostics, since we can say
+       // exactly what happened to the package if it became ambiguous or disappeared
+       // entirely.
+       //
+       // We re-resolve the packages in parallel because this process involves disk
+       // I/O to check for package sources, and because the process of checking for
+       // ambiguous imports may require us to download additional modules that are
+       // otherwise pruned out in Go 1.17 — we don't want to block progress on other
+       // packages while we wait for a single new download.
+       type mismatch struct {
+               mod module.Version
+               err error
+       }
+       mismatchMu := make(chan map[*loadPkg]mismatch, 1)
+       mismatchMu <- map[*loadPkg]mismatch{}
+       for _, pkg := range ld.pkgs {
+               if pkg.mod.Path == "" && pkg.err == nil {
+                       // This package is from the standard library (which does not vary based on
+                       // the module graph).
+                       continue
+               }
+
+               pkg := pkg
+               ld.work.Add(func() {
+                       mod, _, err := importFromModules(ctx, pkg.path, rs, mg)
+                       if mod != pkg.mod {
+                               mismatches := <-mismatchMu
+                               mismatches[pkg] = mismatch{mod: mod, err: err}
+                               mismatchMu <- mismatches
+                       }
+               })
+       }
+       <-ld.work.Idle()
+
+       mismatches := <-mismatchMu
+       if len(mismatches) == 0 {
+               // Since we're running as part of 'go mod tidy', the roots of the module
+               // graph should contain only modules that are relevant to some package in
+               // the package graph. We checked every package in the package graph and
+               // didn't find any mismatches, so that must mean that all of the roots of
+               // the module graph are also consistent.
+               //
+               // If we're wrong, Go 1.16 in -mod=readonly mode will error out with
+               // "updates to go.mod needed", which would be very confusing. So instead,
+               // we'll double-check that our reasoning above actually holds — if it
+               // doesn't, we'll emit an internal error and hopefully the user will report
+               // it as a bug.
+               for _, m := range ld.requirements.rootModules {
+                       if v := mg.Selected(m.Path); v != m.Version {
+                               fmt.Fprintln(os.Stderr)
+                               base.Fatalf("go: internal error: failed to diagnose selected-version mismatch for module %s: go %s selects %s, but go %s selects %s\n\tPlease report this at https://golang.org/issue.", m.Path, ld.GoVersion, m.Version, ld.TidyCompatibleVersion, v)
+                       }
+               }
+               return
+       }
+
+       // Iterate over the packages (instead of the mismatches map) to emit errors in
+       // deterministic order.
+       for _, pkg := range ld.pkgs {
+               mismatch, ok := mismatches[pkg]
+               if !ok {
+                       continue
+               }
+
+               if pkg.isTest() {
+                       // We already did (or will) report an error for the package itself,
+                       // so don't report a duplicate (and more vebose) error for its test.
+                       if _, ok := mismatches[pkg.testOf]; !ok {
+                               base.Fatalf("go: internal error: mismatch recorded for test %s, but not its non-test package", pkg.path)
+                       }
+                       continue
+               }
+
+               switch {
+               case mismatch.err != nil:
+                       // pkg resolved successfully, but errors out using the requirements in rs.
+                       //
+                       // This could occur because the import is provided by a single lazy root
+                       // (and is thus unambiguous in lazy mode) and also one or more
+                       // transitive dependencies (and is ambiguous in eager mode).
+                       //
+                       // It could also occur because some transitive dependency upgrades the
+                       // module that previously provided the package to a version that no
+                       // longer does, or to a version for which the module source code (but
+                       // not the go.mod file in isolation) has a checksum error.
+                       if missing := (*ImportMissingError)(nil); errors.As(mismatch.err, &missing) {
+                               selected := module.Version{
+                                       Path:    pkg.mod.Path,
+                                       Version: mg.Selected(pkg.mod.Path),
+                               }
+                               ld.errorf("%s loaded from %v,\n\tbut go %s would fail to locate it in %s\n", pkg.stackText(), pkg.mod, ld.TidyCompatibleVersion, selected)
+                       } else {
+                               if ambiguous := (*AmbiguousImportError)(nil); errors.As(mismatch.err, &ambiguous) {
+                                       // TODO: Is this check needed?
+                               }
+                               ld.errorf("%s loaded from %v,\n\tbut go %s would fail to locate it:\n\t%v\n", pkg.stackText(), pkg.mod, ld.TidyCompatibleVersion, mismatch.err)
+                       }
+
+                       suggestEFlag = true
+
+                       // Even if we press ahead with the '-e' flag, the older version will
+                       // error out in readonly mode if it thinks the go.mod file contains
+                       // any *explicit* dependency that is not at its selected version,
+                       // even if that dependency is not relevant to any package being loaded.
+                       //
+                       // We check for that condition here. If all of the roots are consistent
+                       // the '-e' flag suffices, but otherwise we need to suggest an upgrade.
+                       if !suggestUpgrade {
+                               for _, m := range ld.requirements.rootModules {
+                                       if v := mg.Selected(m.Path); v != m.Version {
+                                               suggestUpgrade = true
+                                               break
+                                       }
+                               }
+                       }
+
+               case pkg.err != nil:
+                       // pkg had an error in lazy mode (presumably suppressed with the -e flag),
+                       // but not in eager mode.
+                       //
+                       // This is possible, if, say, the import is unresolved in lazy mode
+                       // (because the "latest" version of each candidate module either is
+                       // unavailable or does not contain the package), but is resolved in
+                       // eager mode due to a newer-than-latest dependency that is normally
+                       // runed out of the module graph.
+                       //
+                       // This could also occur if the source code for the module providing the
+                       // package in lazy mode has a checksum error, but eager mode upgrades
+                       // that module to a version with a correct checksum.
+                       //
+                       // pkg.err should have already been logged elsewhere — along with a
+                       // stack trace — so log only the import path and non-error info here.
+                       suggestUpgrade = true
+                       ld.errorf("%s failed to load from any module,\n\tbut go %s would load it from %v\n", pkg.path, ld.TidyCompatibleVersion, mismatch.mod)
+
+               case pkg.mod != mismatch.mod:
+                       // The package is loaded successfully by both Go versions, but from a
+                       // different module in each. This could lead to subtle (and perhaps even
+                       // unnoticed!) variations in behavior between builds with different
+                       // toolchains.
+                       suggestUpgrade = true
+                       ld.errorf("%s loaded from %v,\n\tbut go %s would select %v\n", pkg.stackText(), pkg.mod, ld.TidyCompatibleVersion, mismatch.mod.Version)
+
+               default:
+                       base.Fatalf("go: internal error: mismatch recorded for package %s, but no differences found", pkg.path)
+               }
+       }
+
+       suggestFixes()
+       base.ExitIfErrors()
+}
+
 // scanDir is like imports.ScanDir but elides known magic imports from the list,
 // so that we do not go looking for packages that don't really exist.
 //
index c6667d0bf7944b2dcae558005363d648a05c4c5f..03e02e73b63f659f0ec6e3eff89299f691763c6d 100644 (file)
@@ -8,6 +8,7 @@ import (
        "context"
        "errors"
        "fmt"
+       "os"
        "path/filepath"
        "strings"
        "sync"
@@ -15,6 +16,7 @@ import (
 
        "cmd/go/internal/base"
        "cmd/go/internal/cfg"
+       "cmd/go/internal/fsys"
        "cmd/go/internal/lockedfile"
        "cmd/go/internal/modfetch"
        "cmd/go/internal/par"
@@ -25,14 +27,58 @@ import (
        "golang.org/x/mod/semver"
 )
 
-// narrowAllVersionV is the Go version (plus leading "v") at which the
-// module-module "all" pattern no longer closes over the dependencies of
-// tests outside of the main module.
-const narrowAllVersionV = "v1.16"
-const go116EnableNarrowAll = true
+const (
+       // narrowAllVersionV is the Go version (plus leading "v") at which the
+       // module-module "all" pattern no longer closes over the dependencies of
+       // tests outside of the main module.
+       narrowAllVersionV = "v1.16"
+
+       // lazyLoadingVersionV is the Go version (plus leading "v") at which a
+       // module's go.mod file is expected to list explicit requirements on every
+       // module that provides any package transitively imported by that module.
+       lazyLoadingVersionV = "v1.17"
+
+       // separateIndirectVersionV is the Go version (plus leading "v") at which
+       // "// indirect" dependencies are added in a block separate from the direct
+       // ones. See https://golang.org/issue/45965.
+       separateIndirectVersionV = "v1.17"
+)
+
+const (
+       // go117EnableLazyLoading toggles whether lazy-loading code paths should be
+       // active. It will be removed once the lazy loading implementation is stable
+       // and well-tested.
+       go117EnableLazyLoading = true
+
+       // go1117LazyTODO is a constant that exists only until lazy loading is
+       // implemented. Its use indicates a condition that will need to change if the
+       // main module is lazy.
+       go117LazyTODO = false
+)
 
 var modFile *modfile.File
 
+// modFileGoVersion returns the (non-empty) Go version at which the requirements
+// in modFile are intepreted, or the latest Go version if modFile is nil.
+func modFileGoVersion() string {
+       if modFile == nil {
+               return LatestGoVersion()
+       }
+       if modFile.Go == nil || modFile.Go.Version == "" {
+               // The main module necessarily has a go.mod file, and that file lacks a
+               // 'go' directive. The 'go' command has been adding that directive
+               // automatically since Go 1.12, so this module either dates to Go 1.11 or
+               // has been erroneously hand-edited.
+               //
+               // The semantics of the go.mod file are more-or-less the same from Go 1.11
+               // through Go 1.16, changing at 1.17 for lazy loading. So even though a
+               // go.mod file without a 'go' directive is theoretically a Go 1.11 file,
+               // scripts may assume that it ends up as a Go 1.16 module.
+               return "1.16"
+       }
+       return modFile.Go.Version
+}
+
 // A modFileIndex is an index of data corresponding to a modFile
 // at a specific point in time.
 type modFileIndex struct {
@@ -53,6 +99,24 @@ type requireMeta struct {
        indirect bool
 }
 
+// A modDepth indicates which dependencies should be loaded for a go.mod file.
+type modDepth uint8
+
+const (
+       lazy  modDepth = iota // load dependencies only as needed
+       eager                 // load all transitive dependencies eagerly
+)
+
+func modDepthFromGoVersion(goVersion string) modDepth {
+       if !go117EnableLazyLoading {
+               return eager
+       }
+       if semver.Compare("v"+goVersion, lazyLoadingVersionV) < 0 {
+               return eager
+       }
+       return lazy
+}
+
 // CheckAllowed returns an error equivalent to ErrDisallowed if m is excluded by
 // the main module's go.mod or retracted by its author. Most version queries use
 // this to filter out versions that should not be used.
@@ -88,76 +152,53 @@ func (e *excludedError) Is(err error) bool { return err == ErrDisallowed }
 
 // CheckRetractions returns an error if module m has been retracted by
 // its author.
-func CheckRetractions(ctx context.Context, m module.Version) error {
+func CheckRetractions(ctx context.Context, m module.Version) (err error) {
+       defer func() {
+               if retractErr := (*ModuleRetractedError)(nil); err == nil || errors.As(err, &retractErr) {
+                       return
+               }
+               // Attribute the error to the version being checked, not the version from
+               // which the retractions were to be loaded.
+               if mErr := (*module.ModuleError)(nil); errors.As(err, &mErr) {
+                       err = mErr.Err
+               }
+               err = &retractionLoadingError{m: m, err: err}
+       }()
+
        if m.Version == "" {
                // Main module, standard library, or file replacement module.
                // Cannot be retracted.
                return nil
        }
-
-       // Look up retraction information from the latest available version of
-       // the module. Cache retraction information so we don't parse the go.mod
-       // file repeatedly.
-       type entry struct {
-               retract []retraction
-               err     error
+       if repl := Replacement(module.Version{Path: m.Path}); repl.Path != "" {
+               // All versions of the module were replaced.
+               // Don't load retractions, since we'd just load the replacement.
+               return nil
        }
-       path := m.Path
-       e := retractCache.Do(path, func() (v interface{}) {
-               ctx, span := trace.StartSpan(ctx, "checkRetractions "+path)
-               defer span.Done()
-
-               if repl := Replacement(module.Version{Path: m.Path}); repl.Path != "" {
-                       // All versions of the module were replaced with a local directory.
-                       // Don't load retractions.
-                       return &entry{nil, nil}
-               }
-
-               // Find the latest version of the module.
-               // Ignore exclusions from the main module's go.mod.
-               const ignoreSelected = ""
-               var allowAll AllowedFunc
-               rev, err := Query(ctx, path, "latest", ignoreSelected, allowAll)
-               if err != nil {
-                       return &entry{nil, err}
-               }
-
-               // Load go.mod for that version.
-               // If the version is replaced, we'll load retractions from the replacement.
-               //
-               // If there's an error loading the go.mod, we'll return it here.
-               // These errors should generally be ignored by callers of checkRetractions,
-               // since they happen frequently when we're offline. These errors are not
-               // equivalent to ErrDisallowed, so they may be distinguished from
-               // retraction errors.
-               //
-               // We load the raw file here: the go.mod file may have a different module
-               // path that we expect if the module or its repository was renamed.
-               // We still want to apply retractions to other aliases of the module.
-               rm := module.Version{Path: path, Version: rev.Version}
-               if repl := Replacement(rm); repl.Path != "" {
-                       rm = repl
-               }
-               summary, err := rawGoModSummary(rm)
-               if err != nil {
-                       return &entry{nil, err}
-               }
-               return &entry{summary.retract, nil}
-       }).(*entry)
 
-       if err := e.err; err != nil {
-               // Attribute the error to the version being checked, not the version from
-               // which the retractions were to be loaded.
-               var mErr *module.ModuleError
-               if errors.As(err, &mErr) {
-                       err = mErr.Err
-               }
-               return &retractionLoadingError{m: m, err: err}
+       // Find the latest available version of the module, and load its go.mod. If
+       // the latest version is replaced, we'll load the replacement.
+       //
+       // If there's an error loading the go.mod, we'll return it here. These errors
+       // should generally be ignored by callers since they happen frequently when
+       // we're offline. These errors are not equivalent to ErrDisallowed, so they
+       // may be distinguished from retraction errors.
+       //
+       // We load the raw file here: the go.mod file may have a different module
+       // path that we expect if the module or its repository was renamed.
+       // We still want to apply retractions to other aliases of the module.
+       rm, err := queryLatestVersionIgnoringRetractions(ctx, m.Path)
+       if err != nil {
+               return err
+       }
+       summary, err := rawGoModSummary(rm)
+       if err != nil {
+               return err
        }
 
        var rationale []string
        isRetracted := false
-       for _, r := range e.retract {
+       for _, r := range summary.retract {
                if semver.Compare(r.Low, m.Version) <= 0 && semver.Compare(m.Version, r.High) <= 0 {
                        isRetracted = true
                        if r.Rationale != "" {
@@ -171,8 +212,6 @@ func CheckRetractions(ctx context.Context, m module.Version) error {
        return nil
 }
 
-var retractCache par.Cache
-
 type ModuleRetractedError struct {
        Rationale []string
 }
@@ -182,7 +221,7 @@ func (e *ModuleRetractedError) Error() string {
        if len(e.Rationale) > 0 {
                // This is meant to be a short error printed on a terminal, so just
                // print the first rationale.
-               msg += ": " + ShortRetractionRationale(e.Rationale[0])
+               msg += ": " + ShortMessage(e.Rationale[0], "retracted by module author")
        }
        return msg
 }
@@ -204,28 +243,67 @@ func (e *retractionLoadingError) Unwrap() error {
        return e.err
 }
 
-// ShortRetractionRationale returns a retraction rationale string that is safe
-// to print in a terminal. It returns hard-coded strings if the rationale
-// is empty, too long, or contains non-printable characters.
-func ShortRetractionRationale(rationale string) string {
-       const maxRationaleBytes = 500
-       if i := strings.Index(rationale, "\n"); i >= 0 {
-               rationale = rationale[:i]
-       }
-       rationale = strings.TrimSpace(rationale)
-       if rationale == "" {
-               return "retracted by module author"
-       }
-       if len(rationale) > maxRationaleBytes {
-               return "(rationale omitted: too long)"
-       }
-       for _, r := range rationale {
+// ShortMessage returns a string from go.mod (for example, a retraction
+// rationale or deprecation message) that is safe to print in a terminal.
+//
+// If the given string is empty, ShortMessage returns the given default. If the
+// given string is too long or contains non-printable characters, ShortMessage
+// returns a hard-coded string.
+func ShortMessage(message, emptyDefault string) string {
+       const maxLen = 500
+       if i := strings.Index(message, "\n"); i >= 0 {
+               message = message[:i]
+       }
+       message = strings.TrimSpace(message)
+       if message == "" {
+               return emptyDefault
+       }
+       if len(message) > maxLen {
+               return "(message omitted: too long)"
+       }
+       for _, r := range message {
                if !unicode.IsGraphic(r) && !unicode.IsSpace(r) {
-                       return "(rationale omitted: contains non-printable characters)"
+                       return "(message omitted: contains non-printable characters)"
                }
        }
        // NOTE: the go.mod parser rejects invalid UTF-8, so we don't check that here.
-       return rationale
+       return message
+}
+
+// CheckDeprecation returns a deprecation message from the go.mod file of the
+// latest version of the given module. Deprecation messages are comments
+// before or on the same line as the module directives that start with
+// "Deprecated:" and run until the end of the paragraph.
+//
+// CheckDeprecation returns an error if the message can't be loaded.
+// CheckDeprecation returns "", nil if there is no deprecation message.
+func CheckDeprecation(ctx context.Context, m module.Version) (deprecation string, err error) {
+       defer func() {
+               if err != nil {
+                       err = fmt.Errorf("loading deprecation for %s: %w", m.Path, err)
+               }
+       }()
+
+       if m.Version == "" {
+               // Main module, standard library, or file replacement module.
+               // Don't look up deprecation.
+               return "", nil
+       }
+       if repl := Replacement(module.Version{Path: m.Path}); repl.Path != "" {
+               // All versions of the module were replaced.
+               // We'll look up deprecation separately for the replacement.
+               return "", nil
+       }
+
+       latest, err := queryLatestVersionIgnoringRetractions(ctx, m.Path)
+       if err != nil {
+               return "", err
+       }
+       summary, err := rawGoModSummary(latest)
+       if err != nil {
+               return "", err
+       }
+       return summary.deprecated, nil
 }
 
 // Replacement returns the replacement for mod, if any, from go.mod.
@@ -243,6 +321,15 @@ func Replacement(mod module.Version) module.Version {
        return module.Version{}
 }
 
+// resolveReplacement returns the module actually used to load the source code
+// for m: either m itself, or the replacement for m (iff m is replaced).
+func resolveReplacement(m module.Version) module.Version {
+       if r := Replacement(m); r.Path != "" {
+               return r
+       }
+       return m
+}
+
 // indexModFile rebuilds the index of modFile.
 // If modFile has been changed since it was first read,
 // modFile.Cleanup must be called before indexModFile.
@@ -257,10 +344,13 @@ func indexModFile(data []byte, modFile *modfile.File, needsFix bool) *modFileInd
        }
 
        i.goVersionV = ""
-       if modFile.Go != nil {
+       if modFile.Go == nil {
+               rawGoVersion.Store(Target, "")
+       } else {
                // We're going to use the semver package to compare Go versions, so go ahead
                // and add the "v" prefix it expects once instead of every time.
                i.goVersionV = "v" + modFile.Go.Version
+               rawGoVersion.Store(Target, modFile.Go.Version)
        }
 
        i.require = make(map[module.Version]requireMeta, len(modFile.Require))
@@ -292,23 +382,6 @@ func indexModFile(data []byte, modFile *modfile.File, needsFix bool) *modFileInd
        return i
 }
 
-// allPatternClosesOverTests reports whether the "all" pattern includes
-// dependencies of tests outside the main module (as in Go 1.11–1.15).
-// (Otherwise — as in Go 1.16+ — the "all" pattern includes only the packages
-// transitively *imported by* the packages and tests in the main module.)
-func (i *modFileIndex) allPatternClosesOverTests() bool {
-       if !go116EnableNarrowAll {
-               return true
-       }
-       if i != nil && semver.Compare(i.goVersionV, narrowAllVersionV) < 0 {
-               // The module explicitly predates the change in "all" for lazy loading, so
-               // continue to use the older interpretation. (If i == nil, we not in any
-               // module at all and should use the latest semantics.)
-               return true
-       }
-       return false
-}
-
 // modFileIsDirty reports whether the go.mod file differs meaningfully
 // from what was indexed.
 // If modFile has been changed (even cosmetically) since it was first read,
@@ -335,7 +408,7 @@ func (i *modFileIndex) modFileIsDirty(modFile *modfile.File) bool {
                        return true
                }
        } else if "v"+modFile.Go.Version != i.goVersionV {
-               if i.goVersionV == "" && cfg.BuildMod == "readonly" {
+               if i.goVersionV == "" && cfg.BuildMod != "mod" {
                        // go.mod files did not always require a 'go' version, so do not error out
                        // if one is missing — we may be inside an older module in the module
                        // cache, and should bias toward providing useful behavior.
@@ -391,9 +464,11 @@ var rawGoVersion sync.Map // map[module.Version]string
 // module.
 type modFileSummary struct {
        module     module.Version
-       goVersionV string // GoVersion with "v" prefix
+       goVersion  string
+       depth      modDepth
        require    []module.Version
        retract    []retraction
+       deprecated string
 }
 
 // A retraction consists of a retracted version interval and rationale.
@@ -433,19 +508,13 @@ func goModSummary(m module.Version) (*modFileSummary, error) {
                // return the full list of modules from modules.txt.
                readVendorList()
 
-               // TODO(#36876): Load the "go" version from vendor/modules.txt and store it
-               // in rawGoVersion with the appropriate key.
-
                // We don't know what versions the vendored module actually relies on,
                // so assume that it requires everything.
                summary.require = vendorList
                return summary, nil
        }
 
-       actual := Replacement(m)
-       if actual.Path == "" {
-               actual = m
-       }
+       actual := resolveReplacement(m)
        if HasModRoot() && cfg.BuildMod == "readonly" && actual.Version != "" {
                key := module.Version{Path: actual.Path, Version: actual.Version + "/go.mod"}
                if !modfetch.HaveSum(key) {
@@ -526,45 +595,24 @@ func rawGoModSummary(m module.Version) (*modFileSummary, error) {
        }
        c := rawGoModSummaryCache.Do(m, func() interface{} {
                summary := new(modFileSummary)
-               var f *modfile.File
-               if m.Version == "" {
-                       // m is a replacement module with only a file path.
-                       dir := m.Path
-                       if !filepath.IsAbs(dir) {
-                               dir = filepath.Join(ModRoot(), dir)
-                       }
-                       gomod := filepath.Join(dir, "go.mod")
-
-                       data, err := lockedfile.Read(gomod)
-                       if err != nil {
-                               return cached{nil, module.VersionError(m, fmt.Errorf("reading %s: %v", base.ShortPath(gomod), err))}
-                       }
-                       f, err = modfile.ParseLax(gomod, data, nil)
-                       if err != nil {
-                               return cached{nil, module.VersionError(m, fmt.Errorf("parsing %s: %v", base.ShortPath(gomod), err))}
-                       }
-               } else {
-                       if !semver.IsValid(m.Version) {
-                               // Disallow the broader queries supported by fetch.Lookup.
-                               base.Fatalf("go: internal error: %s@%s: unexpected invalid semantic version", m.Path, m.Version)
-                       }
-
-                       data, err := modfetch.GoMod(m.Path, m.Version)
-                       if err != nil {
-                               return cached{nil, err}
-                       }
-                       f, err = modfile.ParseLax("go.mod", data, nil)
-                       if err != nil {
-                               return cached{nil, module.VersionError(m, fmt.Errorf("parsing go.mod: %v", err))}
-                       }
+               name, data, err := rawGoModData(m)
+               if err != nil {
+                       return cached{nil, err}
+               }
+               f, err := modfile.ParseLax(name, data, nil)
+               if err != nil {
+                       return cached{nil, module.VersionError(m, fmt.Errorf("parsing %s: %v", base.ShortPath(name), err))}
                }
-
                if f.Module != nil {
                        summary.module = f.Module.Mod
+                       summary.deprecated = f.Module.Deprecated
                }
                if f.Go != nil && f.Go.Version != "" {
                        rawGoVersion.LoadOrStore(m, f.Go.Version)
-                       summary.goVersionV = "v" + f.Go.Version
+                       summary.goVersion = f.Go.Version
+                       summary.depth = modDepthFromGoVersion(f.Go.Version)
+               } else {
+                       summary.depth = eager
                }
                if len(f.Require) > 0 {
                        summary.require = make([]module.Version, 0, len(f.Require))
@@ -589,3 +637,84 @@ func rawGoModSummary(m module.Version) (*modFileSummary, error) {
 }
 
 var rawGoModSummaryCache par.Cache // module.Version → rawGoModSummary result
+
+// rawGoModData returns the content of the go.mod file for module m, ignoring
+// all replacements that may apply to m.
+//
+// rawGoModData cannot be used on the Target module.
+//
+// Unlike rawGoModSummary, rawGoModData does not cache its results in memory.
+// Use rawGoModSummary instead unless you specifically need these bytes.
+func rawGoModData(m module.Version) (name string, data []byte, err error) {
+       if m.Version == "" {
+               // m is a replacement module with only a file path.
+               dir := m.Path
+               if !filepath.IsAbs(dir) {
+                       dir = filepath.Join(ModRoot(), dir)
+               }
+               name = filepath.Join(dir, "go.mod")
+               if gomodActual, ok := fsys.OverlayPath(name); ok {
+                       // Don't lock go.mod if it's part of the overlay.
+                       // On Plan 9, locking requires chmod, and we don't want to modify any file
+                       // in the overlay. See #44700.
+                       data, err = os.ReadFile(gomodActual)
+               } else {
+                       data, err = lockedfile.Read(gomodActual)
+               }
+               if err != nil {
+                       return "", nil, module.VersionError(m, fmt.Errorf("reading %s: %v", base.ShortPath(name), err))
+               }
+       } else {
+               if !semver.IsValid(m.Version) {
+                       // Disallow the broader queries supported by fetch.Lookup.
+                       base.Fatalf("go: internal error: %s@%s: unexpected invalid semantic version", m.Path, m.Version)
+               }
+               name = "go.mod"
+               data, err = modfetch.GoMod(m.Path, m.Version)
+       }
+       return name, data, err
+}
+
+// queryLatestVersionIgnoringRetractions looks up the latest version of the
+// module with the given path without considering retracted or excluded
+// versions.
+//
+// If all versions of the module are replaced,
+// queryLatestVersionIgnoringRetractions returns the replacement without making
+// a query.
+//
+// If the queried latest version is replaced,
+// queryLatestVersionIgnoringRetractions returns the replacement.
+func queryLatestVersionIgnoringRetractions(ctx context.Context, path string) (latest module.Version, err error) {
+       type entry struct {
+               latest module.Version
+               err    error
+       }
+       e := latestVersionIgnoringRetractionsCache.Do(path, func() interface{} {
+               ctx, span := trace.StartSpan(ctx, "queryLatestVersionIgnoringRetractions "+path)
+               defer span.Done()
+
+               if repl := Replacement(module.Version{Path: path}); repl.Path != "" {
+                       // All versions of the module were replaced.
+                       // No need to query.
+                       return &entry{latest: repl}
+               }
+
+               // Find the latest version of the module.
+               // Ignore exclusions from the main module's go.mod.
+               const ignoreSelected = ""
+               var allowAll AllowedFunc
+               rev, err := Query(ctx, path, "latest", ignoreSelected, allowAll)
+               if err != nil {
+                       return &entry{err: err}
+               }
+               latest := module.Version{Path: path, Version: rev.Version}
+               if repl := resolveReplacement(latest); repl.Path != "" {
+                       latest = repl
+               }
+               return &entry{latest: latest}
+       }).(*entry)
+       return e.latest, e.err
+}
+
+var latestVersionIgnoringRetractionsCache par.Cache // path → queryLatestVersionIgnoringRetractions result
index 31015194f9a0192b055615bd8619b0b7a6249c7e..87619b4ace68e28d40621054ab4d437a4b97cf83 100644 (file)
@@ -16,17 +16,36 @@ import (
        "golang.org/x/mod/semver"
 )
 
+// cmpVersion implements the comparison for versions in the module loader.
+//
+// It is consistent with semver.Compare except that as a special case,
+// the version "" is considered higher than all other versions.
+// The main module (also known as the target) has no version and must be chosen
+// over other versions of the same module in the module dependency graph.
+func cmpVersion(v1, v2 string) int {
+       if v2 == "" {
+               if v1 == "" {
+                       return 0
+               }
+               return -1
+       }
+       if v1 == "" {
+               return 1
+       }
+       return semver.Compare(v1, v2)
+}
+
 // mvsReqs implements mvs.Reqs for module semantic versions,
 // with any exclusions or replacements applied internally.
 type mvsReqs struct {
-       buildList []module.Version
+       roots []module.Version
 }
 
 func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) {
        if mod == Target {
                // Use the build list as it existed when r was constructed, not the current
                // global build list.
-               return r.buildList[1:], nil
+               return r.roots, nil
        }
 
        if mod.Version == "none" {
@@ -47,7 +66,7 @@ func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) {
 // be chosen over other versions of the same module in the module dependency
 // graph.
 func (*mvsReqs) Max(v1, v2 string) string {
-       if v1 != "" && (v2 == "" || semver.Compare(v1, v2) == -1) {
+       if cmpVersion(v1, v2) < 0 {
                return v2
        }
        return v1
@@ -86,12 +105,12 @@ func versions(ctx context.Context, path string, allowed AllowedFunc) ([]string,
        return versions, err
 }
 
-// Previous returns the tagged version of m.Path immediately prior to
+// previousVersion returns the tagged version of m.Path immediately prior to
 // m.Version, or version "none" if no prior version is tagged.
 //
 // Since the version of Target is not found in the version list,
 // it has no previous version.
-func (*mvsReqs) Previous(m module.Version) (module.Version, error) {
+func previousVersion(m module.Version) (module.Version, error) {
        // TODO(golang.org/issue/38714): thread tracing context through MVS.
 
        if m == Target {
@@ -111,3 +130,7 @@ func (*mvsReqs) Previous(m module.Version) (module.Version, error) {
        }
        return module.Version{Path: m.Path, Version: "none"}, nil
 }
+
+func (*mvsReqs) Previous(m module.Version) (module.Version, error) {
+       return previousVersion(m)
+}
index 8affd179bb2e9c0b1d51fec1b3b2bd80e2254017..e737ca90fcd79d911f741b7fc43e1aa663b97d4b 100644 (file)
@@ -5,13 +5,13 @@
 package modload
 
 import (
+       "bytes"
        "context"
        "errors"
        "fmt"
        "io/fs"
        "os"
        pathpkg "path"
-       "path/filepath"
        "sort"
        "strings"
        "sync"
@@ -177,7 +177,7 @@ func queryProxy(ctx context.Context, proxy, path, query, current string, allowed
                        return nil, err
                }
 
-               if (query == "upgrade" || query == "patch") && modfetch.IsPseudoVersion(current) && !rev.Time.IsZero() {
+               if (query == "upgrade" || query == "patch") && module.IsPseudoVersion(current) && !rev.Time.IsZero() {
                        // Don't allow "upgrade" or "patch" to move from a pseudo-version
                        // to a chronologically older version or pseudo-version.
                        //
@@ -196,7 +196,7 @@ func queryProxy(ctx context.Context, proxy, path, query, current string, allowed
                        // newer but v1.1.0 is still an “upgrade”; or v1.0.2 might be a revert of
                        // an unsuccessful fix in v1.0.1, in which case the v1.0.2 commit may be
                        // older than the v1.0.1 commit despite the tag itself being newer.)
-                       currentTime, err := modfetch.PseudoVersionTime(current)
+                       currentTime, err := module.PseudoVersionTime(current)
                        if err == nil && rev.Time.Before(currentTime) {
                                if err := allowed(ctx, module.Version{Path: path, Version: current}); errors.Is(err, ErrDisallowed) {
                                        return nil, err
@@ -325,18 +325,18 @@ func newQueryMatcher(path string, query, current string, allowed AllowedFunc) (*
                if current == "" || current == "none" {
                        qm.mayUseLatest = true
                } else {
-                       qm.mayUseLatest = modfetch.IsPseudoVersion(current)
+                       qm.mayUseLatest = module.IsPseudoVersion(current)
                        qm.filter = func(mv string) bool { return semver.Compare(mv, current) >= 0 }
                }
 
        case query == "patch":
-               if current == "none" {
+               if current == "" || current == "none" {
                        return nil, &NoPatchBaseError{path}
                }
                if current == "" {
                        qm.mayUseLatest = true
                } else {
-                       qm.mayUseLatest = modfetch.IsPseudoVersion(current)
+                       qm.mayUseLatest = module.IsPseudoVersion(current)
                        qm.prefix = semver.MajorMinor(current) + "."
                        qm.filter = func(mv string) bool { return semver.Compare(mv, current) >= 0 }
                }
@@ -695,7 +695,9 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin
 
 // modulePrefixesExcludingTarget returns all prefixes of path that may plausibly
 // exist as a module, excluding targetPrefix but otherwise including path
-// itself, sorted by descending length.
+// itself, sorted by descending length. Prefixes that are not valid module paths
+// but are valid package paths (like "m" or "example.com/.gen") are included,
+// since they might be replaced.
 func modulePrefixesExcludingTarget(path string) []string {
        prefixes := make([]string, 0, strings.Count(path, "/")+1)
 
@@ -747,6 +749,7 @@ func queryPrefixModules(ctx context.Context, candidateModules []string, queryMod
                noPackage   *PackageNotInModuleError
                noVersion   *NoMatchingVersionError
                noPatchBase *NoPatchBaseError
+               invalidPath *module.InvalidPathError // see comment in case below
                notExistErr error
        )
        for _, r := range results {
@@ -767,6 +770,17 @@ func queryPrefixModules(ctx context.Context, candidateModules []string, queryMod
                        if noPatchBase == nil {
                                noPatchBase = rErr
                        }
+               case *module.InvalidPathError:
+                       // The prefix was not a valid module path, and there was no replacement.
+                       // Prefixes like this may appear in candidateModules, since we handle
+                       // replaced modules that weren't required in the repo lookup process
+                       // (see lookupRepo).
+                       //
+                       // A shorter prefix may be a valid module path and may contain a valid
+                       // import path, so this is a low-priority error.
+                       if invalidPath == nil {
+                               invalidPath = rErr
+                       }
                default:
                        if errors.Is(rErr, fs.ErrNotExist) {
                                if notExistErr == nil {
@@ -800,6 +814,8 @@ func queryPrefixModules(ctx context.Context, candidateModules []string, queryMod
                        err = noVersion
                case noPatchBase != nil:
                        err = noPatchBase
+               case invalidPath != nil:
+                       err = invalidPath
                case notExistErr != nil:
                        err = notExistErr
                default:
@@ -904,8 +920,8 @@ func (e *PackageNotInModuleError) ImportPath() string {
        return ""
 }
 
-// ModuleHasRootPackage returns whether module m contains a package m.Path.
-func ModuleHasRootPackage(ctx context.Context, m module.Version) (bool, error) {
+// moduleHasRootPackage returns whether module m contains a package m.Path.
+func moduleHasRootPackage(ctx context.Context, m module.Version) (bool, error) {
        needSum := false
        root, isLocal, err := fetch(ctx, m, needSum)
        if err != nil {
@@ -915,14 +931,32 @@ func ModuleHasRootPackage(ctx context.Context, m module.Version) (bool, error) {
        return ok, err
 }
 
-func versionHasGoMod(ctx context.Context, m module.Version) (bool, error) {
-       needSum := false
-       root, _, err := fetch(ctx, m, needSum)
+// versionHasGoMod returns whether a version has a go.mod file.
+//
+// versionHasGoMod fetches the go.mod file (possibly a fake) and true if it
+// contains anything other than a module directive with the same path. When a
+// module does not have a real go.mod file, the go command acts as if it had one
+// that only contained a module directive. Normal go.mod files created after
+// 1.12 at least have a go directive.
+//
+// This function is a heuristic, since it's possible to commit a file that would
+// pass this test. However, we only need a heurstic for determining whether
+// +incompatible versions may be "latest", which is what this function is used
+// for.
+//
+// This heuristic is useful for two reasons: first, when using a proxy,
+// this lets us fetch from the .mod endpoint which is much faster than the .zip
+// endpoint. The .mod file is used anyway, even if the .zip file contains a
+// go.mod with different content. Second, if we don't fetch the .zip, then
+// we don't need to verify it in go.sum. This makes 'go list -m -u' faster
+// and simpler.
+func versionHasGoMod(_ context.Context, m module.Version) (bool, error) {
+       _, data, err := rawGoModData(m)
        if err != nil {
                return false, err
        }
-       fi, err := os.Stat(filepath.Join(root, "go.mod"))
-       return err == nil && !fi.IsDir(), nil
+       isFake := bytes.Equal(data, modfetch.LegacyGoMod(m.Path))
+       return !isFake, nil
 }
 
 // A versionRepo is a subset of modfetch.Repo that can report information about
@@ -993,7 +1027,7 @@ func (rr *replacementRepo) Versions(prefix string) ([]string, error) {
        if index != nil && len(index.replace) > 0 {
                path := rr.ModulePath()
                for m, _ := range index.replace {
-                       if m.Path == path && strings.HasPrefix(m.Version, prefix) && m.Version != "" && !modfetch.IsPseudoVersion(m.Version) {
+                       if m.Path == path && strings.HasPrefix(m.Version, prefix) && m.Version != "" && !module.IsPseudoVersion(m.Version) {
                                versions = append(versions, m.Version)
                        }
                }
@@ -1050,9 +1084,9 @@ func (rr *replacementRepo) Latest() (*modfetch.RevInfo, error) {
                                // used from within some other module, the user will be able to upgrade
                                // the requirement to any real version they choose.
                                if _, pathMajor, ok := module.SplitPathVersion(path); ok && len(pathMajor) > 0 {
-                                       v = modfetch.PseudoVersion(pathMajor[1:], "", time.Time{}, "000000000000")
+                                       v = module.PseudoVersion(pathMajor[1:], "", time.Time{}, "000000000000")
                                } else {
-                                       v = modfetch.PseudoVersion("v0", "", time.Time{}, "000000000000")
+                                       v = module.PseudoVersion("v0", "", time.Time{}, "000000000000")
                                }
                        }
 
@@ -1067,9 +1101,9 @@ func (rr *replacementRepo) Latest() (*modfetch.RevInfo, error) {
 
 func (rr *replacementRepo) replacementStat(v string) (*modfetch.RevInfo, error) {
        rev := &modfetch.RevInfo{Version: v}
-       if modfetch.IsPseudoVersion(v) {
-               rev.Time, _ = modfetch.PseudoVersionTime(v)
-               rev.Short, _ = modfetch.PseudoVersionRev(v)
+       if module.IsPseudoVersion(v) {
+               rev.Time, _ = module.PseudoVersionTime(v)
+               rev.Short, _ = module.PseudoVersionRev(v)
        }
        return rev, nil
 }
index e225a0e71e7eb2ec34b549cb9e37d7b1e9821c46..a3f2f84505a0f996d48aa6bb91937e63c33ff097 100644 (file)
@@ -106,7 +106,7 @@ var queryTests = []struct {
        {path: queryRepo, query: "v1.9.10-pre2+metadata", vers: "v1.9.10-pre2.0.20190513201126-42abcb6df8ee"},
        {path: queryRepo, query: "ed5ffdaa", vers: "v1.9.10-pre2.0.20191220134614-ed5ffdaa1f5e"},
 
-       // golang.org/issue/29262: The major version for for a module without a suffix
+       // golang.org/issue/29262: The major version for a module without a suffix
        // should be based on the most recent tag (v1 as appropriate, not v0
        // unconditionally).
        {path: queryRepo, query: "42abcb6df8ee", vers: "v1.9.10-pre2.0.20190513201126-42abcb6df8ee"},
@@ -122,7 +122,7 @@ var queryTests = []struct {
        {path: queryRepo, query: "upgrade", allow: "NOMATCH", err: `no matching versions for query "upgrade"`},
        {path: queryRepo, query: "upgrade", current: "v1.9.9", allow: "NOMATCH", err: `vcs-test.golang.org/git/querytest.git@v1.9.9: disallowed module version`},
        {path: queryRepo, query: "upgrade", current: "v1.99.99", err: `vcs-test.golang.org/git/querytest.git@v1.99.99: invalid version: unknown revision v1.99.99`},
-       {path: queryRepo, query: "patch", current: "", vers: "v1.9.9"},
+       {path: queryRepo, query: "patch", current: "", err: `can't query version "patch" of module vcs-test.golang.org/git/querytest.git: no existing version is required`},
        {path: queryRepo, query: "patch", current: "v0.1.0", vers: "v0.1.2"},
        {path: queryRepo, query: "patch", current: "v1.9.0", vers: "v1.9.9"},
        {path: queryRepo, query: "patch", current: "v1.9.10-pre1", vers: "v1.9.10-pre1"},
index 4c73c783603c1b4ab731c37a3c38da7a061fa5fa..0c2e2660e9fc1c0a4e34f20f9274216f3f723236 100644 (file)
@@ -87,7 +87,7 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f
                        }
 
                        if !fi.IsDir() {
-                               if fi.Mode()&fs.ModeSymlink != 0 && want {
+                               if fi.Mode()&fs.ModeSymlink != 0 && want && strings.Contains(m.Pattern(), "...") {
                                        if target, err := fsys.Stat(path); err == nil && target.IsDir() {
                                                fmt.Fprintf(os.Stderr, "warning: ignoring symlink %s\n", path)
                                        }
@@ -188,7 +188,7 @@ func MatchInModule(ctx context.Context, pattern string, m module.Version, tags m
                matchPackages(ctx, match, tags, includeStd, nil)
        }
 
-       LoadModFile(ctx)
+       LoadModFile(ctx) // Sets Target, needed by fetch and matchPackages.
 
        if !match.IsLiteral() {
                matchPackages(ctx, match, tags, omitStd, []module.Version{m})
index 5842b858f0b1a48a1b2b78b404a574cabf6d58da..368f893198492984b0cc1efaffe988d5f172c5d5 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build (js && wasm) || plan9
 // +build js,wasm plan9
 
 // On plan9, per http://9p.io/magic/man2html/2/access: “Since file permissions
index 032fff8714222ff71c3001b1a7f46cd7e0a7bfac..f5f7ce3e03df4627f34fc4fc0d69d75994bdd4d7 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package modload
index 0ac23913475beab944be2a70ecaa3202e165b8ec..825e60b27af89406122aa400b92df706aba508d5 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build windows
 // +build windows
 
 package modload
index d8fd91f1fea2b20339b4c2f61a1a77f5da6ab15f..80713b0812eacce928f0a39b26eba024e655a56b 100644 (file)
@@ -31,6 +31,7 @@ var (
 type vendorMetadata struct {
        Explicit    bool
        Replacement module.Version
+       GoVersion   string
 }
 
 // readVendorList reads the list of vendored modules from vendor/modules.txt.
@@ -104,6 +105,10 @@ func readVendorList() {
                                        if entry == "explicit" {
                                                meta.Explicit = true
                                        }
+                                       if strings.HasPrefix(entry, "go ") {
+                                               meta.GoVersion = strings.TrimPrefix(entry, "go ")
+                                               rawGoVersion.Store(mod, meta.GoVersion)
+                                       }
                                        // All other tokens are reserved for future use.
                                }
                                vendorMeta[mod] = meta
index 5564965fb51675a33dfd7c303efbacd1009fecda..bf183cea9e88af62b0b8d773297f432bae740b84 100644 (file)
@@ -31,13 +31,15 @@ type buildListErrorElem struct {
 // occurred at a module found along the given path of requirements and/or
 // upgrades, which must be non-empty.
 //
-// The isUpgrade function reports whether a path step is due to an upgrade.
-// A nil isUpgrade function indicates that none of the path steps are due to upgrades.
-func NewBuildListError(err error, path []module.Version, isUpgrade func(from, to module.Version) bool) *BuildListError {
+// The isVersionChange function reports whether a path step is due to an
+// explicit upgrade or downgrade (as opposed to an existing requirement in a
+// go.mod file). A nil isVersionChange function indicates that none of the path
+// steps are due to explicit version changes.
+func NewBuildListError(err error, path []module.Version, isVersionChange func(from, to module.Version) bool) *BuildListError {
        stack := make([]buildListErrorElem, 0, len(path))
        for len(path) > 1 {
                reason := "requires"
-               if isUpgrade != nil && isUpgrade(path[0], path[1]) {
+               if isVersionChange != nil && isVersionChange(path[0], path[1]) {
                        reason = "updating to"
                }
                stack = append(stack, buildListErrorElem{
diff --git a/libgo/go/cmd/go/internal/mvs/graph.go b/libgo/go/cmd/go/internal/mvs/graph.go
new file mode 100644 (file)
index 0000000..c5de486
--- /dev/null
@@ -0,0 +1,223 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package mvs
+
+import (
+       "fmt"
+
+       "golang.org/x/mod/module"
+)
+
+// Graph implements an incremental version of the MVS algorithm, with the
+// requirements pushed by the caller instead of pulled by the MVS traversal.
+type Graph struct {
+       cmp   func(v1, v2 string) int
+       roots []module.Version
+
+       required map[module.Version][]module.Version
+
+       isRoot   map[module.Version]bool // contains true for roots and false for reachable non-roots
+       selected map[string]string       // path → version
+}
+
+// NewGraph returns an incremental MVS graph containing only a set of root
+// dependencies and using the given max function for version strings.
+//
+// The caller must ensure that the root slice is not modified while the Graph
+// may be in use.
+func NewGraph(cmp func(v1, v2 string) int, roots []module.Version) *Graph {
+       g := &Graph{
+               cmp:      cmp,
+               roots:    roots[:len(roots):len(roots)],
+               required: make(map[module.Version][]module.Version),
+               isRoot:   make(map[module.Version]bool),
+               selected: make(map[string]string),
+       }
+
+       for _, m := range roots {
+               g.isRoot[m] = true
+               if g.cmp(g.Selected(m.Path), m.Version) < 0 {
+                       g.selected[m.Path] = m.Version
+               }
+       }
+
+       return g
+}
+
+// Require adds the information that module m requires all modules in reqs.
+// The reqs slice must not be modified after it is passed to Require.
+//
+// m must be reachable by some existing chain of requirements from g's target,
+// and Require must not have been called for it already.
+//
+// If any of the modules in reqs has the same path as g's target,
+// the target must have higher precedence than the version in req.
+func (g *Graph) Require(m module.Version, reqs []module.Version) {
+       // To help catch disconnected-graph bugs, enforce that all required versions
+       // are actually reachable from the roots (and therefore should affect the
+       // selected versions of the modules they name).
+       if _, reachable := g.isRoot[m]; !reachable {
+               panic(fmt.Sprintf("%v is not reachable from any root", m))
+       }
+
+       // Truncate reqs to its capacity to avoid aliasing bugs if it is later
+       // returned from RequiredBy and appended to.
+       reqs = reqs[:len(reqs):len(reqs)]
+
+       if _, dup := g.required[m]; dup {
+               panic(fmt.Sprintf("requirements of %v have already been set", m))
+       }
+       g.required[m] = reqs
+
+       for _, dep := range reqs {
+               // Mark dep reachable, regardless of whether it is selected.
+               if _, ok := g.isRoot[dep]; !ok {
+                       g.isRoot[dep] = false
+               }
+
+               if g.cmp(g.Selected(dep.Path), dep.Version) < 0 {
+                       g.selected[dep.Path] = dep.Version
+               }
+       }
+}
+
+// RequiredBy returns the slice of requirements passed to Require for m, if any,
+// with its capacity reduced to its length.
+// If Require has not been called for m, RequiredBy(m) returns ok=false.
+//
+// The caller must not modify the returned slice, but may safely append to it
+// and may rely on it not to be modified.
+func (g *Graph) RequiredBy(m module.Version) (reqs []module.Version, ok bool) {
+       reqs, ok = g.required[m]
+       return reqs, ok
+}
+
+// Selected returns the selected version of the given module path.
+//
+// If no version is selected, Selected returns version "none".
+func (g *Graph) Selected(path string) (version string) {
+       v, ok := g.selected[path]
+       if !ok {
+               return "none"
+       }
+       return v
+}
+
+// BuildList returns the selected versions of all modules present in the Graph,
+// beginning with the selected versions of each module path in the roots of g.
+//
+// The order of the remaining elements in the list is deterministic
+// but arbitrary.
+func (g *Graph) BuildList() []module.Version {
+       seenRoot := make(map[string]bool, len(g.roots))
+
+       var list []module.Version
+       for _, r := range g.roots {
+               if seenRoot[r.Path] {
+                       // Multiple copies of the same root, with the same or different versions,
+                       // are a bit of a degenerate case: we will take the transitive
+                       // requirements of both roots into account, but only the higher one can
+                       // possibly be selected. However — especially given that we need the
+                       // seenRoot map for later anyway — it is simpler to support this
+                       // degenerate case than to forbid it.
+                       continue
+               }
+
+               if v := g.Selected(r.Path); v != "none" {
+                       list = append(list, module.Version{Path: r.Path, Version: v})
+               }
+               seenRoot[r.Path] = true
+       }
+       uniqueRoots := list
+
+       for path, version := range g.selected {
+               if !seenRoot[path] {
+                       list = append(list, module.Version{Path: path, Version: version})
+               }
+       }
+       module.Sort(list[len(uniqueRoots):])
+
+       return list
+}
+
+// WalkBreadthFirst invokes f once, in breadth-first order, for each module
+// version other than "none" that appears in the graph, regardless of whether
+// that version is selected.
+func (g *Graph) WalkBreadthFirst(f func(m module.Version)) {
+       var queue []module.Version
+       enqueued := make(map[module.Version]bool)
+       for _, m := range g.roots {
+               if m.Version != "none" {
+                       queue = append(queue, m)
+                       enqueued[m] = true
+               }
+       }
+
+       for len(queue) > 0 {
+               m := queue[0]
+               queue = queue[1:]
+
+               f(m)
+
+               reqs, _ := g.RequiredBy(m)
+               for _, r := range reqs {
+                       if !enqueued[r] && r.Version != "none" {
+                               queue = append(queue, r)
+                               enqueued[r] = true
+                       }
+               }
+       }
+}
+
+// FindPath reports a shortest requirement path starting at one of the roots of
+// the graph and ending at a module version m for which f(m) returns true, or
+// nil if no such path exists.
+func (g *Graph) FindPath(f func(module.Version) bool) []module.Version {
+       // firstRequires[a] = b means that in a breadth-first traversal of the
+       // requirement graph, the module version a was first required by b.
+       firstRequires := make(map[module.Version]module.Version)
+
+       queue := g.roots
+       for _, m := range g.roots {
+               firstRequires[m] = module.Version{}
+       }
+
+       for len(queue) > 0 {
+               m := queue[0]
+               queue = queue[1:]
+
+               if f(m) {
+                       // Construct the path reversed (because we're starting from the far
+                       // endpoint), then reverse it.
+                       path := []module.Version{m}
+                       for {
+                               m = firstRequires[m]
+                               if m.Path == "" {
+                                       break
+                               }
+                               path = append(path, m)
+                       }
+
+                       i, j := 0, len(path)-1
+                       for i < j {
+                               path[i], path[j] = path[j], path[i]
+                               i++
+                               j--
+                       }
+
+                       return path
+               }
+
+               reqs, _ := g.RequiredBy(m)
+               for _, r := range reqs {
+                       if _, seen := firstRequires[r]; !seen {
+                               queue = append(queue, r)
+                               firstRequires[r] = m
+                       }
+               }
+       }
+
+       return nil
+}
index b630b610f10e03641362acf7b385f34781e58cf5..6969f90f2e681abf23495ab7aab8ba4432453d17 100644 (file)
@@ -10,7 +10,6 @@ import (
        "fmt"
        "sort"
        "sync"
-       "sync/atomic"
 
        "cmd/go/internal/par"
 
@@ -41,6 +40,11 @@ type Reqs interface {
        // Note that v1 < v2 can be written Max(v1, v2) != v1
        // and similarly v1 <= v2 can be written Max(v1, v2) == v2.
        Max(v1, v2 string) string
+}
+
+// An UpgradeReqs is a Reqs that can also identify available upgrades.
+type UpgradeReqs interface {
+       Reqs
 
        // Upgrade returns the upgraded version of m,
        // for use during an UpgradeAll operation.
@@ -54,6 +58,11 @@ type Reqs interface {
        // TODO(rsc): Upgrade must be able to return errors,
        // but should "no latest version" just return m instead?
        Upgrade(m module.Version) (module.Version, error)
+}
+
+// A DowngradeReqs is a Reqs that can also identify available downgrades.
+type DowngradeReqs interface {
+       Reqs
 
        // Previous returns the version of m.Path immediately prior to m.Version,
        // or "none" if no such version is known.
@@ -81,151 +90,91 @@ func BuildList(target module.Version, reqs Reqs) ([]module.Version, error) {
 }
 
 func buildList(target module.Version, reqs Reqs, upgrade func(module.Version) (module.Version, error)) ([]module.Version, error) {
-       // Explore work graph in parallel in case reqs.Required
-       // does high-latency network operations.
-       type modGraphNode struct {
-               m        module.Version
-               required []module.Version
-               upgrade  module.Version
-               err      error
+       cmp := func(v1, v2 string) int {
+               if reqs.Max(v1, v2) != v1 {
+                       return -1
+               }
+               if reqs.Max(v2, v1) != v2 {
+                       return 1
+               }
+               return 0
        }
+
        var (
                mu       sync.Mutex
-               modGraph = map[module.Version]*modGraphNode{}
-               min      = map[string]string{} // maps module path to minimum required version
-               haveErr  int32
+               g        = NewGraph(cmp, []module.Version{target})
+               upgrades = map[module.Version]module.Version{}
+               errs     = map[module.Version]error{} // (non-nil errors only)
        )
-       setErr := func(n *modGraphNode, err error) {
-               n.err = err
-               atomic.StoreInt32(&haveErr, 1)
-       }
 
+       // Explore work graph in parallel in case reqs.Required
+       // does high-latency network operations.
        var work par.Work
        work.Add(target)
        work.Do(10, func(item interface{}) {
                m := item.(module.Version)
 
-               node := &modGraphNode{m: m}
-               mu.Lock()
-               modGraph[m] = node
+               var required []module.Version
+               var err error
                if m.Version != "none" {
-                       if v, ok := min[m.Path]; !ok || reqs.Max(v, m.Version) != v {
-                               min[m.Path] = m.Version
-                       }
+                       required, err = reqs.Required(m)
                }
-               mu.Unlock()
 
-               if m.Version != "none" {
-                       required, err := reqs.Required(m)
-                       if err != nil {
-                               setErr(node, err)
-                               return
-                       }
-                       node.required = required
-                       for _, r := range node.required {
-                               work.Add(r)
+               u := m
+               if upgrade != nil {
+                       upgradeTo, upErr := upgrade(m)
+                       if upErr == nil {
+                               u = upgradeTo
+                       } else if err == nil {
+                               err = upErr
                        }
                }
 
-               if upgrade != nil {
-                       u, err := upgrade(m)
-                       if err != nil {
-                               setErr(node, err)
-                               return
-                       }
-                       if u != m {
-                               node.upgrade = u
-                               work.Add(u)
-                       }
+               mu.Lock()
+               if err != nil {
+                       errs[m] = err
+               }
+               if u != m {
+                       upgrades[m] = u
+                       required = append([]module.Version{u}, required...)
+               }
+               g.Require(m, required)
+               mu.Unlock()
+
+               for _, r := range required {
+                       work.Add(r)
                }
        })
 
        // If there was an error, find the shortest path from the target to the
        // node where the error occurred so we can report a useful error message.
-       if haveErr != 0 {
-               // neededBy[a] = b means a was added to the module graph by b.
-               neededBy := make(map[*modGraphNode]*modGraphNode)
-               q := make([]*modGraphNode, 0, len(modGraph))
-               q = append(q, modGraph[target])
-               for len(q) > 0 {
-                       node := q[0]
-                       q = q[1:]
-
-                       if node.err != nil {
-                               pathUpgrade := map[module.Version]module.Version{}
-
-                               // Construct the error path reversed (from the error to the main module),
-                               // then reverse it to obtain the usual order (from the main module to
-                               // the error).
-                               errPath := []module.Version{node.m}
-                               for n, prev := neededBy[node], node; n != nil; n, prev = neededBy[n], n {
-                                       if n.upgrade == prev.m {
-                                               pathUpgrade[n.m] = prev.m
-                                       }
-                                       errPath = append(errPath, n.m)
-                               }
-                               i, j := 0, len(errPath)-1
-                               for i < j {
-                                       errPath[i], errPath[j] = errPath[j], errPath[i]
-                                       i++
-                                       j--
-                               }
-
-                               isUpgrade := func(from, to module.Version) bool {
-                                       return pathUpgrade[from] == to
-                               }
-
-                               return nil, NewBuildListError(node.err, errPath, isUpgrade)
-                       }
+       if len(errs) > 0 {
+               errPath := g.FindPath(func(m module.Version) bool {
+                       return errs[m] != nil
+               })
+               if len(errPath) == 0 {
+                       panic("internal error: could not reconstruct path to module with error")
+               }
 
-                       neighbors := node.required
-                       if node.upgrade.Path != "" {
-                               neighbors = append(neighbors, node.upgrade)
-                       }
-                       for _, neighbor := range neighbors {
-                               nn := modGraph[neighbor]
-                               if neededBy[nn] != nil {
-                                       continue
-                               }
-                               neededBy[nn] = node
-                               q = append(q, nn)
+               err := errs[errPath[len(errPath)-1]]
+               isUpgrade := func(from, to module.Version) bool {
+                       if u, ok := upgrades[from]; ok {
+                               return u == to
                        }
+                       return false
                }
+               return nil, NewBuildListError(err.(error), errPath, isUpgrade)
        }
 
        // The final list is the minimum version of each module found in the graph.
-
-       if v := min[target.Path]; v != target.Version {
+       list := g.BuildList()
+       if v := list[0]; v != target {
                // target.Version will be "" for modload, the main client of MVS.
                // "" denotes the main module, which has no version. However, MVS treats
                // version strings as opaque, so "" is not a special value here.
                // See golang.org/issue/31491, golang.org/issue/29773.
-               panic(fmt.Sprintf("mistake: chose version %q instead of target %+v", v, target)) // TODO: Don't panic.
+               panic(fmt.Sprintf("mistake: chose version %q instead of target %+v", v, target))
        }
-
-       list := []module.Version{target}
-       for path, vers := range min {
-               if path != target.Path {
-                       list = append(list, module.Version{Path: path, Version: vers})
-               }
-
-               n := modGraph[module.Version{Path: path, Version: vers}]
-               required := n.required
-               for _, r := range required {
-                       if r.Version == "none" {
-                               continue
-                       }
-                       v := min[r.Path]
-                       if r.Path != target.Path && reqs.Max(v, r.Version) != v {
-                               panic(fmt.Sprintf("mistake: version %q does not satisfy requirement %+v", v, r)) // TODO: Don't panic.
-                       }
-               }
-       }
-
-       tail := list[1:]
-       sort.Slice(tail, func(i, j int) bool {
-               return tail[i].Path < tail[j].Path
-       })
        return list, nil
 }
 
@@ -293,10 +242,15 @@ func Req(target module.Version, base []string, reqs Reqs) ([]module.Version, err
        }
        // First walk the base modules that must be listed.
        var min []module.Version
+       haveBase := map[string]bool{}
        for _, path := range base {
+               if haveBase[path] {
+                       continue
+               }
                m := module.Version{Path: path, Version: max[path]}
                min = append(min, m)
                walk(m)
+               haveBase[path] = true
        }
        // Now the reverse postorder to bring in anything else.
        for i := len(postorder) - 1; i >= 0; i-- {
@@ -318,7 +272,7 @@ func Req(target module.Version, base []string, reqs Reqs) ([]module.Version, err
 
 // UpgradeAll returns a build list for the target module
 // in which every module is upgraded to its latest version.
-func UpgradeAll(target module.Version, reqs Reqs) ([]module.Version, error) {
+func UpgradeAll(target module.Version, reqs UpgradeReqs) ([]module.Version, error) {
        return buildList(target, reqs, func(m module.Version) (module.Version, error) {
                if m.Path == target.Path {
                        return target, nil
@@ -330,7 +284,7 @@ func UpgradeAll(target module.Version, reqs Reqs) ([]module.Version, error) {
 
 // Upgrade returns a build list for the target module
 // in which the given additional modules are upgraded.
-func Upgrade(target module.Version, reqs Reqs, upgrade ...module.Version) ([]module.Version, error) {
+func Upgrade(target module.Version, reqs UpgradeReqs, upgrade ...module.Version) ([]module.Version, error) {
        list, err := reqs.Required(target)
        if err != nil {
                return nil, err
@@ -369,11 +323,20 @@ func Upgrade(target module.Version, reqs Reqs, upgrade ...module.Version) ([]mod
 // The versions to be downgraded may be unreachable from reqs.Latest and
 // reqs.Previous, but the methods of reqs must otherwise handle such versions
 // correctly.
-func Downgrade(target module.Version, reqs Reqs, downgrade ...module.Version) ([]module.Version, error) {
-       list, err := reqs.Required(target)
+func Downgrade(target module.Version, reqs DowngradeReqs, downgrade ...module.Version) ([]module.Version, error) {
+       // Per https://research.swtch.com/vgo-mvs#algorithm_4:
+       // “To avoid an unnecessary downgrade to E 1.1, we must also add a new
+       // requirement on E 1.2. We can apply Algorithm R to find the minimal set of
+       // new requirements to write to go.mod.”
+       //
+       // In order to generate those new requirements, we need to identify versions
+       // for every module in the build list — not just reqs.Required(target).
+       list, err := BuildList(target, reqs)
        if err != nil {
                return nil, err
        }
+       list = list[1:] // remove target
+
        max := make(map[string]string)
        for _, r := range list {
                max[r.Path] = r.Version
@@ -406,6 +369,9 @@ func Downgrade(target module.Version, reqs Reqs, downgrade ...module.Version) ([
                }
                added[m] = true
                if v, ok := max[m.Path]; ok && reqs.Max(m.Version, v) != v {
+                       // m would upgrade an existing dependency — it is not a strict downgrade,
+                       // and because it was already present as a dependency, it could affect the
+                       // behavior of other relevant packages.
                        exclude(m)
                        return
                }
@@ -422,6 +388,7 @@ func Downgrade(target module.Version, reqs Reqs, downgrade ...module.Version) ([
                        // is transient (we couldn't download go.mod), return the error from
                        // Downgrade. Currently, we can't tell what kind of error it is.
                        exclude(m)
+                       return
                }
                for _, r := range list {
                        add(r)
@@ -433,8 +400,8 @@ func Downgrade(target module.Version, reqs Reqs, downgrade ...module.Version) ([
                }
        }
 
-       var out []module.Version
-       out = append(out, target)
+       downgraded := make([]module.Version, 0, len(list)+1)
+       downgraded = append(downgraded, target)
 List:
        for _, r := range list {
                add(r)
@@ -461,10 +428,49 @@ List:
                        add(p)
                        r = p
                }
-               out = append(out, r)
+               downgraded = append(downgraded, r)
        }
 
-       return out, nil
+       // The downgrades we computed above only downgrade to versions enumerated by
+       // reqs.Previous. However, reqs.Previous omits some versions — such as
+       // pseudo-versions and retracted versions — that may be selected as transitive
+       // requirements of other modules.
+       //
+       // If one of those requirements pulls the version back up above the version
+       // identified by reqs.Previous, then the transitive dependencies of that that
+       // initially-downgraded version should no longer matter — in particular, we
+       // should not add new dependencies on module paths that nothing else in the
+       // updated module graph even requires.
+       //
+       // In order to eliminate those spurious dependencies, we recompute the build
+       // list with the actual versions of the downgraded modules as selected by MVS,
+       // instead of our initial downgrades.
+       // (See the downhiddenartifact and downhiddencross test cases).
+       actual, err := BuildList(target, &override{
+               target: target,
+               list:   downgraded,
+               Reqs:   reqs,
+       })
+       if err != nil {
+               return nil, err
+       }
+       actualVersion := make(map[string]string, len(actual))
+       for _, m := range actual {
+               actualVersion[m.Path] = m.Version
+       }
+
+       downgraded = downgraded[:0]
+       for _, m := range list {
+               if v, ok := actualVersion[m.Path]; ok {
+                       downgraded = append(downgraded, module.Version{Path: m.Path, Version: v})
+               }
+       }
+
+       return BuildList(target, &override{
+               target: target,
+               list:   downgraded,
+               Reqs:   reqs,
+       })
 }
 
 type override struct {
index 721cd9635c8d84dabead835817dfa9f817b97fc2..598ed666889517a112c01e78d5b6fcb95101fcd2 100644 (file)
@@ -28,10 +28,11 @@ D4: E2 F1
 D5: E2
 G1: C4
 A2: B1 C4 D4
-build A: A B1 C2 D4 E2 F1
-upgrade* A: A B1 C4 D5 E2 F1 G1
-upgrade A C4: A B1 C4 D4 E2 F1 G1
-downgrade A2 D2: A2 C4 D2
+build A:       A B1 C2 D4 E2 F1
+upgrade* A:    A B1 C4 D5 E2 F1 G1
+upgrade A C4:  A B1 C4 D4 E2 F1 G1
+build A2:     A2 B1 C4 D4 E2 F1 G1
+downgrade A2 D2: A2 C4 D2 E2 F1 G1
 
 name: trim
 A: B1 C2
@@ -68,7 +69,7 @@ B2: D1
 C: D2
 D1: E2
 D2: E1
-build A: A B1 C D2 E1
+build A:      A B1 C D2 E1
 upgrade A B2: A B2 C D2 E2
 
 name: cross1R
@@ -136,17 +137,17 @@ name: cross5
 A: D1
 D1: E2
 D2: E1
-build A: A D1 E2
-upgrade* A: A D2 E2
-upgrade A D2: A D2 E2
+build A:       A D1 E2
+upgrade* A:    A D2 E2
+upgrade A D2:  A D2 E2
 upgradereq A D2: D2 E2
 
 name: cross6
 A: D2
 D1: E2
 D2: E1
-build A: A D2 E1
-upgrade* A: A D2 E2
+build A:      A D2 E1
+upgrade* A:   A D2 E2
 upgrade A E2: A D2 E2
 
 name: cross7
@@ -175,7 +176,7 @@ B1: D1
 B2:
 C2:
 D2:
-build A: A B1 C1 D1
+build A:    A B1 C1 D1
 upgrade* A: A B2 C2 D2
 
 name: simplify
@@ -194,7 +195,7 @@ B4:
 B5.hidden:
 C2:
 C3:
-build A: A B1 C1
+build A:    A B1 C1
 upgrade* A: A B4 C3
 
 name: up2
@@ -206,15 +207,15 @@ B4:
 B5.hidden:
 C2:
 C3:
-build A: A B5.hidden C1
+build A:    A B5.hidden C1
 upgrade* A: A B5.hidden C3
 
 name: down1
 A: B2
 B1: C1
 B2: C2
-build A: A B2 C2
-downgrade A C1: A B1
+build A:        A B2 C2
+downgrade A C1: A B1 C1
 
 name: down2
 A: B2 E2
@@ -227,19 +228,113 @@ D2: B2
 E2: D2
 E1:
 F1:
-downgrade A F1: A B1 E1
+build A:        A B2 C2 D2 E2 F2
+downgrade A F1: A B1 C1 D1 E1 F1
+
+# https://research.swtch.com/vgo-mvs#algorithm_4:
+# “[D]owngrades are constrained to only downgrade packages, not also upgrade
+# them; if an upgrade before downgrade is needed, the user must ask for it
+# explicitly.”
+#
+# Here, downgrading B2 to B1 upgrades C1 to C2, and C2 does not depend on D2.
+# However, C2 would be an upgrade — not a downgrade — so B1 must also be
+# rejected.
+name: downcross1
+A: B2 C1
+B1: C2
+B2: C1
+C1: D2
+C2:
+D1:
+D2:
+build A:        A B2 C1 D2
+downgrade A D1: A       D1
+
+# https://research.swtch.com/vgo-mvs#algorithm_4:
+# “Unlike upgrades, downgrades must work by removing requirements, not adding
+# them.”
+#
+# However, downgrading a requirement may introduce a new requirement on a
+# previously-unrequired module. If each dependency's requirements are complete
+# (“tidy”), that can't change the behavior of any other package whose version is
+# not also being downgraded, so we should allow it.
+name: downcross2
+A: B2
+B1: C1
+B2: D2
+C1:
+D1:
+D2:
+build A:        A B2    D2
+downgrade A D1: A B1 C1 D1
 
 name: downcycle
 A: A B2
 B2: A
 B1:
+build A:        A B2
 downgrade A B1: A B1
 
+# Both B3 and C2 require D2.
+# If we downgrade D to D1, then in isolation B3 would downgrade to B1,
+# because B2 is hidden — B1 is the next-highest version that is not hidden.
+# However, if we downgrade D, we will also downgrade C to C1.
+# And C1 requires B2.hidden, and B2.hidden also meets our requirements:
+# it is compatible with D1 and a strict downgrade from B3.
+#
+# Since neither the initial nor the final build list includes B1,
+# and the nothing in the final downgraded build list requires E at all,
+# no dependency on E1 (required by only B1) should be introduced.
+#
+name: downhiddenartifact
+A: B3 C2
+A1: B3
+B1: E1
+B2.hidden:
+B3: D2
+C1: B2.hidden
+C2: D2
+D1:
+D2:
+build A1: A1 B3 D2
+downgrade A1 D1: A1 B1 D1 E1
+build A: A B3 C2 D2
+downgrade A D1: A B2.hidden C1 D1
+
+# Both B3 and C3 require D2.
+# If we downgrade D to D1, then in isolation B3 would downgrade to B1,
+# and C3 would downgrade to C1.
+# But C1 requires B2.hidden, and B1 requires C2.hidden, so we can't
+# downgrade to either of those without pulling the other back up a little.
+#
+# B2.hidden and C2.hidden are both compatible with D1, so that still
+# meets our requirements — but then we're in an odd state in which
+# B and C have both been downgraded to hidden versions, without any
+# remaining requirements to explain how those hidden versions got there.
+#
+# TODO(bcmills): Would it be better to force downgrades to land on non-hidden
+# versions?
+# In this case, that would remove the dependencies on B and C entirely.
+#
+name: downhiddencross
+A: B3 C3
+B1: C2.hidden
+B2.hidden:
+B3: D2
+C1: B2.hidden
+C2.hidden:
+C3: D2
+D1:
+D2:
+build A: A B3 C3 D2
+downgrade A D1: A B2.hidden C2.hidden D1
+
 # golang.org/issue/25542.
 name: noprev1
 A: B4 C2
 B2.hidden:
 C2:
+build A:               A B4        C2
 downgrade A B2.hidden: A B2.hidden C2
 
 name: noprev2
@@ -247,6 +342,7 @@ A: B4 C2
 B2.hidden:
 B1:
 C2:
+build A:               A B4        C2
 downgrade A B2.hidden: A B2.hidden C2
 
 name: noprev3
@@ -254,6 +350,7 @@ A: B4 C2
 B3:
 B2.hidden:
 C2:
+build A:               A B4        C2
 downgrade A B2.hidden: A B2.hidden C2
 
 # Cycles involving the target.
@@ -264,9 +361,9 @@ A: B1
 B1: A1
 B2: A2
 B3: A3
-build A: A B1
+build A:      A B1
 upgrade A B2: A B2
-upgrade* A: A B3
+upgrade* A:   A B3
 
 # golang.org/issue/29773:
 # Requirements of older versions of the target
@@ -280,7 +377,7 @@ B2: A2
 C1: A2
 C2:
 D2:
-build A: A B1 C1 D1
+build A:    A B1 C1 D1
 upgrade* A: A B2 C2 D2
 
 # Cycles with multiple possible solutions.
@@ -293,23 +390,23 @@ B2: C2
 C1:
 C2: B2
 build M: M A1 B2 C2
-req M: A1 B2
-req M A: A1 B2
-req M C: A1 C2
+req M:     A1 B2
+req M A:   A1 B2
+req M C:   A1 C2
 
 # Requirement minimization.
 
 name: req1
 A: B1 C1 D1 E1 F1
 B1: C1 E1 F1
-req A: B1 D1
+req A:   B1    D1
 req A C: B1 C1 D1
 
 name: req2
 A: G1 H1
 G1: H1
 H1: G1
-req A: G1
+req A:   G1
 req A G: G1
 req A H: H1
 
@@ -326,7 +423,20 @@ M: Anone B1 D1 E1
 B1: Cnone D1
 E1: Fnone
 build M: M B1 D1 E1
-req M: B1 E1
+req M:     B1    E1
+
+name: reqdup
+M: A1 B1
+A1: B1
+B1:
+req M A A: A1
+
+name: reqcross
+M: A1 B1 C1
+A1: B1 C1
+B1: C1
+C1:
+req M A B: A1 B1
 `
 
 func Test(t *testing.T) {
diff --git a/libgo/go/cmd/go/internal/renameio/renameio.go b/libgo/go/cmd/go/internal/renameio/renameio.go
deleted file mode 100644 (file)
index 9788171..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package renameio writes files atomically by renaming temporary files.
-package renameio
-
-import (
-       "bytes"
-       "io"
-       "io/fs"
-       "math/rand"
-       "os"
-       "path/filepath"
-       "strconv"
-
-       "cmd/go/internal/robustio"
-)
-
-const patternSuffix = ".tmp"
-
-// Pattern returns a glob pattern that matches the unrenamed temporary files
-// created when writing to filename.
-func Pattern(filename string) string {
-       return filepath.Join(filepath.Dir(filename), filepath.Base(filename)+patternSuffix)
-}
-
-// WriteFile is like os.WriteFile, but first writes data to an arbitrary
-// file in the same directory as filename, then renames it atomically to the
-// final name.
-//
-// That ensures that the final location, if it exists, is always a complete file.
-func WriteFile(filename string, data []byte, perm fs.FileMode) (err error) {
-       return WriteToFile(filename, bytes.NewReader(data), perm)
-}
-
-// WriteToFile is a variant of WriteFile that accepts the data as an io.Reader
-// instead of a slice.
-func WriteToFile(filename string, data io.Reader, perm fs.FileMode) (err error) {
-       f, err := tempFile(filepath.Dir(filename), filepath.Base(filename), perm)
-       if err != nil {
-               return err
-       }
-       defer func() {
-               // Only call os.Remove on f.Name() if we failed to rename it: otherwise,
-               // some other process may have created a new file with the same name after
-               // that.
-               if err != nil {
-                       f.Close()
-                       os.Remove(f.Name())
-               }
-       }()
-
-       if _, err := io.Copy(f, data); err != nil {
-               return err
-       }
-       // Sync the file before renaming it: otherwise, after a crash the reader may
-       // observe a 0-length file instead of the actual contents.
-       // See https://golang.org/issue/22397#issuecomment-380831736.
-       if err := f.Sync(); err != nil {
-               return err
-       }
-       if err := f.Close(); err != nil {
-               return err
-       }
-
-       return robustio.Rename(f.Name(), filename)
-}
-
-// ReadFile is like os.ReadFile, but on Windows retries spurious errors that
-// may occur if the file is concurrently replaced.
-//
-// Errors are classified heuristically and retries are bounded, so even this
-// function may occasionally return a spurious error on Windows.
-// If so, the error will likely wrap one of:
-//     - syscall.ERROR_ACCESS_DENIED
-//     - syscall.ERROR_FILE_NOT_FOUND
-//     - internal/syscall/windows.ERROR_SHARING_VIOLATION
-func ReadFile(filename string) ([]byte, error) {
-       return robustio.ReadFile(filename)
-}
-
-// tempFile creates a new temporary file with given permission bits.
-func tempFile(dir, prefix string, perm fs.FileMode) (f *os.File, err error) {
-       for i := 0; i < 10000; i++ {
-               name := filepath.Join(dir, prefix+strconv.Itoa(rand.Intn(1000000000))+patternSuffix)
-               f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, perm)
-               if os.IsExist(err) {
-                       continue
-               }
-               break
-       }
-       return
-}
diff --git a/libgo/go/cmd/go/internal/renameio/renameio_test.go b/libgo/go/cmd/go/internal/renameio/renameio_test.go
deleted file mode 100644 (file)
index 5b2ed83..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2019 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build !plan9
-
-package renameio
-
-import (
-       "encoding/binary"
-       "errors"
-       "internal/testenv"
-       "math/rand"
-       "os"
-       "path/filepath"
-       "runtime"
-       "strings"
-       "sync"
-       "sync/atomic"
-       "syscall"
-       "testing"
-       "time"
-
-       "cmd/go/internal/robustio"
-)
-
-func TestConcurrentReadsAndWrites(t *testing.T) {
-       if runtime.GOOS == "darwin" && strings.HasSuffix(testenv.Builder(), "-10_14") {
-               testenv.SkipFlaky(t, 33041)
-       }
-
-       dir, err := os.MkdirTemp("", "renameio")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(dir)
-       path := filepath.Join(dir, "blob.bin")
-
-       const chunkWords = 8 << 10
-       buf := make([]byte, 2*chunkWords*8)
-       for i := uint64(0); i < 2*chunkWords; i++ {
-               binary.LittleEndian.PutUint64(buf[i*8:], i)
-       }
-
-       var attempts int64 = 128
-       if !testing.Short() {
-               attempts *= 16
-       }
-       const parallel = 32
-
-       var sem = make(chan bool, parallel)
-
-       var (
-               writeSuccesses, readSuccesses int64 // atomic
-               writeErrnoSeen, readErrnoSeen sync.Map
-       )
-
-       for n := attempts; n > 0; n-- {
-               sem <- true
-               go func() {
-                       defer func() { <-sem }()
-
-                       time.Sleep(time.Duration(rand.Intn(100)) * time.Microsecond)
-                       offset := rand.Intn(chunkWords)
-                       chunk := buf[offset*8 : (offset+chunkWords)*8]
-                       if err := WriteFile(path, chunk, 0666); err == nil {
-                               atomic.AddInt64(&writeSuccesses, 1)
-                       } else if robustio.IsEphemeralError(err) {
-                               var (
-                                       errno syscall.Errno
-                                       dup   bool
-                               )
-                               if errors.As(err, &errno) {
-                                       _, dup = writeErrnoSeen.LoadOrStore(errno, true)
-                               }
-                               if !dup {
-                                       t.Logf("ephemeral error: %v", err)
-                               }
-                       } else {
-                               t.Errorf("unexpected error: %v", err)
-                       }
-
-                       time.Sleep(time.Duration(rand.Intn(100)) * time.Microsecond)
-                       data, err := ReadFile(path)
-                       if err == nil {
-                               atomic.AddInt64(&readSuccesses, 1)
-                       } else if robustio.IsEphemeralError(err) {
-                               var (
-                                       errno syscall.Errno
-                                       dup   bool
-                               )
-                               if errors.As(err, &errno) {
-                                       _, dup = readErrnoSeen.LoadOrStore(errno, true)
-                               }
-                               if !dup {
-                                       t.Logf("ephemeral error: %v", err)
-                               }
-                               return
-                       } else {
-                               t.Errorf("unexpected error: %v", err)
-                               return
-                       }
-
-                       if len(data) != 8*chunkWords {
-                               t.Errorf("read %d bytes, but each write is a %d-byte file", len(data), 8*chunkWords)
-                               return
-                       }
-
-                       u := binary.LittleEndian.Uint64(data)
-                       for i := 1; i < chunkWords; i++ {
-                               next := binary.LittleEndian.Uint64(data[i*8:])
-                               if next != u+1 {
-                                       t.Errorf("wrote sequential integers, but read integer out of sequence at offset %d", i)
-                                       return
-                               }
-                               u = next
-                       }
-               }()
-       }
-
-       for n := parallel; n > 0; n-- {
-               sem <- true
-       }
-
-       var minWriteSuccesses int64 = attempts
-       if runtime.GOOS == "windows" {
-               // Windows produces frequent "Access is denied" errors under heavy rename load.
-               // As long as those are the only errors and *some* of the writes succeed, we're happy.
-               minWriteSuccesses = attempts / 4
-       }
-
-       if writeSuccesses < minWriteSuccesses {
-               t.Errorf("%d (of %d) writes succeeded; want ≥ %d", writeSuccesses, attempts, minWriteSuccesses)
-       } else {
-               t.Logf("%d (of %d) writes succeeded (ok: ≥ %d)", writeSuccesses, attempts, minWriteSuccesses)
-       }
-
-       var minReadSuccesses int64 = attempts
-
-       switch runtime.GOOS {
-       case "windows":
-               // Windows produces frequent "Access is denied" errors under heavy rename load.
-               // As long as those are the only errors and *some* of the reads succeed, we're happy.
-               minReadSuccesses = attempts / 4
-
-       case "darwin", "ios":
-               // The filesystem on certain versions of macOS (10.14) and iOS (affected
-               // versions TBD) occasionally fail with "no such file or directory" errors.
-               // See https://golang.org/issue/33041 and https://golang.org/issue/42066.
-               // The flake rate is fairly low, so ensure that at least 75% of attempts
-               // succeed.
-               minReadSuccesses = attempts - (attempts / 4)
-       }
-
-       if readSuccesses < minReadSuccesses {
-               t.Errorf("%d (of %d) reads succeeded; want ≥ %d", readSuccesses, attempts, minReadSuccesses)
-       } else {
-               t.Logf("%d (of %d) reads succeeded (ok: ≥ %d)", readSuccesses, attempts, minReadSuccesses)
-       }
-}
diff --git a/libgo/go/cmd/go/internal/renameio/umask_test.go b/libgo/go/cmd/go/internal/renameio/umask_test.go
deleted file mode 100644 (file)
index 65e4fa5..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2019 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build !plan9,!windows,!js
-
-package renameio
-
-import (
-       "io/fs"
-       "os"
-       "path/filepath"
-       "syscall"
-       "testing"
-)
-
-func TestWriteFileModeAppliesUmask(t *testing.T) {
-       dir, err := os.MkdirTemp("", "renameio")
-       if err != nil {
-               t.Fatalf("Failed to create temporary directory: %v", err)
-       }
-       defer os.RemoveAll(dir)
-
-       const mode = 0644
-       const umask = 0007
-       defer syscall.Umask(syscall.Umask(umask))
-
-       file := filepath.Join(dir, "testWrite")
-       err = WriteFile(file, []byte("go-build"), mode)
-       if err != nil {
-               t.Fatalf("Failed to write file: %v", err)
-       }
-
-       fi, err := os.Stat(file)
-       if err != nil {
-               t.Fatalf("Stat %q (looking for mode %#o): %s", file, mode, err)
-       }
-
-       if fi.Mode()&fs.ModePerm != 0640 {
-               t.Errorf("Stat %q: mode %#o want %#o", file, fi.Mode()&fs.ModePerm, 0640)
-       }
-}
index 5bd44bd345338f31f7e278c0eaf66042f955ac51..d5c241857b476c47cfed2c9bb1c5b1f739426ee3 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build windows || darwin
 // +build windows darwin
 
 package robustio
index 6fe7b7e4e4e9df3e4812f73a598e2073be43f96d..3a20cac6cf88aef9882a484439c2298489a80e2f 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !windows && !darwin
 // +build !windows,!darwin
 
 package robustio
index 666b1a0e560c5156d39c56e7ae5a2a5baedaeaa6..784f7162dfd3f5b01bbd7c60a89975a9e3e5f1aa 100644 (file)
@@ -8,13 +8,16 @@ package run
 import (
        "context"
        "fmt"
+       "go/build"
        "os"
        "path"
+       "path/filepath"
        "strings"
 
        "cmd/go/internal/base"
        "cmd/go/internal/cfg"
        "cmd/go/internal/load"
+       "cmd/go/internal/modload"
        "cmd/go/internal/str"
        "cmd/go/internal/work"
 )
@@ -24,10 +27,21 @@ var CmdRun = &base.Command{
        Short:     "compile and run Go program",
        Long: `
 Run compiles and runs the named main Go package.
-Typically the package is specified as a list of .go source files from a single directory,
-but it may also be an import path, file system path, or pattern
+Typically the package is specified as a list of .go source files from a single
+directory, but it may also be an import path, file system path, or pattern
 matching a single known package, as in 'go run .' or 'go run my/cmd'.
 
+If the package argument has a version suffix (like @latest or @v1.0.0),
+"go run" builds the program in module-aware mode, ignoring the go.mod file in
+the current directory or any parent directory, if there is one. This is useful
+for running programs without affecting the dependencies of the main module.
+
+If the package argument doesn't have a version suffix, "go run" may run in
+module-aware mode or GOPATH mode, depending on the GO111MODULE environment
+variable and the presence of a go.mod file. See 'go help modules' for details.
+If module-aware mode is enabled, "go run" runs in the context of the main
+module.
+
 By default, 'go run' runs the compiled binary directly: 'a.out arguments...'.
 If the -exec flag is given, 'go run' invokes the binary using xprog:
        'xprog a.out arguments...'.
@@ -59,14 +73,26 @@ func printStderr(args ...interface{}) (int, error) {
 }
 
 func runRun(ctx context.Context, cmd *base.Command, args []string) {
+       if shouldUseOutsideModuleMode(args) {
+               // Set global module flags for 'go run cmd@version'.
+               // This must be done before modload.Init, but we need to call work.BuildInit
+               // before loading packages, since it affects package locations, e.g.,
+               // for -race and -msan.
+               modload.ForceUseModules = true
+               modload.RootMode = modload.NoRoot
+               modload.AllowMissingModuleImports()
+               modload.Init()
+       }
        work.BuildInit()
        var b work.Builder
        b.Init()
        b.Print = printStderr
+
        i := 0
        for i < len(args) && strings.HasSuffix(args[i], ".go") {
                i++
        }
+       pkgOpts := load.PackageOpts{MainOnly: true}
        var p *load.Package
        if i > 0 {
                files := args[:i]
@@ -77,18 +103,29 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) {
                                base.Fatalf("go run: cannot run *_test.go files (%s)", file)
                        }
                }
-               p = load.GoFilesPackage(ctx, files)
+               p = load.GoFilesPackage(ctx, pkgOpts, files)
        } else if len(args) > 0 && !strings.HasPrefix(args[0], "-") {
-               pkgs := load.PackagesAndErrors(ctx, args[:1])
+               arg := args[0]
+               var pkgs []*load.Package
+               if strings.Contains(arg, "@") && !build.IsLocalImport(arg) && !filepath.IsAbs(arg) {
+                       var err error
+                       pkgs, err = load.PackagesAndErrorsOutsideModule(ctx, pkgOpts, args[:1])
+                       if err != nil {
+                               base.Fatalf("go run: %v", err)
+                       }
+               } else {
+                       pkgs = load.PackagesAndErrors(ctx, pkgOpts, args[:1])
+               }
+
                if len(pkgs) == 0 {
-                       base.Fatalf("go run: no packages loaded from %s", args[0])
+                       base.Fatalf("go run: no packages loaded from %s", arg)
                }
                if len(pkgs) > 1 {
                        var names []string
                        for _, p := range pkgs {
                                names = append(names, p.ImportPath)
                        }
-                       base.Fatalf("go run: pattern %s matches multiple packages:\n\t%s", args[0], strings.Join(names, "\n\t"))
+                       base.Fatalf("go run: pattern %s matches multiple packages:\n\t%s", arg, strings.Join(names, "\n\t"))
                }
                p = pkgs[0]
                i++
@@ -98,9 +135,6 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) {
        cmdArgs := args[i:]
        load.CheckPackageErrors([]*load.Package{p})
 
-       if p.Name != "main" {
-               base.Fatalf("go run: cannot run non-main package")
-       }
        p.Internal.OmitDebug = true
        p.Target = "" // must build - not up to date
        if p.Internal.CmdlineFiles {
@@ -123,11 +157,34 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) {
        } else {
                p.Internal.ExeName = path.Base(p.ImportPath)
        }
+
        a1 := b.LinkAction(work.ModeBuild, work.ModeBuild, p)
        a := &work.Action{Mode: "go run", Func: buildRunProgram, Args: cmdArgs, Deps: []*work.Action{a1}}
        b.Do(ctx, a)
 }
 
+// shouldUseOutsideModuleMode returns whether 'go run' will load packages in
+// module-aware mode, ignoring the go.mod file in the current directory. It
+// returns true if the first argument contains "@", does not begin with "-"
+// (resembling a flag) or end with ".go" (a file). The argument must not be a
+// local or absolute file path.
+//
+// These rules are slightly different than other commands. Whether or not
+// 'go run' uses this mode, it interprets arguments ending with ".go" as files
+// and uses arguments up to the last ".go" argument to comprise the package.
+// If there are no ".go" arguments, only the first argument is interpreted
+// as a package path, since there can be only one package.
+func shouldUseOutsideModuleMode(args []string) bool {
+       // NOTE: "@" not allowed in import paths, but it is allowed in non-canonical
+       // versions.
+       return len(args) > 0 &&
+               !strings.HasSuffix(args[0], ".go") &&
+               !strings.HasPrefix(args[0], "-") &&
+               strings.Contains(args[0], "@") &&
+               !build.IsLocalImport(args[0]) &&
+               !filepath.IsAbs(args[0])
+}
+
 // buildRunProgram is the action for running a binary that has already
 // been compiled. We ignore exit status.
 func buildRunProgram(b *work.Builder, ctx context.Context, a *work.Action) error {
index 18738cf59ec8d3c48dc30339c869c40ef698bde0..a0c806a259329c27c2f45739e1250550bec04f06 100644 (file)
@@ -155,7 +155,7 @@ func (m *Match) MatchPackages() {
                        }
 
                        if !fi.IsDir() {
-                               if fi.Mode()&fs.ModeSymlink != 0 && want {
+                               if fi.Mode()&fs.ModeSymlink != 0 && want && strings.Contains(m.pattern, "...") {
                                        if target, err := fsys.Stat(path); err == nil && target.IsDir() {
                                                fmt.Fprintf(os.Stderr, "warning: ignoring symlink %s\n", path)
                                        }
@@ -445,7 +445,7 @@ func ImportPathsQuiet(patterns []string) []*Match {
                        for i, dir := range m.Dirs {
                                absDir := dir
                                if !filepath.IsAbs(dir) {
-                                       absDir = filepath.Join(base.Cwd, dir)
+                                       absDir = filepath.Join(base.Cwd(), dir)
                                }
                                if bp, _ := cfg.BuildContext.ImportDir(absDir, build.FindOnly); bp.ImportPath != "" && bp.ImportPath != "." {
                                        m.Pkgs[i] = bp.ImportPath
@@ -571,7 +571,6 @@ func IsRelativePath(pattern string) bool {
 // If so, InDir returns an equivalent path relative to dir.
 // If not, InDir returns an empty string.
 // InDir makes some effort to succeed even in the presence of symbolic links.
-// TODO(rsc): Replace internal/test.inDir with a call to this function for Go 1.12.
 func InDir(path, dir string) string {
        if rel := inDirLex(path, dir); rel != "" {
                return rel
index 9841791552dbbc125afa5b3fa4e193a62d4aaad1..657d22a6b4d2ff8a7a1d69c6e2ed76e6c869c3e6 100644 (file)
@@ -26,8 +26,8 @@ func initCoverProfile() {
        if testCoverProfile == "" || testC {
                return
        }
-       if !filepath.IsAbs(testCoverProfile) && testOutputDir != "" {
-               testCoverProfile = filepath.Join(testOutputDir, testCoverProfile)
+       if !filepath.IsAbs(testCoverProfile) {
+               testCoverProfile = filepath.Join(testOutputDir.getAbs(), testCoverProfile)
        }
 
        // No mutex - caller's responsibility to call with no racing goroutines.
index 8a0a07683b7cc9778ee96d5011db4baefadc6f3a..37ac81c26782ae226be515bc2f65a42700de978d 100644 (file)
@@ -28,6 +28,7 @@ var passFlagToTest = map[string]bool{
        "parallel":             true,
        "run":                  true,
        "short":                true,
+       "shuffle":              true,
        "timeout":              true,
        "trace":                true,
        "v":                    true,
index 30334b0f305ce495cc0475a43f6c08da063c90be..9277de7fee839e216f8c70b31b8720d839f16c5e 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 package main
index 7fc9e8fbdcda1afb5837d5b2932329890b49b6a2..59ea1ef5445178f052006dd37af2d8b0b209b9ef 100644 (file)
@@ -29,6 +29,7 @@ import (
        "cmd/go/internal/cfg"
        "cmd/go/internal/load"
        "cmd/go/internal/lockedfile"
+       "cmd/go/internal/search"
        "cmd/go/internal/str"
        "cmd/go/internal/trace"
        "cmd/go/internal/work"
@@ -117,8 +118,8 @@ elapsed time in the summary line.
 
 The rule for a match in the cache is that the run involves the same
 test binary and the flags on the command line come entirely from a
-restricted set of 'cacheable' test flags, defined as -cpu, -list,
--parallel, -run, -short, and -v. If a run of go test has any test
+restricted set of 'cacheable' test flags, defined as -benchtime, -cpu,
+-list, -parallel, -run, -short, and -v. If a run of go test has any test
 or non-test flags outside this set, the result is not cached. To
 disable test caching, use any test flag or argument other than the
 cacheable flags. The idiomatic way to disable test caching explicitly
@@ -271,6 +272,13 @@ control the execution of any test:
            the Go tree can run a sanity check but not spend time running
            exhaustive tests.
 
+       -shuffle off,on,N
+               Randomize the execution order of tests and benchmarks.
+               It is off by default. If -shuffle is set to on, then it will seed
+               the randomizer using the system clock. If -shuffle is set to an
+               integer N, then N will be used as the seed value. In both cases,
+               the seed will be reported for reproducibility.
+
        -timeout d
            If a test binary runs longer than duration d, panic.
            If d is 0, the timeout is disabled.
@@ -478,7 +486,8 @@ var (
        testJSON         bool                              // -json flag
        testList         string                            // -list flag
        testO            string                            // -o flag
-       testOutputDir    = base.Cwd                        // -outputdir flag
+       testOutputDir    outputdirFlag                     // -outputdir flag
+       testShuffle      shuffleFlag                       // -shuffle flag
        testTimeout      time.Duration                     // -timeout flag
        testV            bool                              // -v flag
        testVet          = vetFlag{flags: defaultVetFlags} // -vet flag
@@ -568,8 +577,6 @@ var defaultVetFlags = []string{
 }
 
 func runTest(ctx context.Context, cmd *base.Command, args []string) {
-       load.ModResolveTests = true
-
        pkgArgs, testArgs = testFlags(args)
 
        if cfg.DebugTrace != "" {
@@ -595,7 +602,8 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
        work.VetFlags = testVet.flags
        work.VetExplicit = testVet.explicit
 
-       pkgs = load.PackagesAndErrors(ctx, pkgArgs)
+       pkgOpts := load.PackageOpts{ModResolveTests: true}
+       pkgs = load.PackagesAndErrors(ctx, pkgOpts, pkgArgs)
        load.CheckPackageErrors(pkgs)
        if len(pkgs) == 0 {
                base.Fatalf("no packages to test")
@@ -679,7 +687,7 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
                sort.Strings(all)
 
                a := &work.Action{Mode: "go test -i"}
-               pkgs := load.PackagesAndErrors(ctx, all)
+               pkgs := load.PackagesAndErrors(ctx, pkgOpts, all)
                load.CheckPackageErrors(pkgs)
                for _, p := range pkgs {
                        if cfg.BuildToolchainName == "gccgo" && p.Standard {
@@ -702,11 +710,11 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
                match := make([]func(*load.Package) bool, len(testCoverPaths))
                matched := make([]bool, len(testCoverPaths))
                for i := range testCoverPaths {
-                       match[i] = load.MatchPackage(testCoverPaths[i], base.Cwd)
+                       match[i] = load.MatchPackage(testCoverPaths[i], base.Cwd())
                }
 
                // Select for coverage all dependencies matching the testCoverPaths patterns.
-               for _, p := range load.TestPackageList(ctx, pkgs) {
+               for _, p := range load.TestPackageList(ctx, pkgOpts, pkgs) {
                        haveMatch := false
                        for i := range testCoverPaths {
                                if match[i](p) {
@@ -715,6 +723,12 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
                                }
                        }
 
+                       // A package which only has test files can't be imported
+                       // as a dependency, nor can it be instrumented for coverage.
+                       if len(p.GoFiles)+len(p.CgoFiles) == 0 {
+                               continue
+                       }
+
                        // Silently ignore attempts to run coverage on
                        // sync/atomic when using atomic coverage mode.
                        // Atomic coverage mode uses sync/atomic, so
@@ -768,7 +782,7 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
                        ensureImport(p, "sync/atomic")
                }
 
-               buildTest, runTest, printTest, err := builderTest(&b, ctx, p)
+               buildTest, runTest, printTest, err := builderTest(&b, ctx, pkgOpts, p)
                if err != nil {
                        str := err.Error()
                        str = strings.TrimPrefix(str, "\n")
@@ -835,7 +849,7 @@ var windowsBadWords = []string{
        "update",
 }
 
-func builderTest(b *work.Builder, ctx context.Context, p *load.Package) (buildAction, runAction, printAction *work.Action, err error) {
+func builderTest(b *work.Builder, ctx context.Context, pkgOpts load.PackageOpts, p *load.Package) (buildAction, runAction, printAction *work.Action, err error) {
        if len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 {
                build := b.CompileAction(work.ModeBuild, work.ModeBuild, p)
                run := &work.Action{Mode: "test run", Package: p, Deps: []*work.Action{build}}
@@ -858,7 +872,7 @@ func builderTest(b *work.Builder, ctx context.Context, p *load.Package) (buildAc
                        DeclVars: declareCoverVars,
                }
        }
-       pmain, ptest, pxtest, err := load.TestPackagesFor(ctx, p, cover)
+       pmain, ptest, pxtest, err := load.TestPackagesFor(ctx, pkgOpts, p, cover)
        if err != nil {
                return nil, nil, nil, err
        }
@@ -931,11 +945,11 @@ func builderTest(b *work.Builder, ctx context.Context, p *load.Package) (buildAc
        var installAction, cleanAction *work.Action
        if testC || testNeedBinary() {
                // -c or profiling flag: create action to copy binary to ./test.out.
-               target := filepath.Join(base.Cwd, testBinary+cfg.ExeSuffix)
+               target := filepath.Join(base.Cwd(), testBinary+cfg.ExeSuffix)
                if testO != "" {
                        target = testO
                        if !filepath.IsAbs(target) {
-                               target = filepath.Join(base.Cwd, target)
+                               target = filepath.Join(base.Cwd(), target)
                        }
                }
                if target == os.DevNull {
@@ -1326,7 +1340,8 @@ func (c *runCache) tryCacheWithID(b *work.Builder, a *work.Action, id string) bo
                        return false
                }
                switch arg[:i] {
-               case "-test.cpu",
+               case "-test.benchtime",
+                       "-test.cpu",
                        "-test.list",
                        "-test.parallel",
                        "-test.run",
@@ -1499,7 +1514,7 @@ func computeTestInputsID(a *work.Action, testlog []byte) (cache.ActionID, error)
                        if !filepath.IsAbs(name) {
                                name = filepath.Join(pwd, name)
                        }
-                       if a.Package.Root == "" || !inDir(name, a.Package.Root) {
+                       if a.Package.Root == "" || search.InDir(name, a.Package.Root) == "" {
                                // Do not recheck files outside the module, GOPATH, or GOROOT root.
                                break
                        }
@@ -1508,7 +1523,7 @@ func computeTestInputsID(a *work.Action, testlog []byte) (cache.ActionID, error)
                        if !filepath.IsAbs(name) {
                                name = filepath.Join(pwd, name)
                        }
-                       if a.Package.Root == "" || !inDir(name, a.Package.Root) {
+                       if a.Package.Root == "" || search.InDir(name, a.Package.Root) == "" {
                                // Do not recheck files outside the module, GOPATH, or GOROOT root.
                                break
                        }
@@ -1526,18 +1541,6 @@ func computeTestInputsID(a *work.Action, testlog []byte) (cache.ActionID, error)
        return sum, nil
 }
 
-func inDir(path, dir string) bool {
-       if str.HasFilePathPrefix(path, dir) {
-               return true
-       }
-       xpath, err1 := filepath.EvalSymlinks(path)
-       xdir, err2 := filepath.EvalSymlinks(dir)
-       if err1 == nil && err2 == nil && str.HasFilePathPrefix(xpath, xdir) {
-               return true
-       }
-       return false
-}
-
 func hashGetenv(name string) cache.ActionID {
        h := cache.NewHash("getenv")
        v, ok := os.LookupEnv(name)
index 10e6604da5f44b3b1c41f56f0653a667b7019196..08f1efa2c0d26a0cf398f2b778c0adde90fc97ae 100644 (file)
@@ -10,6 +10,7 @@ import (
        "fmt"
        "os"
        "path/filepath"
+       "strconv"
        "strings"
        "time"
 
@@ -61,15 +62,16 @@ func init() {
        cf.String("memprofilerate", "", "")
        cf.StringVar(&testMutexProfile, "mutexprofile", "", "")
        cf.String("mutexprofilefraction", "", "")
-       cf.Var(outputdirFlag{&testOutputDir}, "outputdir", "")
+       cf.Var(&testOutputDir, "outputdir", "")
        cf.Int("parallel", 0, "")
        cf.String("run", "", "")
        cf.Bool("short", false, "")
        cf.DurationVar(&testTimeout, "timeout", 10*time.Minute, "")
        cf.StringVar(&testTrace, "trace", "", "")
        cf.BoolVar(&testV, "v", false, "")
+       cf.Var(&testShuffle, "shuffle", "")
 
-       for name, _ := range passFlagToTest {
+       for name := range passFlagToTest {
                cf.Var(cf.Lookup(name).Value, "test."+name, "")
        }
 }
@@ -126,19 +128,26 @@ func (f stringFlag) Set(value string) error {
 // outputdirFlag implements the -outputdir flag.
 // It interprets an empty value as the working directory of the 'go' command.
 type outputdirFlag struct {
-       resolved *string
+       abs string
 }
 
-func (f outputdirFlag) String() string { return *f.resolved }
-func (f outputdirFlag) Set(value string) (err error) {
+func (f *outputdirFlag) String() string {
+       return f.abs
+}
+func (f *outputdirFlag) Set(value string) (err error) {
        if value == "" {
-               // The empty string implies the working directory of the 'go' command.
-               *f.resolved = base.Cwd
+               f.abs = ""
        } else {
-               *f.resolved, err = filepath.Abs(value)
+               f.abs, err = filepath.Abs(value)
        }
        return err
 }
+func (f *outputdirFlag) getAbs() string {
+       if f.abs == "" {
+               return base.Cwd()
+       }
+       return f.abs
+}
 
 // vetFlag implements the special parsing logic for the -vet flag:
 // a comma-separated list, with a distinguished value "off" and
@@ -194,6 +203,41 @@ func (f *vetFlag) Set(value string) error {
        return nil
 }
 
+type shuffleFlag struct {
+       on   bool
+       seed *int64
+}
+
+func (f *shuffleFlag) String() string {
+       if !f.on {
+               return "off"
+       }
+       if f.seed == nil {
+               return "on"
+       }
+       return fmt.Sprintf("%d", *f.seed)
+}
+
+func (f *shuffleFlag) Set(value string) error {
+       if value == "off" {
+               *f = shuffleFlag{on: false}
+               return nil
+       }
+
+       if value == "on" {
+               *f = shuffleFlag{on: true}
+               return nil
+       }
+
+       seed, err := strconv.ParseInt(value, 10, 64)
+       if err != nil {
+               return fmt.Errorf(`-shuffle argument must be "on", "off", or an int64: %v`, err)
+       }
+
+       *f = shuffleFlag{on: true, seed: &seed}
+       return nil
+}
+
 // testFlags processes the command line, grabbing -x and -c, rewriting known flags
 // to have "test" before them, and reading the command line for the test binary.
 // Unfortunately for us, we need to do our own flag processing because go test
@@ -367,7 +411,7 @@ func testFlags(args []string) (packageNames, passToTest []string) {
        // command. Set it explicitly if it is needed due to some other flag that
        // requests output.
        if testProfile() != "" && !outputDirSet {
-               injectedFlags = append(injectedFlags, "-test.outputdir="+testOutputDir)
+               injectedFlags = append(injectedFlags, "-test.outputdir="+testOutputDir.getAbs())
        }
 
        // If the user is explicitly passing -help or -h, show output
index 9feffe07656e84fa7fc821e5b52250d85077bedf..91485f6f745b1ffcc64fcbd95f3449cbcb2b7cb6 100644 (file)
@@ -1176,7 +1176,7 @@ func expand(match map[string]string, s string) string {
 // and import paths referring to a fully-qualified importPath
 // containing a VCS type (foo.com/repo.git/dir)
 var vcsPaths = []*vcsPath{
-       // Github
+       // GitHub
        {
                pathPrefix: "github.com",
                regexp:     lazyregexp.New(`^(?P<root>github\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`),
index 4257c90c97a193ca5a80b8a5a82abb04a98a1a81..1d419dddb98d6cdcc53ef5e3e6eb67b477531988 100644 (file)
@@ -53,8 +53,6 @@ See also: go fmt, go fix.
 }
 
 func runVet(ctx context.Context, cmd *base.Command, args []string) {
-       load.ModResolveTests = true
-
        vetFlags, pkgArgs := vetFlags(args)
 
        if cfg.DebugTrace != "" {
@@ -87,7 +85,8 @@ func runVet(ctx context.Context, cmd *base.Command, args []string) {
                }
        }
 
-       pkgs := load.PackagesAndErrors(ctx, pkgArgs)
+       pkgOpts := load.PackageOpts{ModResolveTests: true}
+       pkgs := load.PackagesAndErrors(ctx, pkgOpts, pkgArgs)
        load.CheckPackageErrors(pkgs)
        if len(pkgs) == 0 {
                base.Fatalf("no packages to vet")
@@ -98,7 +97,7 @@ func runVet(ctx context.Context, cmd *base.Command, args []string) {
 
        root := &work.Action{Mode: "go vet"}
        for _, p := range pkgs {
-               _, ptest, pxtest, err := load.TestPackagesFor(ctx, p, nil)
+               _, ptest, pxtest, err := load.TestPackagesFor(ctx, pkgOpts, p, nil)
                if err != nil {
                        base.Errorf("%v", err)
                        continue
index 781702100a09e8b596ce9d3a9095e7dc88ada578..08686cdfcf9f4c11e96587a99738a09aa62b4324 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build cmd_go_bootstrap
 // +build cmd_go_bootstrap
 
 // This code is compiled only into the bootstrap 'go' binary.
index 72fa2b2ca6aa349241d1e7ec8a0b96c23d3ed3fc..f177278eba1e7d9088014ee0ae246e2efb0dca39 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !cmd_go_bootstrap
 // +build !cmd_go_bootstrap
 
 // This code is compiled into the real 'go' binary, but it is not
@@ -27,7 +28,7 @@ import (
        "cmd/internal/browser"
 )
 
-// impatientInsecureHTTPClient is used in -insecure mode,
+// impatientInsecureHTTPClient is used with GOINSECURE,
 // when we're connecting to https servers that might not be there
 // or might be using self-signed certificates.
 var impatientInsecureHTTPClient = &http.Client{
index 2641ee62bfa5518b7d4500f9df55ffa8207afe3c..453af402b43dd9eb9208af234701127cfa887f25 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !windows
 // +build !windows
 
 package web
index aa5663355efb9c262012ed3b31d7954a73c6bc75..4d6ed2ec7f8c1dd0d9ab90f83f4478057c36b46d 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !windows
 // +build !windows
 
 package web
index 5320121102256fc5223626ed28d22be80f038405..2e00c0cb126c1b5face3adb872058e67ddbb8241 100644 (file)
@@ -349,7 +349,7 @@ func readpkglist(shlibpath string) (pkgs []*load.Package) {
                        if strings.HasPrefix(t, "pkgpath ") {
                                t = strings.TrimPrefix(t, "pkgpath ")
                                t = strings.TrimSuffix(t, ";")
-                               pkgs = append(pkgs, load.LoadImportWithFlags(t, base.Cwd, nil, &stk, nil, 0))
+                               pkgs = append(pkgs, load.LoadImportWithFlags(t, base.Cwd(), nil, &stk, nil, 0))
                        }
                }
        } else {
@@ -360,7 +360,7 @@ func readpkglist(shlibpath string) (pkgs []*load.Package) {
                scanner := bufio.NewScanner(bytes.NewBuffer(pkglistbytes))
                for scanner.Scan() {
                        t := scanner.Text()
-                       pkgs = append(pkgs, load.LoadImportWithFlags(t, base.Cwd, nil, &stk, nil, 0))
+                       pkgs = append(pkgs, load.LoadImportWithFlags(t, base.Cwd(), nil, &stk, nil, 0))
                }
        }
        return
@@ -781,7 +781,7 @@ func (b *Builder) linkSharedAction(mode, depMode BuildMode, shlib string, a1 *Ac
                                        }
                                }
                                var stk load.ImportStack
-                               p := load.LoadImportWithFlags(pkg, base.Cwd, nil, &stk, nil, 0)
+                               p := load.LoadImportWithFlags(pkg, base.Cwd(), nil, &stk, nil, 0)
                                if p.Error != nil {
                                        base.Fatalf("load %s: %v", pkg, p.Error)
                                }
index f024b07b229e03927acb59f4a83ee4dd682690dd..0ed2389cd5a81af6f3ff862dd275b9fb9ba0109e 100644 (file)
@@ -10,9 +10,7 @@ import (
        "fmt"
        "go/build"
        exec "internal/execabs"
-       "internal/goroot"
        "os"
-       "path"
        "path/filepath"
        "runtime"
        "strings"
@@ -21,13 +19,9 @@ import (
        "cmd/go/internal/cfg"
        "cmd/go/internal/fsys"
        "cmd/go/internal/load"
-       "cmd/go/internal/modfetch"
        "cmd/go/internal/modload"
        "cmd/go/internal/search"
        "cmd/go/internal/trace"
-
-       "golang.org/x/mod/modfile"
-       "golang.org/x/mod/module"
 )
 
 var CmdBuild = &base.Command{
@@ -71,7 +65,7 @@ and test commands:
        -p n
                the number of programs, such as build commands or
                test binaries, that can be run in parallel.
-               The default is the number of CPUs available.
+               The default is GOMAXPROCS, normally the number of CPUs available.
        -race
                enable data race detection.
                Supported only on linux/amd64, freebsd/amd64, darwin/amd64, windows/amd64,
@@ -134,8 +128,8 @@ and test commands:
                a build will run as if the disk file path exists with the contents
                given by the backing file paths, or as if the disk file path does not
                exist if its backing file path is empty. Support for the -overlay flag
-               has some limitations:importantly, cgo files included from outside the
-               include path must be  in the same directory as the Go package they are
+               has some limitations: importantly, cgo files included from outside the
+               include path must be in the same directory as the Go package they are
                included from, and overlays will not appear when binaries and tests are
                run through go run and go test respectively.
        -pkgdir dir
@@ -158,6 +152,8 @@ and test commands:
                a program to use to invoke toolchain programs like vet and asm.
                For example, instead of running asm, the go command will run
                'cmd args /path/to/asm <arguments for asm>'.
+               The TOOLEXEC_IMPORTPATH environment variable will be set,
+               matching 'go list -f {{.ImportPath}}' for the package being built.
 
 The -asmflags, -gccgoflags, -gcflags, and -ldflags flags accept a
 space-separated list of arguments to pass to an underlying tool
@@ -372,7 +368,7 @@ func runBuild(ctx context.Context, cmd *base.Command, args []string) {
        var b Builder
        b.Init()
 
-       pkgs := load.PackagesAndErrors(ctx, args)
+       pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{}, args)
        load.CheckPackageErrors(pkgs)
 
        explicitO := len(cfg.BuildO) > 0
@@ -592,7 +588,7 @@ func runInstall(ctx context.Context, cmd *base.Command, args []string) {
        }
 
        BuildInit()
-       pkgs := load.PackagesAndErrors(ctx, args)
+       pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{}, args)
        if cfg.ModulesEnabled && !modload.HasModRoot() {
                haveErrors := false
                allMissingErrors := true
@@ -762,145 +758,27 @@ func installOutsideModule(ctx context.Context, args []string) {
        modload.RootMode = modload.NoRoot
        modload.AllowMissingModuleImports()
        modload.Init()
-
-       // Check that the arguments satisfy syntactic constraints.
-       var version string
-       for _, arg := range args {
-               if i := strings.Index(arg, "@"); i >= 0 {
-                       version = arg[i+1:]
-                       if version == "" {
-                               base.Fatalf("go install %s: version must not be empty", arg)
-                       }
-                       break
-               }
-       }
-       patterns := make([]string, len(args))
-       for i, arg := range args {
-               if !strings.HasSuffix(arg, "@"+version) {
-                       base.Errorf("go install %s: all arguments must have the same version (@%s)", arg, version)
-                       continue
-               }
-               p := arg[:len(arg)-len(version)-1]
-               switch {
-               case build.IsLocalImport(p):
-                       base.Errorf("go install %s: argument must be a package path, not a relative path", arg)
-               case filepath.IsAbs(p):
-                       base.Errorf("go install %s: argument must be a package path, not an absolute path", arg)
-               case search.IsMetaPackage(p):
-                       base.Errorf("go install %s: argument must be a package path, not a meta-package", arg)
-               case path.Clean(p) != p:
-                       base.Errorf("go install %s: argument must be a clean package path", arg)
-               case !strings.Contains(p, "...") && search.IsStandardImportPath(p) && goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, p):
-                       base.Errorf("go install %s: argument must not be a package in the standard library", arg)
-               default:
-                       patterns[i] = p
-               }
-       }
-       base.ExitIfErrors()
        BuildInit()
 
-       // Query the module providing the first argument, load its go.mod file, and
-       // check that it doesn't contain directives that would cause it to be
-       // interpreted differently if it were the main module.
-       //
-       // If multiple modules match the first argument, accept the longest match
-       // (first result). It's possible this module won't provide packages named by
-       // later arguments, and other modules would. Let's not try to be too
-       // magical though.
-       allowed := modload.CheckAllowed
-       if modload.IsRevisionQuery(version) {
-               // Don't check for retractions if a specific revision is requested.
-               allowed = nil
-       }
-       noneSelected := func(path string) (version string) { return "none" }
-       qrs, err := modload.QueryPackages(ctx, patterns[0], version, noneSelected, allowed)
-       if err != nil {
-               base.Fatalf("go install %s: %v", args[0], err)
-       }
-       installMod := qrs[0].Mod
-       data, err := modfetch.GoMod(installMod.Path, installMod.Version)
-       if err != nil {
-               base.Fatalf("go install %s: %v", args[0], err)
-       }
-       f, err := modfile.Parse("go.mod", data, nil)
-       if err != nil {
-               base.Fatalf("go install %s: %s: %v", args[0], installMod, err)
-       }
-       directiveFmt := "go install %s: %s\n" +
-               "\tThe go.mod file for the module providing named packages contains one or\n" +
-               "\tmore %s directives. It must not contain directives that would cause\n" +
-               "\tit to be interpreted differently than if it were the main module."
-       if len(f.Replace) > 0 {
-               base.Fatalf(directiveFmt, args[0], installMod, "replace")
-       }
-       if len(f.Exclude) > 0 {
-               base.Fatalf(directiveFmt, args[0], installMod, "exclude")
-       }
-
-       // Since we are in NoRoot mode, the build list initially contains only
-       // the dummy command-line-arguments module. Add a requirement on the
-       // module that provides the packages named on the command line.
-       if err := modload.EditBuildList(ctx, nil, []module.Version{installMod}); err != nil {
-               base.Fatalf("go install %s: %v", args[0], err)
-       }
-
-       // Load packages for all arguments. Ignore non-main packages.
+       // Load packages. Ignore non-main packages.
        // Print a warning if an argument contains "..." and matches no main packages.
        // PackagesAndErrors already prints warnings for patterns that don't match any
        // packages, so be careful not to double print.
-       matchers := make([]func(string) bool, len(patterns))
-       for i, p := range patterns {
-               if strings.Contains(p, "...") {
-                       matchers[i] = search.MatchPattern(p)
-               }
-       }
-
        // TODO(golang.org/issue/40276): don't report errors loading non-main packages
        // matched by a pattern.
-       pkgs := load.PackagesAndErrors(ctx, patterns)
-       load.CheckPackageErrors(pkgs)
-       mainPkgs := make([]*load.Package, 0, len(pkgs))
-       mainCount := make([]int, len(patterns))
-       nonMainCount := make([]int, len(patterns))
-       for _, pkg := range pkgs {
-               if pkg.Name == "main" {
-                       mainPkgs = append(mainPkgs, pkg)
-                       for i := range patterns {
-                               if matchers[i] != nil && matchers[i](pkg.ImportPath) {
-                                       mainCount[i]++
-                               }
-                       }
-               } else {
-                       for i := range patterns {
-                               if matchers[i] == nil && patterns[i] == pkg.ImportPath {
-                                       base.Errorf("go install: package %s is not a main package", pkg.ImportPath)
-                               } else if matchers[i] != nil && matchers[i](pkg.ImportPath) {
-                                       nonMainCount[i]++
-                               }
-                       }
-               }
-       }
-       base.ExitIfErrors()
-       for i, p := range patterns {
-               if matchers[i] != nil && mainCount[i] == 0 && nonMainCount[i] > 0 {
-                       fmt.Fprintf(os.Stderr, "go: warning: %q matched no main packages\n", p)
-               }
+       pkgOpts := load.PackageOpts{MainOnly: true}
+       pkgs, err := load.PackagesAndErrorsOutsideModule(ctx, pkgOpts, args)
+       if err != nil {
+               base.Fatalf("go install: %v", err)
        }
-
-       // Check that named packages are all provided by the same module.
-       for _, pkg := range mainPkgs {
-               if pkg.Module == nil {
-                       // Packages in std, cmd, and their vendored dependencies
-                       // don't have this field set.
-                       base.Errorf("go install: package %s not provided by module %s", pkg.ImportPath, installMod)
-               } else if pkg.Module.Path != installMod.Path || pkg.Module.Version != installMod.Version {
-                       base.Errorf("go install: package %s provided by module %s@%s\n\tAll packages must be provided by the same module (%s).", pkg.ImportPath, pkg.Module.Path, pkg.Module.Version, installMod)
-               }
+       load.CheckPackageErrors(pkgs)
+       patterns := make([]string, len(args))
+       for i, arg := range args {
+               patterns[i] = arg[:strings.Index(arg, "@")]
        }
-       base.ExitIfErrors()
 
        // Build and install the packages.
-       InstallPackages(ctx, patterns, mainPkgs)
+       InstallPackages(ctx, patterns, pkgs)
 }
 
 // ExecCmd is the command to use to run user binaries.
index eaf2639e9e0deaa5e43f1acadb279bc146c4d1b7..600fc3083f0d506228fe1e26797013f94e11607b 100644 (file)
@@ -173,10 +173,11 @@ func TestSharedLibName(t *testing.T) {
                                if err != nil {
                                        t.Fatal(err)
                                }
+                               cwd := base.Cwd()
                                oldGopath := cfg.BuildContext.GOPATH
                                defer func() {
                                        cfg.BuildContext.GOPATH = oldGopath
-                                       os.Chdir(base.Cwd)
+                                       os.Chdir(cwd)
                                        err := os.RemoveAll(tmpGopath)
                                        if err != nil {
                                                t.Error(err)
index c555d4a9f1ed036367fbfc0a0ed4d4e748919e09..4e9189a36320ace016890c567fd241ffb92a7a87 100644 (file)
@@ -204,7 +204,7 @@ func (b *Builder) toolID(name string) string {
 // In order to get reproducible builds for released compilers, we
 // detect a released compiler by the absence of "experimental" in the
 // --version output, and in that case we just use the version string.
-func (b *Builder) gccgoToolID(name, language string) (string, error) {
+func (b *Builder) gccToolID(name, language string) (string, error) {
        key := name + "." + language
        b.id.Lock()
        id := b.toolIDCache[key]
index f354f3086e4b71dab7a8c35e0f9b2bc30d994eac..b0281041c9821b365198436bf4a6ea6b2854f140 100644 (file)
@@ -8,11 +8,11 @@ package work
 
 import (
        "bytes"
-       "cmd/go/internal/fsys"
        "context"
        "encoding/json"
        "errors"
        "fmt"
+       "internal/buildcfg"
        exec "internal/execabs"
        "internal/lazyregexp"
        "io"
@@ -31,6 +31,7 @@ import (
        "cmd/go/internal/base"
        "cmd/go/internal/cache"
        "cmd/go/internal/cfg"
+       "cmd/go/internal/fsys"
        "cmd/go/internal/load"
        "cmd/go/internal/modload"
        "cmd/go/internal/str"
@@ -245,17 +246,37 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID {
        if p.Internal.ForceLibrary {
                fmt.Fprintf(h, "forcelibrary\n")
        }
-       if len(p.CgoFiles)+len(p.SwigFiles) > 0 {
+       if len(p.CgoFiles)+len(p.SwigFiles)+len(p.SwigCXXFiles) > 0 {
                fmt.Fprintf(h, "cgo %q\n", b.toolID("cgo"))
                cppflags, cflags, cxxflags, fflags, ldflags, _ := b.CFlags(p)
-               fmt.Fprintf(h, "CC=%q %q %q %q\n", b.ccExe(), cppflags, cflags, ldflags)
-               if len(p.CXXFiles)+len(p.SwigFiles) > 0 {
-                       fmt.Fprintf(h, "CXX=%q %q\n", b.cxxExe(), cxxflags)
+
+               ccExe := b.ccExe()
+               fmt.Fprintf(h, "CC=%q %q %q %q\n", ccExe, cppflags, cflags, ldflags)
+               // Include the C compiler tool ID so that if the C
+               // compiler changes we rebuild the package.
+               // But don't do that for standard library packages like net,
+               // so that the prebuilt .a files from a Go binary install
+               // don't need to be rebuilt with the local compiler.
+               if !p.Standard {
+                       if ccID, err := b.gccToolID(ccExe[0], "c"); err == nil {
+                               fmt.Fprintf(h, "CC ID=%q\n", ccID)
+                       }
+               }
+               if len(p.CXXFiles)+len(p.SwigCXXFiles) > 0 {
+                       cxxExe := b.cxxExe()
+                       fmt.Fprintf(h, "CXX=%q %q\n", cxxExe, cxxflags)
+                       if cxxID, err := b.gccToolID(cxxExe[0], "c++"); err == nil {
+                               fmt.Fprintf(h, "CXX ID=%q\n", cxxID)
+                       }
                }
                if len(p.FFiles) > 0 {
-                       fmt.Fprintf(h, "FC=%q %q\n", b.fcExe(), fflags)
+                       fcExe := b.fcExe()
+                       fmt.Fprintf(h, "FC=%q %q\n", fcExe, fflags)
+                       if fcID, err := b.gccToolID(fcExe[0], "f95"); err == nil {
+                               fmt.Fprintf(h, "FC ID=%q\n", fcID)
+                       }
                }
-               // TODO(rsc): Should we include the SWIG version or Fortran/GCC/G++/Objective-C compiler versions?
+               // TODO(rsc): Should we include the SWIG version?
        }
        if p.Internal.CoverMode != "" {
                fmt.Fprintf(h, "cover %q %q\n", p.Internal.CoverMode, b.toolID("cover"))
@@ -276,6 +297,10 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID {
                key, val := cfg.GetArchEnv()
                fmt.Fprintf(h, "%s=%s\n", key, val)
 
+               if goexperiment := buildcfg.GOEXPERIMENT(); goexperiment != "" {
+                       fmt.Fprintf(h, "GOEXPERIMENT=%q\n", goexperiment)
+               }
+
                // TODO(rsc): Convince compiler team not to add more magic environment variables,
                // or perhaps restrict the environment variables passed to subprocesses.
                // Because these are clumsy, undocumented special-case hacks
@@ -284,7 +309,7 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID {
                magic := []string{
                        "GOCLOBBERDEADHASH",
                        "GOSSAFUNC",
-                       "GO_SSA_PHI_LOC_CUTOFF",
+                       "GOSSADIR",
                        "GOSSAHASH",
                }
                for _, env := range magic {
@@ -311,7 +336,7 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID {
                }
 
        case "gccgo":
-               id, err := b.gccgoToolID(BuildToolchain.compiler(), "go")
+               id, err := b.gccToolID(BuildToolchain.compiler(), "go")
                if err != nil {
                        base.Fatalf("%v", err)
                }
@@ -319,7 +344,7 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID {
                fmt.Fprintf(h, "pkgpath %s\n", gccgoPkgpath(p))
                fmt.Fprintf(h, "ar %q\n", BuildToolchain.(gccgoToolchain).ar())
                if len(p.SFiles) > 0 {
-                       id, _ = b.gccgoToolID(BuildToolchain.compiler(), "assembler-with-cpp")
+                       id, _ = b.gccToolID(BuildToolchain.compiler(), "assembler-with-cpp")
                        // Ignore error; different assembler versions
                        // are unlikely to make any difference anyhow.
                        fmt.Fprintf(h, "asm %q\n", id)
@@ -649,6 +674,10 @@ OverlayLoop:
                }
 
                outGo, outObj, err := b.cgo(a, base.Tool("cgo"), objdir, pcCFLAGS, pcLDFLAGS, mkAbsFiles(a.Package.Dir, cgofiles), gccfiles, cxxfiles, a.Package.MFiles, a.Package.FFiles)
+
+               // The files in cxxfiles have now been handled by b.cgo.
+               cxxfiles = nil
+
                if err != nil {
                        return err
                }
@@ -1248,6 +1277,10 @@ func (b *Builder) printLinkerConfig(h io.Writer, p *load.Package) {
                key, val := cfg.GetArchEnv()
                fmt.Fprintf(h, "%s=%s\n", key, val)
 
+               if goexperiment := buildcfg.GOEXPERIMENT(); goexperiment != "" {
+                       fmt.Fprintf(h, "GOEXPERIMENT=%q\n", goexperiment)
+               }
+
                // The linker writes source file paths that say GOROOT_FINAL, but
                // only if -trimpath is not specified (see ld() in gc.go).
                gorootFinal := cfg.GOROOT_FINAL
@@ -1263,7 +1296,7 @@ func (b *Builder) printLinkerConfig(h io.Writer, p *load.Package) {
                // Or external linker settings and flags?
 
        case "gccgo":
-               id, err := b.gccgoToolID(BuildToolchain.linker(), "go")
+               id, err := b.gccToolID(BuildToolchain.linker(), "go")
                if err != nil {
                        base.Fatalf("%v", err)
                }
@@ -1843,6 +1876,7 @@ var objectMagic = [][]byte{
        {0xCE, 0xFA, 0xED, 0xFE},                  // Mach-O little-endian 32-bit
        {0xCF, 0xFA, 0xED, 0xFE},                  // Mach-O little-endian 64-bit
        {0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00},      // PE (Windows) as generated by 6l/8l and gcc
+       {0x4d, 0x5a, 0x78, 0x00, 0x01, 0x00},      // PE (Windows) as generated by llvm for dll
        {0x00, 0x00, 0x01, 0xEB},                  // Plan 9 i386
        {0x00, 0x00, 0x8a, 0x97},                  // Plan 9 amd64
        {0x00, 0x00, 0x06, 0x47},                  // Plan 9 arm
@@ -2059,8 +2093,11 @@ func (b *Builder) runOut(a *Action, dir string, env []string, cmdargs ...interfa
 
        // Add the TOOLEXEC_IMPORTPATH environment variable for -toolexec tools.
        // It doesn't really matter if -toolexec isn't being used.
+       // Note that a.Package.Desc is not really an import path,
+       // but this is consistent with 'go list -f {{.ImportPath}}'.
+       // Plus, it is useful to uniquely identify packages in 'go list -json'.
        if a != nil && a.Package != nil {
-               cmd.Env = append(cmd.Env, "TOOLEXEC_IMPORTPATH="+a.Package.ImportPath)
+               cmd.Env = append(cmd.Env, "TOOLEXEC_IMPORTPATH="+a.Package.Desc())
        }
 
        cmd.Env = append(cmd.Env, env...)
@@ -2349,7 +2386,7 @@ func (b *Builder) gccld(a *Action, p *load.Package, objdir, outfile string, flag
 
        cmdargs := []interface{}{cmd, "-o", outfile, objs, flags}
        dir := p.Dir
-       out, err := b.runOut(a, base.Cwd, b.cCompilerEnv(), cmdargs...)
+       out, err := b.runOut(a, base.Cwd(), b.cCompilerEnv(), cmdargs...)
 
        if len(out) > 0 {
                // Filter out useless linker warnings caused by bugs outside Go.
@@ -2606,9 +2643,19 @@ func (b *Builder) gccArchArgs() []string {
        case "s390x":
                return []string{"-m64", "-march=z196"}
        case "mips64", "mips64le":
-               return []string{"-mabi=64"}
+               args := []string{"-mabi=64"}
+               if cfg.GOMIPS64 == "hardfloat" {
+                       return append(args, "-mhard-float")
+               } else if cfg.GOMIPS64 == "softfloat" {
+                       return append(args, "-msoft-float")
+               }
        case "mips", "mipsle":
-               return []string{"-mabi=32", "-march=mips32"}
+               args := []string{"-mabi=32", "-march=mips32"}
+               if cfg.GOMIPS == "hardfloat" {
+                       return append(args, "-mhard-float", "-mfp32", "-mno-odd-spreg")
+               } else if cfg.GOMIPS == "softfloat" {
+                       return append(args, "-msoft-float")
+               }
        case "ppc64":
                if cfg.Goos == "aix" {
                        return []string{"-maix64"}
@@ -2963,7 +3010,7 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe
        if p.Standard && p.ImportPath == "runtime/cgo" {
                cgoflags = []string{"-dynlinker"} // record path to dynamic linker
        }
-       return b.run(a, base.Cwd, p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags)
+       return b.run(a, base.Cwd(), p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags)
 }
 
 // Run SWIG on all SWIG input files.
@@ -3097,7 +3144,7 @@ func (b *Builder) swigDoIntSize(objdir string) (intsize string, err error) {
        }
        srcs := []string{src}
 
-       p := load.GoFilesPackage(context.TODO(), srcs)
+       p := load.GoFilesPackage(context.TODO(), load.PackageOpts{}, srcs)
 
        if _, _, e := BuildToolchain.gc(b, &Action{Mode: "swigDoIntSize", Package: p, Objdir: objdir}, "", nil, nil, "", false, srcs); e != nil {
                return "32", nil
index cc4e2b2b2b96553f0d899ca2f92e8f367bd4dea5..85da4f89f991f48e4ad9a3aad4b145f622363cb1 100644 (file)
@@ -8,6 +8,7 @@ import (
        "bufio"
        "bytes"
        "fmt"
+       "internal/buildcfg"
        "io"
        "log"
        "os"
@@ -63,15 +64,33 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg
 
        pkgpath := pkgPath(a)
        gcargs := []string{"-p", pkgpath}
-       if p.Module != nil && p.Module.GoVersion != "" && allowedVersion(p.Module.GoVersion) {
-               gcargs = append(gcargs, "-lang=go"+p.Module.GoVersion)
+       if p.Module != nil {
+               v := p.Module.GoVersion
+               if v == "" {
+                       // We started adding a 'go' directive to the go.mod file unconditionally
+                       // as of Go 1.12, so any module that still lacks such a directive must
+                       // either have been authored before then, or have a hand-edited go.mod
+                       // file that hasn't been updated by cmd/go since that edit.
+                       //
+                       // Unfortunately, through at least Go 1.16 we didn't add versions to
+                       // vendor/modules.txt. So this could also be a vendored 1.16 dependency.
+                       //
+                       // Fortunately, there were no breaking changes to the language between Go
+                       // 1.11 and 1.16, so if we assume Go 1.16 semantics we will not introduce
+                       // any spurious errors — we will only mask errors, and not particularly
+                       // important ones at that.
+                       v = "1.16"
+               }
+               if allowedVersion(v) {
+                       gcargs = append(gcargs, "-lang=go"+v)
+               }
        }
        if p.Standard {
                gcargs = append(gcargs, "-std")
        }
        compilingRuntime := p.Standard && (p.ImportPath == "runtime" || strings.HasPrefix(p.ImportPath, "runtime/internal"))
        // The runtime package imports a couple of general internal packages.
-       if p.Standard && (p.ImportPath == "internal/cpu" || p.ImportPath == "internal/bytealg") {
+       if p.Standard && (p.ImportPath == "internal/cpu" || p.ImportPath == "internal/bytealg" || p.ImportPath == "internal/abi") {
                compilingRuntime = true
        }
        if compilingRuntime {
@@ -129,7 +148,11 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg
                }
        }
 
-       args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", a.trimpath(), gcflags, gcargs, "-D", p.Internal.LocalPrefix}
+       args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", a.trimpath(), gcflags, gcargs}
+       if p.Internal.LocalPrefix != "" {
+               // Workaround #43883.
+               args = append(args, "-D", p.Internal.LocalPrefix)
+       }
        if importcfg != nil {
                if err := b.writeFile(objdir+"importcfg", importcfg); err != nil {
                        return "", nil, err
@@ -174,7 +197,7 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg
                args = append(args, f)
        }
 
-       output, err = b.runOut(a, base.Cwd, nil, args...)
+       output, err = b.runOut(a, base.Cwd(), nil, args...)
        return ofile, output, err
 }
 
@@ -209,7 +232,7 @@ CheckFlags:
        }
 
        // TODO: Test and delete these conditions.
-       if objabi.Fieldtrack_enabled != 0 || objabi.Preemptibleloops_enabled != 0 {
+       if buildcfg.Experiment.FieldTrack || buildcfg.Experiment.PreemptibleLoops {
                canDashC = false
        }
 
@@ -235,16 +258,19 @@ CheckFlags:
        //   - it has no successor packages to compile (usually package main)
        //   - all paths through the build graph pass through it
        //   - critical path scheduling says it is high priority
-       // and in such a case, set c to runtime.NumCPU.
+       // and in such a case, set c to runtime.GOMAXPROCS(0).
+       // By default this is the same as runtime.NumCPU.
        // We do this now when p==1.
+       // To limit parallelism, set GOMAXPROCS below numCPU; this may be useful
+       // on a low-memory builder, or if a deterministic build order is required.
+       c := runtime.GOMAXPROCS(0)
        if cfg.BuildP == 1 {
-               // No process parallelism. Max out c.
-               return runtime.NumCPU()
+               // No process parallelism, do not cap compiler parallelism.
+               return c
        }
-       // Some process parallelism. Set c to min(4, numcpu).
-       c := 4
-       if ncpu := runtime.NumCPU(); ncpu < c {
-               c = ncpu
+       // Some process parallelism. Set c to min(4, maxprocs).
+       if c > 4 {
+               c = 4
        }
        return c
 }
@@ -265,10 +291,11 @@ func (a *Action) trimpath() string {
 
        rewriteDir := a.Package.Dir
        if cfg.BuildTrimpath {
+               importPath := a.Package.Internal.OrigImportPath
                if m := a.Package.Module; m != nil && m.Version != "" {
-                       rewriteDir = m.Path + "@" + m.Version + strings.TrimPrefix(a.Package.ImportPath, m.Path)
+                       rewriteDir = m.Path + "@" + m.Version + strings.TrimPrefix(importPath, m.Path)
                } else {
-                       rewriteDir = a.Package.ImportPath
+                       rewriteDir = importPath
                }
                rewrite += a.Package.Dir + "=>" + rewriteDir + ";"
        }
@@ -336,18 +363,6 @@ func asmArgs(a *Action, p *load.Package) []interface{} {
        }
        if objabi.IsRuntimePackagePath(pkgpath) {
                args = append(args, "-compiling-runtime")
-               if objabi.Regabi_enabled != 0 {
-                       // In order to make it easier to port runtime assembly
-                       // to the register ABI, we introduce a macro
-                       // indicating the experiment is enabled.
-                       //
-                       // Note: a similar change also appears in
-                       // cmd/dist/build.go.
-                       //
-                       // TODO(austin): Remove this once we commit to the
-                       // register ABI (#40724).
-                       args = append(args, "-D=GOEXPERIMENT_REGABI=1")
-               }
        }
 
        if cfg.Goarch == "mips" || cfg.Goarch == "mipsle" {
index 36b3f4b05a02d8ef3c531b25315b3d48a812bf04..1e8250002eec1261f91350929bbab7351fd24988 100644 (file)
@@ -102,7 +102,7 @@ func (tools gccgoToolchain) gc(b *Builder, a *Action, archive string, importcfg,
 
        if b.gccSupportsFlag(args[:1], "-ffile-prefix-map=a=b") {
                if cfg.BuildTrimpath {
-                       args = append(args, "-ffile-prefix-map="+base.Cwd+"=.")
+                       args = append(args, "-ffile-prefix-map="+base.Cwd()+"=.")
                        args = append(args, "-ffile-prefix-map="+b.WorkDir+"=/tmp/go-build")
                }
                if fsys.OverlayFile != "" {
@@ -114,9 +114,9 @@ func (tools gccgoToolchain) gc(b *Builder, a *Action, archive string, importcfg,
                                }
                                toPath := absPath
                                // gccgo only applies the last matching rule, so also handle the case where
-                               // BuildTrimpath is true and the path is relative to base.Cwd.
-                               if cfg.BuildTrimpath && str.HasFilePathPrefix(toPath, base.Cwd) {
-                                       toPath = "." + toPath[len(base.Cwd):]
+                               // BuildTrimpath is true and the path is relative to base.Cwd().
+                               if cfg.BuildTrimpath && str.HasFilePathPrefix(toPath, base.Cwd()) {
+                                       toPath = "." + toPath[len(base.Cwd()):]
                                }
                                args = append(args, "-ffile-prefix-map="+overlayPath+"="+toPath)
                        }
@@ -597,7 +597,7 @@ func (tools gccgoToolchain) cc(b *Builder, a *Action, ofile, cfile string) error
        }
        defs = tools.maybePIC(defs)
        if b.gccSupportsFlag(compiler, "-ffile-prefix-map=a=b") {
-               defs = append(defs, "-ffile-prefix-map="+base.Cwd+"=.")
+               defs = append(defs, "-ffile-prefix-map="+base.Cwd()+"=.")
                defs = append(defs, "-ffile-prefix-map="+b.WorkDir+"=/tmp/go-build")
        } else if b.gccSupportsFlag(compiler, "-fdebug-prefix-map=a=b") {
                defs = append(defs, "-fdebug-prefix-map="+b.WorkDir+"=/tmp/go-build")
index ba7c7c2fbb18d95b456e6e0973006ec3d48ab411..37a3e2d0ffd1232368863992603432fbd783e828 100644 (file)
@@ -11,21 +11,19 @@ import (
        "cmd/go/internal/cfg"
        "cmd/go/internal/fsys"
        "cmd/go/internal/modload"
-       "cmd/internal/objabi"
        "cmd/internal/sys"
        "flag"
        "fmt"
        "os"
        "path/filepath"
        "runtime"
-       "strings"
 )
 
 func BuildInit() {
        modload.Init()
        instrumentInit()
        buildModeInit()
-       if err := fsys.Init(base.Cwd); err != nil {
+       if err := fsys.Init(base.Cwd()); err != nil {
                base.Fatalf("go: %v", err)
        }
 
@@ -47,20 +45,6 @@ func BuildInit() {
                        base.Fatalf("go %s: %s environment variable is relative; must be absolute path: %s\n", flag.Args()[0], key, path)
                }
        }
-
-       // For each experiment that has been enabled in the toolchain, define a
-       // build tag with the same name but prefixed by "goexperiment." which can be
-       // used for compiling alternative files for the experiment. This allows
-       // changes for the experiment, like extra struct fields in the runtime,
-       // without affecting the base non-experiment code at all. [2:] strips the
-       // leading "X:" from objabi.Expstring().
-       exp := objabi.Expstring()[2:]
-       if exp != "none" {
-               experiments := strings.Split(exp, ",")
-               for _, expt := range experiments {
-                       cfg.BuildContext.BuildTags = append(cfg.BuildContext.BuildTags, "goexperiment."+expt)
-               }
-       }
 }
 
 func instrumentInit() {
index 36bbab37ee23e89943f26a543e5a230ae1fb70a0..e9b9f6c6c0f24417652309b4d2b13b098677db73 100644 (file)
@@ -208,8 +208,8 @@ var validLinkerFlags = []*lazyregexp.Regexp{
        re(`-Wl,-z,(no)?execstack`),
        re(`-Wl,-z,relro`),
 
-       re(`[a-zA-Z0-9_/].*\.(a|o|obj|dll|dylib|so)`), // direct linker inputs: x.o or libfoo.so (but not -foo.o or @foo.o)
-       re(`\./.*\.(a|o|obj|dll|dylib|so)`),
+       re(`[a-zA-Z0-9_/].*\.(a|o|obj|dll|dylib|so|tbd)`), // direct linker inputs: x.o or libfoo.so (but not -foo.o or @foo.o)
+       re(`\./.*\.(a|o|obj|dll|dylib|so|tbd)`),
 }
 
 var validLinkerFlagsWithNextArg = []string{
index 4f2e0eb21ab842dd80c4425fa806ca2998000f73..8d4be0abfc09e6c21c9a51ea6a32696c4fa6e259 100644 (file)
@@ -164,6 +164,8 @@ var goodLinkerFlags = [][]string{
        {"-Wl,-framework", "-Wl,Chocolate"},
        {"-Wl,-framework,Chocolate"},
        {"-Wl,-unresolved-symbols=ignore-all"},
+       {"libcgotbdtest.tbd"},
+       {"./libcgotbdtest.tbd"},
 }
 
 var badLinkerFlags = [][]string{
index 931f49a0691d278b490dad919b40e0e1e7e0716b..8b77871b23f26922b4612c9017522710f1511af5 100644 (file)
@@ -4,6 +4,7 @@
 
 // This file contains extra hooks for testing the go command.
 
+//go:build testgo
 // +build testgo
 
 package work
index c4af1955d12a082a76b57b1832c90d25b183aa90..a3251723c55d635e8060c2d399020ad3a15a027d 100644 (file)
@@ -10,6 +10,7 @@ import (
        "context"
        "flag"
        "fmt"
+       "internal/buildcfg"
        "log"
        "os"
        "path/filepath"
@@ -147,19 +148,6 @@ func main() {
                os.Exit(2)
        }
 
-       // Set environment (GOOS, GOARCH, etc) explicitly.
-       // In theory all the commands we invoke should have
-       // the same default computation of these as we do,
-       // but in practice there might be skew
-       // This makes sure we all agree.
-       cfg.OrigEnv = os.Environ()
-       cfg.CmdEnv = envcmd.MkEnv()
-       for _, env := range cfg.CmdEnv {
-               if os.Getenv(env.Name) != env.Value {
-                       os.Setenv(env.Name, env.Value)
-               }
-       }
-
 BigCmdLoop:
        for bigCmd := base.Go; ; {
                for _, cmd := range bigCmd.Commands {
@@ -185,18 +173,7 @@ BigCmdLoop:
                        if !cmd.Runnable() {
                                continue
                        }
-                       cmd.Flag.Usage = func() { cmd.Usage() }
-                       if cmd.CustomFlags {
-                               args = args[1:]
-                       } else {
-                               base.SetFromGOFLAGS(&cmd.Flag)
-                               cmd.Flag.Parse(args[1:])
-                               args = cmd.Flag.Args()
-                       }
-                       ctx := maybeStartTrace(context.Background())
-                       ctx, span := trace.StartSpan(ctx, fmt.Sprint("Running ", cmd.Name(), " command"))
-                       cmd.Run(ctx, cmd, args)
-                       span.Done()
+                       invoke(cmd, args)
                        base.Exit()
                        return
                }
@@ -210,6 +187,39 @@ BigCmdLoop:
        }
 }
 
+func invoke(cmd *base.Command, args []string) {
+       // 'go env' handles checking the build config
+       if cmd != envcmd.CmdEnv {
+               buildcfg.Check()
+       }
+
+       // Set environment (GOOS, GOARCH, etc) explicitly.
+       // In theory all the commands we invoke should have
+       // the same default computation of these as we do,
+       // but in practice there might be skew
+       // This makes sure we all agree.
+       cfg.OrigEnv = os.Environ()
+       cfg.CmdEnv = envcmd.MkEnv()
+       for _, env := range cfg.CmdEnv {
+               if os.Getenv(env.Name) != env.Value {
+                       os.Setenv(env.Name, env.Value)
+               }
+       }
+
+       cmd.Flag.Usage = func() { cmd.Usage() }
+       if cmd.CustomFlags {
+               args = args[1:]
+       } else {
+               base.SetFromGOFLAGS(&cmd.Flag)
+               cmd.Flag.Parse(args[1:])
+               args = cmd.Flag.Args()
+       }
+       ctx := maybeStartTrace(context.Background())
+       ctx, span := trace.StartSpan(ctx, fmt.Sprint("Running ", cmd.Name(), " command"))
+       cmd.Run(ctx, cmd, args)
+       span.Done()
+}
+
 func init() {
        base.Usage = mainUsage
 }
index 72886db1eac7e695067246756abdabc7bf54969f..a2b0aca3c9da65b1c588b5e875bf61e799e289f6 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # Copyright 2012 The Go Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style
 # license that can be found in the LICENSE file.
@@ -6,6 +6,8 @@
 set -e
 
 go build -o go.latest
-./go.latest help documentation >alldocs.go
+# If the command used to generate alldocs.go changes, update TestDocsUpToDate in
+# help_test.go.
+GO111MODULE='' ./go.latest help documentation >alldocs.go
 gofmt -w alldocs.go
 rm go.latest
index e390c73a9cfa06aa71975c13fade24b2d8c60812..74bfecc08dbc6de1ca9768c536113eb878d7f3da 100644 (file)
@@ -23,7 +23,6 @@ import (
        "sync"
        "testing"
 
-       "cmd/go/internal/modfetch"
        "cmd/go/internal/modfetch/codehost"
        "cmd/go/internal/par"
        "cmd/go/internal/txtar"
@@ -229,7 +228,7 @@ func proxyHandler(w http.ResponseWriter, r *http.Request) {
                        if m.Path != modPath {
                                continue
                        }
-                       if modfetch.IsPseudoVersion(m.Version) && (latestPseudo == "" || semver.Compare(latestPseudo, m.Version) > 0) {
+                       if module.IsPseudoVersion(m.Version) && (latestPseudo == "" || semver.Compare(latestPseudo, m.Version) > 0) {
                                latestPseudo = m.Version
                        } else if semver.Prerelease(m.Version) != "" && (latestPrerelease == "" || semver.Compare(latestPrerelease, m.Version) > 0) {
                                latestPrerelease = m.Version
@@ -282,7 +281,7 @@ func proxyHandler(w http.ResponseWriter, r *http.Request) {
                                continue
                        }
                        found = true
-                       if !modfetch.IsPseudoVersion(m.Version) {
+                       if !module.IsPseudoVersion(m.Version) {
                                if err := module.Check(m.Path, m.Version); err == nil {
                                        fmt.Fprintf(w, "%s\n", m.Version)
                                }
@@ -315,7 +314,7 @@ func proxyHandler(w http.ResponseWriter, r *http.Request) {
                for _, m := range modList {
                        if m.Path == path && semver.Compare(best, m.Version) < 0 {
                                var hash string
-                               if modfetch.IsPseudoVersion(m.Version) {
+                               if module.IsPseudoVersion(m.Version) {
                                        hash = m.Version[strings.LastIndex(m.Version, "-")+1:]
                                } else {
                                        hash = findHash(m)
@@ -362,7 +361,7 @@ func proxyHandler(w http.ResponseWriter, r *http.Request) {
                        var buf bytes.Buffer
                        z := zip.NewWriter(&buf)
                        for _, f := range a.Files {
-                               if strings.HasPrefix(f.Name, ".") {
+                               if f.Name == ".info" || f.Name == ".mod" || f.Name == ".zip" {
                                        continue
                                }
                                var zipName string
index dfaa40548e44d8df9f10ef873d566f1a684cdbd5..639e907db075159dd5aba227d38e7ec9261127bf 100644 (file)
@@ -32,7 +32,6 @@ import (
        "cmd/go/internal/robustio"
        "cmd/go/internal/txtar"
        "cmd/go/internal/work"
-       "cmd/internal/objabi"
        "cmd/internal/sys"
 )
 
@@ -41,6 +40,33 @@ func TestScript(t *testing.T) {
        testenv.MustHaveGoBuild(t)
        testenv.SkipIfShortAndSlow(t)
 
+       var (
+               ctx         = context.Background()
+               gracePeriod = 100 * time.Millisecond
+       )
+       if deadline, ok := t.Deadline(); ok {
+               timeout := time.Until(deadline)
+
+               // If time allows, increase the termination grace period to 5% of the
+               // remaining time.
+               if gp := timeout / 20; gp > gracePeriod {
+                       gracePeriod = gp
+               }
+
+               // When we run commands that execute subprocesses, we want to reserve two
+               // grace periods to clean up. We will send the first termination signal when
+               // the context expires, then wait one grace period for the process to
+               // produce whatever useful output it can (such as a stack trace). After the
+               // first grace period expires, we'll escalate to os.Kill, leaving the second
+               // grace period for the test function to record its output before the test
+               // process itself terminates.
+               timeout -= 2 * gracePeriod
+
+               var cancel context.CancelFunc
+               ctx, cancel = context.WithTimeout(ctx, timeout)
+               t.Cleanup(cancel)
+       }
+
        files, err := filepath.Glob("testdata/script/*.txt")
        if err != nil {
                t.Fatal(err)
@@ -50,40 +76,51 @@ func TestScript(t *testing.T) {
                name := strings.TrimSuffix(filepath.Base(file), ".txt")
                t.Run(name, func(t *testing.T) {
                        t.Parallel()
-                       ts := &testScript{t: t, name: name, file: file}
+                       ctx, cancel := context.WithCancel(ctx)
+                       ts := &testScript{
+                               t:           t,
+                               ctx:         ctx,
+                               cancel:      cancel,
+                               gracePeriod: gracePeriod,
+                               name:        name,
+                               file:        file,
+                       }
                        ts.setup()
                        if !*testWork {
                                defer removeAll(ts.workdir)
                        }
                        ts.run()
+                       cancel()
                })
        }
 }
 
 // A testScript holds execution state for a single test script.
 type testScript struct {
-       t          *testing.T
-       workdir    string            // temporary work dir ($WORK)
-       log        bytes.Buffer      // test execution log (printed at end of test)
-       mark       int               // offset of next log truncation
-       cd         string            // current directory during test execution; initially $WORK/gopath/src
-       name       string            // short name of test ("foo")
-       file       string            // full file name ("testdata/script/foo.txt")
-       lineno     int               // line number currently executing
-       line       string            // line currently executing
-       env        []string          // environment list (for os/exec)
-       envMap     map[string]string // environment mapping (matches env)
-       stdout     string            // standard output from last 'go' command; for 'stdout' command
-       stderr     string            // standard error from last 'go' command; for 'stderr' command
-       stopped    bool              // test wants to stop early
-       start      time.Time         // time phase started
-       background []*backgroundCmd  // backgrounded 'exec' and 'go' commands
+       t           *testing.T
+       ctx         context.Context
+       cancel      context.CancelFunc
+       gracePeriod time.Duration
+       workdir     string            // temporary work dir ($WORK)
+       log         bytes.Buffer      // test execution log (printed at end of test)
+       mark        int               // offset of next log truncation
+       cd          string            // current directory during test execution; initially $WORK/gopath/src
+       name        string            // short name of test ("foo")
+       file        string            // full file name ("testdata/script/foo.txt")
+       lineno      int               // line number currently executing
+       line        string            // line currently executing
+       env         []string          // environment list (for os/exec)
+       envMap      map[string]string // environment mapping (matches env)
+       stdout      string            // standard output from last 'go' command; for 'stdout' command
+       stderr      string            // standard error from last 'go' command; for 'stderr' command
+       stopped     bool              // test wants to stop early
+       start       time.Time         // time phase started
+       background  []*backgroundCmd  // backgrounded 'exec' and 'go' commands
 }
 
 type backgroundCmd struct {
        want           simpleStatus
        args           []string
-       cancel         context.CancelFunc
        done           <-chan struct{}
        err            error
        stdout, stderr strings.Builder
@@ -109,6 +146,10 @@ var extraEnvKeys = []string{
 
 // setup sets up the test execution temporary directory and environment.
 func (ts *testScript) setup() {
+       if err := ts.ctx.Err(); err != nil {
+               ts.t.Fatalf("test interrupted during setup: %v", err)
+       }
+
        StartProxy()
        ts.workdir = filepath.Join(testTmpDir, "script-"+ts.name)
        ts.check(os.MkdirAll(filepath.Join(ts.workdir, "tmp"), 0777))
@@ -123,13 +164,13 @@ func (ts *testScript) setup() {
                "GOCACHE=" + testGOCACHE,
                "GODEBUG=" + os.Getenv("GODEBUG"),
                "GOEXE=" + cfg.ExeSuffix,
-               "GOEXPSTRING=" + objabi.Expstring()[2:],
                "GOOS=" + runtime.GOOS,
                "GOPATH=" + filepath.Join(ts.workdir, "gopath"),
                "GOPROXY=" + proxyURL,
                "GOPRIVATE=",
                "GOROOT=" + testGOROOT,
                "GOROOT_FINAL=" + os.Getenv("GOROOT_FINAL"), // causes spurious rebuilds and breaks the "stale" built-in if not propagated
+               "GOTRACEBACK=system",
                "TESTGO_GOROOT=" + testGOROOT,
                "GOSUMDB=" + testSumDBVerifierKey,
                "GONOPROXY=",
@@ -200,9 +241,7 @@ func (ts *testScript) run() {
                // On a normal exit from the test loop, background processes are cleaned up
                // before we print PASS. If we return early (e.g., due to a test failure),
                // don't print anything about the processes that were still running.
-               for _, bg := range ts.background {
-                       bg.cancel()
-               }
+               ts.cancel()
                for _, bg := range ts.background {
                        <-bg.done
                }
@@ -275,6 +314,10 @@ Script:
                fmt.Fprintf(&ts.log, "> %s\n", line)
 
                for _, cond := range parsed.conds {
+                       if err := ts.ctx.Err(); err != nil {
+                               ts.fatalf("test interrupted: %v", err)
+                       }
+
                        // Known conds are: $GOOS, $GOARCH, runtime.Compiler, and 'short' (for testing.Short).
                        //
                        // NOTE: If you make changes here, update testdata/script/README too!
@@ -356,9 +399,7 @@ Script:
                }
        }
 
-       for _, bg := range ts.background {
-               bg.cancel()
-       }
+       ts.cancel()
        ts.cmdWait(success, nil)
 
        // Final phase ended.
@@ -476,7 +517,7 @@ func (ts *testScript) cmdCd(want simpleStatus, args []string) {
                ts.fatalf("usage: cd dir")
        }
 
-       dir := args[0]
+       dir := filepath.FromSlash(args[0])
        if !filepath.IsAbs(dir) {
                dir = filepath.Join(ts.cd, dir)
        }
@@ -798,9 +839,7 @@ func (ts *testScript) cmdSkip(want simpleStatus, args []string) {
 
        // Before we mark the test as skipped, shut down any background processes and
        // make sure they have returned the correct status.
-       for _, bg := range ts.background {
-               bg.cancel()
-       }
+       ts.cancel()
        ts.cmdWait(success, nil)
 
        if len(args) == 1 {
@@ -1065,38 +1104,9 @@ func (ts *testScript) exec(command string, args ...string) (stdout, stderr strin
 func (ts *testScript) startBackground(want simpleStatus, command string, args ...string) (*backgroundCmd, error) {
        done := make(chan struct{})
        bg := &backgroundCmd{
-               want:   want,
-               args:   append([]string{command}, args...),
-               done:   done,
-               cancel: func() {},
-       }
-
-       ctx := context.Background()
-       gracePeriod := 100 * time.Millisecond
-       if deadline, ok := ts.t.Deadline(); ok {
-               timeout := time.Until(deadline)
-               // If time allows, increase the termination grace period to 5% of the
-               // remaining time.
-               if gp := timeout / 20; gp > gracePeriod {
-                       gracePeriod = gp
-               }
-
-               // Send the first termination signal with two grace periods remaining.
-               // If it still hasn't finished after the first period has elapsed,
-               // we'll escalate to os.Kill with a second period remaining until the
-               // test deadline..
-               timeout -= 2 * gracePeriod
-
-               if timeout <= 0 {
-                       // The test has less than the grace period remaining. There is no point in
-                       // even starting the command, because it will be terminated immediately.
-                       // Save the expense of starting it in the first place.
-                       bg.err = context.DeadlineExceeded
-                       close(done)
-                       return bg, nil
-               }
-
-               ctx, bg.cancel = context.WithTimeout(ctx, timeout)
+               want: want,
+               args: append([]string{command}, args...),
+               done: done,
        }
 
        cmd := exec.Command(command, args...)
@@ -1105,29 +1115,16 @@ func (ts *testScript) startBackground(want simpleStatus, command string, args ..
        cmd.Stdout = &bg.stdout
        cmd.Stderr = &bg.stderr
        if err := cmd.Start(); err != nil {
-               bg.cancel()
                return nil, err
        }
 
        go func() {
-               bg.err = waitOrStop(ctx, cmd, stopSignal(), gracePeriod)
+               bg.err = waitOrStop(ts.ctx, cmd, quitSignal(), ts.gracePeriod)
                close(done)
        }()
        return bg, nil
 }
 
-// stopSignal returns the appropriate signal to use to request that a process
-// stop execution.
-func stopSignal() os.Signal {
-       if runtime.GOOS == "windows" {
-               // Per https://golang.org/pkg/os/#Signal, “Interrupt is not implemented on
-               // Windows; using it with os.Process.Signal will return an error.”
-               // Fall back to Kill instead.
-               return os.Kill
-       }
-       return os.Interrupt
-}
-
 // waitOrStop waits for the already-started command cmd by calling its Wait method.
 //
 // If cmd does not return before ctx is done, waitOrStop sends it the given interrupt signal.
diff --git a/libgo/go/cmd/go/stop_other_test.go b/libgo/go/cmd/go/stop_other_test.go
new file mode 100644 (file)
index 0000000..e1cc6cf
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !(aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris)
+// +build !aix
+// +build !darwin
+// +build !dragonfly
+// +build !freebsd
+// +build !js !wasm
+// +build !linux
+// +build !netbsd
+// +build !openbsd
+// +build !solaris
+
+package main_test
+
+import (
+       "os"
+       "runtime"
+)
+
+// quitSignal returns the appropriate signal to use to request that a process
+// quit execution.
+func quitSignal() os.Signal {
+       if runtime.GOOS == "windows" {
+               // Per https://golang.org/pkg/os/#Signal, “Interrupt is not implemented on
+               // Windows; using it with os.Process.Signal will return an error.”
+               // Fall back to Kill instead.
+               return os.Kill
+       }
+       return os.Interrupt
+}
diff --git a/libgo/go/cmd/go/stop_unix_test.go b/libgo/go/cmd/go/stop_unix_test.go
new file mode 100644 (file)
index 0000000..ac35b24
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris
+// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris
+
+package main_test
+
+import (
+       "os"
+       "syscall"
+)
+
+func quitSignal() os.Signal {
+       return syscall.SIGQUIT
+}
index 09fc8e713bcbcfbc9ad226567369df1f2387d446..03869e68defe0845c5cbdef60fa08f2fd3fdf42d 100644 (file)
@@ -22,10 +22,10 @@ import (
        "bytes"
        "flag"
        "fmt"
+       exec "internal/execabs"
        "io/fs"
        "log"
        "os"
-       exec "internal/execabs"
        "path/filepath"
        "strings"
 
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_ambiguous_a_b_v0.0.0-empty.txt b/libgo/go/cmd/go/testdata/mod/example.com_ambiguous_a_b_v0.0.0-empty.txt
new file mode 100644 (file)
index 0000000..a869519
--- /dev/null
@@ -0,0 +1,12 @@
+Module example.com/ambiguous/a/b is a suffix of example.com/a.
+This version contains no package.
+-- .mod --
+module example.com/ambiguous/a/b
+
+go 1.16
+-- .info --
+{"Version":"v0.0.0-empty"}
+-- go.mod --
+module example.com/ambiguous/a/b
+
+go 1.16
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_ambiguous_a_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_ambiguous_a_v1.0.0.txt
new file mode 100644 (file)
index 0000000..bb43826
--- /dev/null
@@ -0,0 +1,18 @@
+Module example.com/ambiguous/a is a prefix of example.com/a/b.
+It contains package example.com/a/b.
+-- .mod --
+module example.com/ambiguous/a
+
+go 1.16
+
+require example.com/ambiguous/a/b v0.0.0-empty
+-- .info --
+{"Version":"v1.0.0"}
+-- go.mod --
+module example.com/ambiguous/a
+
+go 1.16
+
+require example.com/ambiguous/a/b v0.0.0-empty
+-- b/b.go --
+package b
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0-exclude.txt b/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0-exclude.txt
new file mode 100644 (file)
index 0000000..c883d8a
--- /dev/null
@@ -0,0 +1,28 @@
+example.com/cmd contains main packages.
+
+-- .info --
+{"Version":"v1.0.0-exclude"}
+-- .mod --
+module example.com/cmd
+
+go 1.16
+
+exclude rsc.io/quote v1.5.2
+-- go.mod --
+module example.com/cmd
+
+go 1.16
+
+exclude rsc.io/quote v1.5.2
+-- a/a.go --
+package main
+
+func main() {}
+-- b/b.go --
+package main
+
+func main() {}
+-- err/err.go --
+package err
+
+var X = DoesNotCompile
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0-newerself.txt b/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0-newerself.txt
new file mode 100644 (file)
index 0000000..7670f29
--- /dev/null
@@ -0,0 +1,28 @@
+example.com/cmd contains main packages.
+
+-- .info --
+{"Version":"v1.0.0-newerself"}
+-- .mod --
+module example.com/cmd
+
+go 1.16
+
+require example.com/cmd v1.0.0
+-- go.mod --
+module example.com/cmd
+
+go 1.16
+
+require example.com/cmd v1.0.0
+-- a/a.go --
+package main
+
+func main() {}
+-- b/b.go --
+package main
+
+func main() {}
+-- err/err.go --
+package err
+
+var X = DoesNotCompile
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0-replace.txt b/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0-replace.txt
new file mode 100644 (file)
index 0000000..581a496
--- /dev/null
@@ -0,0 +1,28 @@
+example.com/cmd contains main packages.
+
+-- .info --
+{"Version":"v1.0.0-replace"}
+-- .mod --
+module example.com/cmd
+
+go 1.16
+
+replace rsc.io/quote => rsc.io/quote v1.5.2
+-- go.mod --
+module example.com/cmd
+
+go 1.16
+
+replace rsc.io/quote => rsc.io/quote v1.5.2
+-- a/a.go --
+package main
+
+func main() {}
+-- b/b.go --
+package main
+
+func main() {}
+-- err/err.go --
+package err
+
+var X = DoesNotCompile
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0.txt
new file mode 100644 (file)
index 0000000..c198139
--- /dev/null
@@ -0,0 +1,31 @@
+example.com/cmd contains main packages.
+
+v1.0.0 is the latest non-retracted version. Other versions contain errors or
+detectable problems.
+
+-- .info --
+{"Version":"v1.0.0"}
+-- .mod --
+module example.com/cmd
+
+go 1.16
+-- go.mod --
+module example.com/cmd
+
+go 1.16
+-- a/a.go --
+package main
+
+import "fmt"
+
+func main() { fmt.Println("a@v1.0.0") }
+-- b/b.go --
+package main
+
+import "fmt"
+
+func main() { fmt.Println("b@v1.0.0") }
+-- err/err.go --
+package err
+
+var X = DoesNotCompile
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.9.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.9.0.txt
new file mode 100644 (file)
index 0000000..9298afb
--- /dev/null
@@ -0,0 +1,30 @@
+example.com/cmd contains main packages.
+
+-- .info --
+{"Version":"v1.9.0"}
+-- .mod --
+module example.com/cmd
+
+go 1.16
+
+// this is a bad version
+retract v1.9.0
+-- go.mod --
+module example.com/cmd
+
+go 1.16
+
+// this is a bad version
+retract v1.9.0
+-- a/a.go --
+package main
+
+func main() {}
+-- b/b.go --
+package main
+
+func main() {}
+-- err/err.go --
+package err
+
+var X = DoesNotCompile
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_deprecated_a_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_deprecated_a_v1.0.0.txt
new file mode 100644 (file)
index 0000000..7c29621
--- /dev/null
@@ -0,0 +1,12 @@
+-- .info --
+{"Version":"v1.0.0"}
+-- .mod --
+module example.com/deprecated/a
+
+go 1.17
+-- go.mod --
+module example.com/deprecated/a
+
+go 1.17
+-- a.go --
+package a
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_deprecated_a_v1.9.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_deprecated_a_v1.9.0.txt
new file mode 100644 (file)
index 0000000..0613389
--- /dev/null
@@ -0,0 +1,14 @@
+-- .info --
+{"Version":"v1.9.0"}
+-- .mod --
+// Deprecated: in example.com/deprecated/a@v1.9.0
+module example.com/deprecated/a
+
+go 1.17
+-- go.mod --
+// Deprecated: in example.com/deprecated/a@v1.9.0
+module example.com/deprecated/a
+
+go 1.17
+-- a.go --
+package a
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_deprecated_b_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_deprecated_b_v1.0.0.txt
new file mode 100644 (file)
index 0000000..50006ae
--- /dev/null
@@ -0,0 +1,12 @@
+-- .info --
+{"Version":"v1.0.0"}
+-- .mod --
+module example.com/deprecated/b
+
+go 1.17
+-- go.mod --
+module example.com/deprecated/b
+
+go 1.17
+-- b.go --
+package b
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_deprecated_b_v1.9.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_deprecated_b_v1.9.0.txt
new file mode 100644 (file)
index 0000000..163d6b5
--- /dev/null
@@ -0,0 +1,14 @@
+-- .info --
+{"Version":"v1.9.0"}
+-- .mod --
+// Deprecated: in example.com/deprecated/b@v1.9.0
+module example.com/deprecated/b
+
+go 1.17
+-- go.mod --
+// Deprecated: in example.com/deprecated/b@v1.9.0
+module example.com/deprecated/b
+
+go 1.17
+-- b.go --
+package b
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_dotname_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_dotname_v1.0.0.txt
new file mode 100644 (file)
index 0000000..2ada3a3
--- /dev/null
@@ -0,0 +1,12 @@
+-- .info --
+{"Version":"v1.0.0"}
+-- .mod --
+module example.com/dotname
+
+go 1.16
+-- go.mod --
+module example.com/dotname
+
+go 1.16
+-- .dot/dot.go --
+package dot
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_incompatiblewithsub_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_incompatiblewithsub_v1.0.0.txt
new file mode 100644 (file)
index 0000000..435578d
--- /dev/null
@@ -0,0 +1,8 @@
+Module example.com/incompatiblewithsub has an incompatible version
+and a package in a subdirectory.
+-- .info --
+{"Version":"v1.0.0"}
+-- .mod --
+module example.com/incompatiblewithsub
+-- sub/sub.go --
+package sub
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_incompatiblewithsub_v2.0.0+incompatible.txt b/libgo/go/cmd/go/testdata/mod/example.com_incompatiblewithsub_v2.0.0+incompatible.txt
new file mode 100644 (file)
index 0000000..198ec17
--- /dev/null
@@ -0,0 +1,8 @@
+Module example.com/incompatiblewithsub has an incompatible version
+and a package in a subdirectory.
+-- .info --
+{"Version":"v2.0.0+incompatible"}
+-- .mod --
+module example.com/incompatiblewithsub
+-- sub/sub.go --
+package sub
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_quote_v1.5.2.txt b/libgo/go/cmd/go/testdata/mod/example.com_quote_v1.5.2.txt
new file mode 100644 (file)
index 0000000..05f7ae2
--- /dev/null
@@ -0,0 +1,9 @@
+This module is a replacement for rsc.io/quote, but its go.mod file declares
+a module path different from its location and the original module.
+
+-- .mod --
+module rsc.io/Quote
+
+go 1.14
+-- .info --
+{"Version":"v1.5.2"}
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_ambiguous_nested_v1.9.0-bad.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_ambiguous_nested_v1.9.0-bad.txt
new file mode 100644 (file)
index 0000000..f8e623d
--- /dev/null
@@ -0,0 +1,10 @@
+-- .mod --
+module example.com/retract/ambiguous/nested
+
+go 1.16
+
+retract v1.9.0-bad // nested modules are bad
+-- .info --
+{"Version":"v1.9.0-bad"}
+-- nested.go --
+package nested
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_ambiguous_other_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_ambiguous_other_v1.0.0.txt
new file mode 100644 (file)
index 0000000..5ee0139
--- /dev/null
@@ -0,0 +1,12 @@
+-- .mod --
+module example.com/retract/ambiguous/other
+
+go 1.16
+
+require example.com/retract/ambiguous v1.0.0
+-- .info --
+{"Version":"v1.0.0"}
+-- other.go --
+package other
+
+import _ "example.com/retract/ambiguous/nested"
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_ambiguous_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_ambiguous_v1.0.0.txt
new file mode 100644 (file)
index 0000000..c8eeb16
--- /dev/null
@@ -0,0 +1,9 @@
+-- .mod --
+module example.com/retract/ambiguous
+
+go 1.16
+-- .info --
+{"Version":"v1.0.0"}
+-- nested/nested.go --
+package nested
+
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_incompatible_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_incompatible_v1.0.0.txt
new file mode 100644 (file)
index 0000000..a987685
--- /dev/null
@@ -0,0 +1,19 @@
+The v1.0.0 release of example.com/retract/incompatible retracts
+v2.0.0+incompatible.
+
+-- .mod --
+module example.com/retract/incompatible
+
+go 1.16
+
+retract v2.0.0+incompatible
+-- .info --
+{"Version":"v1.0.0"}
+-- go.mod --
+module example.com/retract/incompatible
+
+go 1.16
+
+retract v2.0.0+incompatible
+-- incompatible.go --
+package incompatible
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_incompatible_v2.0.0+incompatible.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_incompatible_v2.0.0+incompatible.txt
new file mode 100644 (file)
index 0000000..c668dbb
--- /dev/null
@@ -0,0 +1,9 @@
+The v1.0.0 release of example.com/retract/incompatible retracts
+v2.0.0+incompatible.
+
+-- .mod --
+module example.com/retract/incompatible
+-- .info --
+{"Version":"v2.0.0+incompatible"}
+-- incompatible.go --
+package incompatible
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_missingmod_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_missingmod_v1.0.0.txt
new file mode 100644 (file)
index 0000000..1d8d810
--- /dev/null
@@ -0,0 +1,10 @@
+This version should be retracted, but the go.mod file for the version that would
+contain the retraction is not available.
+-- .mod --
+module example.com/retract/missingmod
+
+go 1.14
+-- .info --
+{"Version":"v1.0.0"}
+-- missingmod.go --
+package missingmod
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_missingmod_v1.9.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_missingmod_v1.9.0.txt
new file mode 100644 (file)
index 0000000..bba919e
--- /dev/null
@@ -0,0 +1,4 @@
+The go.mod file at this version will be loaded to check for retractions
+of earlier versions. However, the .mod file is not available.
+-- .info --
+{"Version":"v1.9.0"}
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-block.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-block.txt
new file mode 100644 (file)
index 0000000..c4a53e1
--- /dev/null
@@ -0,0 +1,6 @@
+-- .mod --
+module example.com/retract/rationale
+
+go 1.14
+-- .info --
+{"Version":"v1.0.0-block"}
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-blockwithcomment.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-blockwithcomment.txt
new file mode 100644 (file)
index 0000000..92573b6
--- /dev/null
@@ -0,0 +1,6 @@
+-- .mod --
+module example.com/retract/rationale
+
+go 1.14
+-- .info --
+{"Version":"v1.0.0-blockwithcomment"}
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-empty.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-empty.txt
new file mode 100644 (file)
index 0000000..1f0894a
--- /dev/null
@@ -0,0 +1,8 @@
+-- .mod --
+module example.com/retract/rationale
+
+go 1.14
+-- .info --
+{"Version":"v1.0.0-empty"}
+-- empty.go --
+package empty
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-long.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-long.txt
new file mode 100644 (file)
index 0000000..1b5e753
--- /dev/null
@@ -0,0 +1,8 @@
+-- .mod --
+module example.com/retract/rationale
+
+go 1.14
+-- .info --
+{"Version":"v1.0.0-long"}
+-- empty.go --
+package empty
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-multiline1.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-multiline1.txt
new file mode 100644 (file)
index 0000000..b1ffe27
--- /dev/null
@@ -0,0 +1,8 @@
+-- .mod --
+module example.com/retract/rationale
+
+go 1.14
+-- .info --
+{"Version":"v1.0.0-multiline1"}
+-- empty.go --
+package empty
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-multiline2.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-multiline2.txt
new file mode 100644 (file)
index 0000000..72f80b3
--- /dev/null
@@ -0,0 +1,8 @@
+-- .mod --
+module example.com/retract/rationale
+
+go 1.14
+-- .info --
+{"Version":"v1.0.0-multiline2"}
+-- empty.go --
+package empty
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-order.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-order.txt
new file mode 100644 (file)
index 0000000..1b04504
--- /dev/null
@@ -0,0 +1,6 @@
+-- .mod --
+module example.com/retract/rationale
+
+go 1.14
+-- .info --
+{"Version":"v1.0.0-order"}
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-unprintable.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-unprintable.txt
new file mode 100644 (file)
index 0000000..9496124
--- /dev/null
@@ -0,0 +1,8 @@
+-- .mod --
+module example.com/retract/rationale
+
+go 1.14
+-- .info --
+{"Version":"v1.0.0-unprintable"}
+-- empty.go --
+package empty
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.1-order.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.1-order.txt
new file mode 100644 (file)
index 0000000..3be7d5b
--- /dev/null
@@ -0,0 +1,6 @@
+-- .mod --
+module example.com/retract/rationale
+
+go 1.14
+-- .info --
+{"Version":"v1.0.1-order"}
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.9.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.9.0.txt
new file mode 100644 (file)
index 0000000..6975d4e
--- /dev/null
@@ -0,0 +1,48 @@
+Module example.com/retract/description retracts all versions of itself.
+The rationale comments have various problems.
+
+-- .mod --
+module example.com/retract/rationale
+
+go 1.14
+
+retract (
+       v1.0.0-empty
+
+       // short description
+       // more
+       //
+       // detail
+       v1.0.0-multiline1 // suffix
+       // after not included
+)
+
+// short description
+// more
+//
+// detail
+retract v1.0.0-multiline2 // suffix
+
+// loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong
+retract v1.0.0-long
+
+// Ends with a BEL character. Beep!\a
+retract v1.0.0-unprintable
+
+// block comment
+retract (
+       v1.0.0-block
+
+       // inner comment
+       v1.0.0-blockwithcomment
+)
+
+retract (
+       [v1.0.0-order, v1.0.0-order] // degenerate range
+       v1.0.0-order // single version
+
+       v1.0.1-order // single version
+       [v1.0.1-order, v1.0.1-order] // degenerate range
+)
+-- .info --
+{"Version":"v1.9.0"}
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rename_v1.0.0-bad.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rename_v1.0.0-bad.txt
new file mode 100644 (file)
index 0000000..25c4ff1
--- /dev/null
@@ -0,0 +1,16 @@
+Module example.com/retract/rename is renamed in a later version.
+
+This happens frequently when a repository is renamed or when a go.mod file
+is added for the first time with a custom module path.
+-- .info --
+{"Version":"v1.0.0-bad"}
+-- .mod --
+module example.com/retract/rename
+
+go 1.16
+-- go.mod --
+module example.com/retract/rename
+
+go 1.16
+-- rename.go --
+package rename
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rename_v1.9.0-new.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rename_v1.9.0-new.txt
new file mode 100644 (file)
index 0000000..9c08f71
--- /dev/null
@@ -0,0 +1,22 @@
+Module example.com/retract/rename is renamed in this version.
+
+This happens frequently when a repository is renamed or when a go.mod file
+is added for the first time with a custom module path.
+-- .info --
+{"Version":"v1.9.0-new"}
+-- .mod --
+module example.com/retract/newname
+
+go 1.16
+
+// bad
+retract v1.0.0-bad
+-- go.mod --
+module example.com/retract/newname
+
+go 1.16
+
+// bad
+retract v1.0.0-bad
+-- newname.go --
+package newname
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_self_all_v1.9.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_all_v1.9.0.txt
new file mode 100644 (file)
index 0000000..4dc486b
--- /dev/null
@@ -0,0 +1,14 @@
+Module example.com/retract/self/prev is a module that retracts its own
+latest version.
+
+No unretracted versions are available.
+
+-- .mod --
+module example.com/retract/self/all
+
+go 1.15
+
+retract v1.9.0 // bad
+
+-- .info --
+{"Version":"v1.9.0"}
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prerelease_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prerelease_v1.0.0.txt
new file mode 100644 (file)
index 0000000..04c2845
--- /dev/null
@@ -0,0 +1,16 @@
+Module example.com/retract/self/prerelease is a module that retracts its own
+latest version and all other release version.
+
+A pre-release version higher than the highest release version is still
+available, and that should be matched by @latest.
+
+-- .mod --
+module example.com/retract/self/prerelease
+
+go 1.15
+
+-- .info --
+{"Version":"v1.0.0"}
+
+-- p.go --
+package p
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prerelease_v1.9.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prerelease_v1.9.0.txt
new file mode 100644 (file)
index 0000000..7c1c047
--- /dev/null
@@ -0,0 +1,19 @@
+Module example.com/retract/self/prerelease is a module that retracts its own
+latest version and all other release version.
+
+A pre-release version higher than the highest release version is still
+available, and that should be matched by @latest.
+
+-- .mod --
+module example.com/retract/self/prerelease
+
+go 1.15
+
+retract v1.0.0 // bad
+retract v1.9.0 // self
+
+-- .info --
+{"Version":"v1.9.0"}
+
+-- p.go --
+package p
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prerelease_v1.9.1-pre.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prerelease_v1.9.1-pre.txt
new file mode 100644 (file)
index 0000000..abf44fd
--- /dev/null
@@ -0,0 +1,16 @@
+Module example.com/retract/self/prerelease is a module that retracts its own
+latest version and all other release version.
+
+A pre-release version higher than the highest release version is still
+available, and that should be matched by @latest.
+
+-- .mod --
+module example.com/retract/self/prerelease
+
+go 1.15
+
+-- .info --
+{"Version":"v1.9.1-pre"}
+
+-- p.go --
+package p
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prev_v1.0.0-bad.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prev_v1.0.0-bad.txt
new file mode 100644 (file)
index 0000000..095063d
--- /dev/null
@@ -0,0 +1,14 @@
+See example.com_retract_self_prev_v1.9.0.txt.
+
+This version is retracted.
+
+-- .mod --
+module example.com/retract/self/prev
+
+go 1.15
+
+-- .info --
+{"Version":"v1.0.0-bad"}
+
+-- p.go --
+package p
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prev_v1.1.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prev_v1.1.0.txt
new file mode 100644 (file)
index 0000000..27c3a39
--- /dev/null
@@ -0,0 +1,14 @@
+See example.com_retract_self_pref_v1.9.0.txt.
+
+This version is the latest (only) non-retracted version.
+
+-- .mod --
+module example.com/retract/self/prev
+
+go 1.15
+
+-- .info --
+{"Version":"v1.1.0"}
+
+-- p.go --
+package p
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prev_v1.9.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prev_v1.9.0.txt
new file mode 100644 (file)
index 0000000..03d6168
--- /dev/null
@@ -0,0 +1,18 @@
+Module example.com/retract/self/prev is a module that retracts its own
+latest version, as well as an earlier version.
+
+A previous unretracted release version, v1.1.0, is still available.
+
+-- .mod --
+module example.com/retract/self/prev
+
+go 1.15
+
+retract v1.0.0-bad // bad
+retract v1.9.0 // self
+
+-- .info --
+{"Version":"v1.9.0"}
+
+-- p.go --
+package p
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_self_pseudo_v0.0.0-20200325131415-0123456789ab b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_pseudo_v0.0.0-20200325131415-0123456789ab
new file mode 100644 (file)
index 0000000..f9ab41e
--- /dev/null
@@ -0,0 +1,20 @@
+See example.com_retract_self_pseudo_v1.9.0.txt.
+
+This version is not retracted. It should be returned by the proxy's
+@latest endpoint. It should match the @latest version query.
+
+TODO(golang.org/issue/24031): the proxy and proxy.golang.org both return
+the highest release version from the @latest endpoint, even if that
+version is retracted, so there is no way for the go command to
+discover an unretracted pseudo-version.
+
+-- .mod --
+module example.com/retract/self/pseudo
+
+go 1.15
+
+-- .info --
+{"Version":"v0.0.0-20200325131415-01234567890ab"}
+
+-- p.go --
+package p
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_self_pseudo_v1.0.0-bad.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_pseudo_v1.0.0-bad.txt
new file mode 100644 (file)
index 0000000..d47eda0
--- /dev/null
@@ -0,0 +1,14 @@
+See example.com_retract_self_pseudo_v1.9.0.txt.
+
+This version is retracted.
+
+-- .mod --
+module example.com/retract/self/pseudo
+
+go 1.15
+
+-- .info --
+{"Version":"v1.0.0-bad"}
+
+-- p.go --
+package p
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_self_pseudo_v1.9.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_pseudo_v1.9.0.txt
new file mode 100644 (file)
index 0000000..db09cc6
--- /dev/null
@@ -0,0 +1,16 @@
+Module example.com/retract/self/pseudo is a module that retracts its own
+latest version, as well as an earlier version.
+
+An unretracted pseudo-version is available.
+
+-- .mod --
+module example.com/retract/self/pseudo
+
+go 1.15
+
+retract v1.0.0-bad // bad
+retract v1.9.0 // self
+
+-- .info --
+{"Version":"v1.9.0"}
+
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_v1.0.0-bad.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_v1.0.0-bad.txt
new file mode 100644 (file)
index 0000000..2f996cf
--- /dev/null
@@ -0,0 +1,10 @@
+-- .mod --
+module example.com/retract
+
+go 1.15
+
+-- .info --
+{"Version":"v1.0.0-bad"}
+
+-- retract.go --
+package retract
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_v1.0.0-good.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_v1.0.0-good.txt
new file mode 100644 (file)
index 0000000..78152bb
--- /dev/null
@@ -0,0 +1,10 @@
+-- .mod --
+module example.com/retract
+
+go 1.15
+
+-- .info --
+{"Version":"v1.0.0-good"}
+
+-- retract.go --
+package retract
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_v1.0.0-unused.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_v1.0.0-unused.txt
new file mode 100644 (file)
index 0000000..3bc9e35
--- /dev/null
@@ -0,0 +1,10 @@
+-- .mod --
+module example.com/retract
+
+go 1.15
+
+-- .info --
+{"Version":"v1.0.0-unused"}
+
+-- retract.go --
+package retract
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_v1.1.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_v1.1.0.txt
new file mode 100644 (file)
index 0000000..18d6d83
--- /dev/null
@@ -0,0 +1,13 @@
+-- .mod --
+module example.com/retract
+
+go 1.15
+
+retract v1.0.0-bad // bad
+retract v1.0.0-unused // bad
+
+-- .info --
+{"Version":"v1.1.0"}
+
+-- retract.go --
+package retract
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_split-incompatible_subpkg_v0.1.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_split-incompatible_subpkg_v0.1.0.txt
new file mode 100644 (file)
index 0000000..edf5d48
--- /dev/null
@@ -0,0 +1,14 @@
+Written by hand.
+Test case for getting a package that has been moved to a nested module,
+with a +incompatible version (and thus no go.mod file) at the root module.
+
+-- .mod --
+module example.com/split-incompatible/subpkg
+-- .info --
+{"Version": "v0.1.0"}
+-- go.mod --
+module example.com/split-incompatible/subpkg
+
+go 1.16
+-- subpkg.go --
+package subpkg
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_split-incompatible_v2.0.0+incompatible.txt b/libgo/go/cmd/go/testdata/mod/example.com_split-incompatible_v2.0.0+incompatible.txt
new file mode 100644 (file)
index 0000000..35c3f27
--- /dev/null
@@ -0,0 +1,10 @@
+Written by hand.
+Test case for getting a package that has been moved to a nested module,
+with a +incompatible verison (and thus no go.mod file) at the root module.
+
+-- .mod --
+module example.com/split-incompatible
+-- .info --
+{"Version": "v2.0.0+incompatible"}
+-- subpkg/subpkg.go --
+package subpkg
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_split-incompatible_v2.1.0-pre+incompatible.txt b/libgo/go/cmd/go/testdata/mod/example.com_split-incompatible_v2.1.0-pre+incompatible.txt
new file mode 100644 (file)
index 0000000..917fc0f
--- /dev/null
@@ -0,0 +1,10 @@
+Written by hand.
+Test case for getting a package that has been moved to a nested module,
+with a +incompatible verison (and thus no go.mod file) at the root module.
+
+-- .mod --
+module example.com/split-incompatible
+-- .info --
+{"Version": "v2.1.0-pre+incompatible"}
+-- README.txt --
+subpkg has moved to module example.com/split-incompatible/subpkg
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_undeprecated_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_undeprecated_v1.0.0.txt
new file mode 100644 (file)
index 0000000..a68588e
--- /dev/null
@@ -0,0 +1,14 @@
+-- .info --
+{"Version":"v1.0.0"}
+-- .mod --
+// Deprecated: in v1.0.0
+module example.com/undeprecated
+
+go 1.17
+-- go.mod --
+// Deprecated: in v1.0.0
+module example.com/undeprecated
+
+go 1.17
+-- undeprecated.go --
+package undeprecated
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_undeprecated_v1.0.1.txt b/libgo/go/cmd/go/testdata/mod/example.com_undeprecated_v1.0.1.txt
new file mode 100644 (file)
index 0000000..ecabf32
--- /dev/null
@@ -0,0 +1,14 @@
+-- .info --
+{"Version":"v1.0.1"}
+-- .mod --
+// no longer deprecated
+module example.com/undeprecated
+
+go 1.17
+-- go.mod --
+// no longer deprecated
+module example.com/undeprecated
+
+go 1.17
+-- undeprecated.go --
+package undeprecated
diff --git a/libgo/go/cmd/go/testdata/mod/example.net_ambiguous_nested_v0.1.0.txt b/libgo/go/cmd/go/testdata/mod/example.net_ambiguous_nested_v0.1.0.txt
new file mode 100644 (file)
index 0000000..8c9de7a
--- /dev/null
@@ -0,0 +1,19 @@
+Written by hand.
+
+Test module containing a package that is also provided by a nested module tagged
+with the same version.
+
+-- .mod --
+module example.net/ambiguous/nested
+
+go 1.16
+-- .info --
+{"Version": "v0.1.0"}
+-- go.mod --
+module example.net/ambiguous/nested
+
+go 1.16
+-- pkg/pkg.go --
+// Package pkg exists in both example.net/ambiguous v0.1.0
+// and example.net/ambiguous/nested v0.1.0
+package pkg
diff --git a/libgo/go/cmd/go/testdata/mod/example.net_ambiguous_v0.1.0.txt b/libgo/go/cmd/go/testdata/mod/example.net_ambiguous_v0.1.0.txt
new file mode 100644 (file)
index 0000000..8fa6d83
--- /dev/null
@@ -0,0 +1,19 @@
+Written by hand.
+
+Test module containing a package that is also provided by a nested module tagged
+with the same version.
+
+-- .mod --
+module example.net/ambiguous
+
+go 1.16
+-- .info --
+{"Version": "v0.1.0"}
+-- go.mod --
+module example.net/ambiguous
+
+go 1.16
+-- nested/pkg/pkg.go --
+// Package pkg exists in both example.net/ambiguous v0.1.0
+// and example.net/ambiguous/nested v0.1.0
+package pkg
diff --git a/libgo/go/cmd/go/testdata/mod/example.net_ambiguous_v0.2.0.txt b/libgo/go/cmd/go/testdata/mod/example.net_ambiguous_v0.2.0.txt
new file mode 100644 (file)
index 0000000..7589ad7
--- /dev/null
@@ -0,0 +1,18 @@
+Written by hand.
+
+Test module containing a package that is also provided by a nested module tagged
+with the same version.
+
+-- .mod --
+module example.net/ambiguous
+
+go 1.16
+-- .info --
+{"Version": "v0.2.0"}
+-- go.mod --
+module example.net/ambiguous
+
+go 1.16
+-- nested/pkg/README.txt --
+// Package pkg no longer exists in this module at v0.2.0.
+// Find it in module example.net/ambiguous/nested instead.
diff --git a/libgo/go/cmd/go/testdata/mod/example.net_pkgadded_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.net_pkgadded_v1.0.0.txt
new file mode 100644 (file)
index 0000000..207e86a
--- /dev/null
@@ -0,0 +1,17 @@
+Written by hand.
+Test module with a root package added in v1.1.0
+and a subpackage added in v1.2.0.
+
+-- .mod --
+module example.net/pkgadded
+
+go 1.16
+-- .info --
+{"Version":"v1.0.0"}
+-- go.mod --
+module example.net/pkgadded
+
+go 1.16
+-- README.txt --
+We will add the package example.net/pkgadded in v1.1.0,
+and example.net/pkgadded/subpkg in v1.2.0.
diff --git a/libgo/go/cmd/go/testdata/mod/example.net_pkgadded_v1.1.0.txt b/libgo/go/cmd/go/testdata/mod/example.net_pkgadded_v1.1.0.txt
new file mode 100644 (file)
index 0000000..1c88de2
--- /dev/null
@@ -0,0 +1,19 @@
+Written by hand.
+Test module with a root package added in v1.1.0
+and a subpackage added in v1.2.0.
+
+-- .mod --
+module example.net/pkgadded
+
+go 1.16
+-- .info --
+{"Version":"v1.1.0"}
+-- go.mod --
+module example.net/pkgadded
+
+go 1.16
+-- README.txt --
+We will add the package example.net/pkgadded/subpkg in v1.2.0.
+-- pkgadded.go --
+// Package pkgadded was added in v1.1.0.
+package pkgadded
diff --git a/libgo/go/cmd/go/testdata/mod/example.net_pkgadded_v1.2.0.txt b/libgo/go/cmd/go/testdata/mod/example.net_pkgadded_v1.2.0.txt
new file mode 100644 (file)
index 0000000..922951a
--- /dev/null
@@ -0,0 +1,20 @@
+Written by hand.
+Test module with a root package added in v1.1.0
+and a subpackage added in v1.2.0.
+
+-- .mod --
+module example.net/pkgadded
+
+go 1.16
+-- .info --
+{"Version":"v1.2.0"}
+-- go.mod --
+module example.net/pkgadded
+
+go 1.16
+-- pkgadded.go --
+// Package pkgadded was added in v1.1.0.
+package pkgadded
+-- subpkg/subpkg.go --
+// Package subpkg was added in v1.2.0.
+package subpkg
index d658cebfce0170e8fcd2956b2bd2e11d74a2555c..48e4055b0bdb971397be7dd2b0b909205a46a588 100644 (file)
@@ -29,7 +29,6 @@ Scripts also have access to these other environment variables:
        GOARCH=<target GOARCH>
        GOCACHE=<actual GOCACHE being used outside the test>
        GOEXE=<executable file suffix: .exe on Windows, empty on other systems>
-       GOEXPSTRING=<value of objabi.Expstring(), from GOEXPERIMENT when toolchain built>
        GOOS=<target GOOS>
        GOPATH=$WORK/gopath
        GOPROXY=<local module proxy serving from cmd/go/testdata/mod>
@@ -103,6 +102,7 @@ The commands are:
 
 - cd dir
   Change to the given directory for future commands.
+  The directory must use slashes as path separator.
 
 - chmod perm path...
   Change the permissions of the files or directories named by the path arguments
diff --git a/libgo/go/cmd/go/testdata/script/badgo.txt b/libgo/go/cmd/go/testdata/script/badgo.txt
new file mode 100644 (file)
index 0000000..cf4e258
--- /dev/null
@@ -0,0 +1,50 @@
+go get example.net/badgo@v1.0.0
+go get example.net/badgo@v1.1.0
+go get example.net/badgo@v1.2.0
+go get example.net/badgo@v1.3.0
+go get example.net/badgo@v1.4.0
+go get example.net/badgo@v1.5.0
+! go get example.net/badgo@v1.6.0
+stderr 'invalid go version .X.Y.: must match format 1.23'
+
+-- go.mod --
+module m
+
+replace (
+       example.net/badgo v1.0.0 => ./v1.0.0
+       example.net/badgo v1.1.0 => ./v1.1.0
+       example.net/badgo v1.2.0 => ./v1.2.0
+       example.net/badgo v1.3.0 => ./v1.3.0
+       example.net/badgo v1.4.0 => ./v1.4.0
+       example.net/badgo v1.5.0 => ./v1.5.0
+       example.net/badgo v1.6.0 => ./v1.6.0
+)
+
+-- v1.0.0/go.mod --
+module example.net/badgo
+go 1.17.0
+
+-- v1.1.0/go.mod --
+module example.net/badgo
+go 1.17rc2
+
+-- v1.2.0/go.mod --
+module example.net/badgo
+go 1.17.1
+
+-- v1.3.0/go.mod --
+module example.net/badgo
+go v1.17.0
+
+-- v1.4.0/go.mod --
+module example.net/badgo
+go v1.17.0-rc.2
+
+-- v1.5.0/go.mod --
+module example.net/badgo
+go v1.17.1
+
+-- v1.6.0/go.mod --
+module example.net/badgo
+go X.Y
+
index f52250a1b0b52dcdcf27965bb446a9eb5a860514..fc38f18ca5186f4183ce52b2f3a89bb05387ca98 100644 (file)
@@ -2,9 +2,11 @@
 
 [!linux] skip
 [gccgo] skip
+[short] skip
 
 go install
-env BROWSER=$GOPATH/bin/browser
+go build -o $TMPDIR/go ./go
+env BROWSER=$GOPATH/bin/browser PATH=$TMPDIR:$PATH
 go bug
 exists $TMPDIR/browser
 grep '^go version' $TMPDIR/browser
@@ -45,3 +47,13 @@ func main() {
        }
 }
 
+-- go/main.go --
+package main
+
+import (
+    "os"
+)
+
+func main() {
+    os.Exit(1)
+}
diff --git a/libgo/go/cmd/go/testdata/script/build_arm.txt b/libgo/go/cmd/go/testdata/script/build_arm.txt
new file mode 100644 (file)
index 0000000..ff2a364
--- /dev/null
@@ -0,0 +1,13 @@
+[short] skip 'skipping cross-compile in short mode'
+
+env GOARCH=arm
+env GOOS=linux
+env GOARM=5
+
+go build hello.go
+! stderr 'unable to find math.a'
+
+-- hello.go --
+package main
+
+func main() {}
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/build_cache_arch_mode.txt b/libgo/go/cmd/go/testdata/script/build_cache_arch_mode.txt
new file mode 100644 (file)
index 0000000..931827f
--- /dev/null
@@ -0,0 +1,21 @@
+# Issue 9737: verify that GOARM affects the computed build ID
+
+[short] skip
+
+# arm
+env GOOS=linux
+env GOARCH=arm
+env GOARM=5
+go install mycmd
+env GOARM=7
+stale mycmd
+
+
+-- go.mod --
+module mycmd
+
+go 1.16
+-- x.go --
+package main
+
+func main() {}
diff --git a/libgo/go/cmd/go/testdata/script/build_cache_disabled.txt b/libgo/go/cmd/go/testdata/script/build_cache_disabled.txt
new file mode 100644 (file)
index 0000000..68e2773
--- /dev/null
@@ -0,0 +1,50 @@
+# The build cache is required to build anything. It also may be needed to
+# initialize the build system, which is needed for commands like 'go env'.
+# However, there are lots of commands the cache is not needed for, and we
+# shouldn't require it when it won't be used.
+#
+# TODO(golang.org/issue/39882): commands below should work, too.
+# * go clean -modcache
+# * go env
+# * go fix
+# * go fmt
+# * go generate
+# * go get -d
+# * go list (without -export or -compiled)
+
+env GOCACHE=off
+
+# Commands that don't completely load packages should work.
+[!gccgo] go doc fmt
+[!gccgo] stdout Printf
+
+[!gccgo] ! go tool compile -h
+[!gccgo] stderr usage:
+
+go version
+stdout '^go version'
+
+
+# Module commands that don't load packages should work.
+go mod init m
+exists go.mod
+
+go mod edit -require rsc.io/quote@v1.5.2
+
+go mod download rsc.io/quote
+
+go mod graph
+stdout rsc.io/quote
+
+go mod verify
+
+
+# Commands that load but don't build packages should work.
+go fmt .
+
+[!gccgo] go doc .
+
+-- main.go --
+package main
+
+func main() {}
diff --git a/libgo/go/cmd/go/testdata/script/build_cd_gopath_different.txt b/libgo/go/cmd/go/testdata/script/build_cd_gopath_different.txt
new file mode 100644 (file)
index 0000000..a7a4bf4
--- /dev/null
@@ -0,0 +1,73 @@
+[gccgo] skip 'gccgo does not support -ldflags -X'
+env GO111MODULE=off
+go build run_go.go
+
+# Apply identity function to GOPATH
+exec ./run_go$GOEXE $GOPATH/src/my.pkg/main $GOPATH IDENTITY build -o $WORK/tmp/a.exe -ldflags -X=my.pkg.Text=linkXworked
+exec $WORK/tmp/a.exe
+stderr 'linkXworked'
+rm $WORK/tmp/a.exe
+
+[!windows] stop 'rest of the tests only apply to Windows'
+
+# Replace '\' with '/' in GOPATH
+exec ./run_go$GOEXE $GOPATH/src/my.pkg/main $GOPATH REPLACE_SLASH build -o $WORK/tmp/a.exe -ldflags -X=my.pkg.Text=linkXworked
+exec $WORK/tmp/a.exe
+stderr 'linkXworked'
+rm $WORK/tmp/a.exe
+
+# Apply identity function to GOPATH
+exec ./run_go$GOEXE $GOPATH/src/my.pkg/main $GOPATH UPPER build -o $WORK/tmp/a.exe -ldflags -X=my.pkg.Text=linkXworked
+exec $WORK/tmp/a.exe
+stderr 'linkXworked'
+rm $WORK/tmp/a.exe
+
+# Apply identity function to GOPATH
+exec ./run_go$GOEXE $GOPATH/src/my.pkg/main $GOPATH LOWER build -o $WORK/tmp/a.exe -ldflags -X=my.pkg.Text=linkXworked
+exec $WORK/tmp/a.exe
+stderr 'linkXworked'
+rm $WORK/tmp/a.exe
+
+-- run_go.go --
+package main
+
+import (
+       "fmt"
+       "os"
+       "os/exec"
+       "strings"
+)
+
+func main() {
+       dir := os.Args[1]
+       gopath := os.Args[2]
+       switch os.Args[3] {
+               case "IDENTITY":
+               case "REPLACE_SLASH": gopath = strings.ReplaceAll(gopath, `\`, `/`)
+               case "UPPER": gopath = strings.ToUpper(gopath)
+               case "LOWER": gopath = strings.ToLower(gopath)
+               default: fmt.Fprintln(os.Stderr, "bad op"); os.Exit(1)
+       }
+       cmd := exec.Command("go", os.Args[4:]...)
+       cmd.Dir = dir
+       cmd.Env = append(os.Environ(), "GOPATH="+gopath)
+       cmd.Stdout = os.Stdout
+       cmd.Stderr = os.Stderr
+       if err := cmd.Run(); err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+}
+
+-- my.pkg/main/main.go --
+package main
+
+import "my.pkg"
+
+func main() {
+       println(pkg.Text)
+}
+-- my.pkg/pkg.go --
+package pkg
+
+var Text = "unset"
diff --git a/libgo/go/cmd/go/testdata/script/build_cgo_consistent_results.txt b/libgo/go/cmd/go/testdata/script/build_cgo_consistent_results.txt
new file mode 100644 (file)
index 0000000..88a24de
--- /dev/null
@@ -0,0 +1,23 @@
+[short] skip
+[!cgo] skip
+
+[solaris] skip "skipping on Solaris; see golang.org/issue/13247"
+[illumos] skip "skipping on Solaris; see golang.org/issue/13247"
+
+go build -o $WORK/exe1$GOEXE cgotest
+go build -x -o $WORK/exe2$GOEXE cgotest
+
+# TODO(matloob): skip if stderr does not contain '-fdebug-prefix-map=\$WORK'
+
+cmp $WORK/exe1$GOEXE $WORK/exe2$GOEXE
+
+-- go.mod --
+module cgotest
+
+go 1.16
+-- m.go --
+package cgotest
+
+import "C"
+
+var _ C.int
diff --git a/libgo/go/cmd/go/testdata/script/build_darwin_cc_arch.txt b/libgo/go/cmd/go/testdata/script/build_darwin_cc_arch.txt
new file mode 100644 (file)
index 0000000..2b81b4c
--- /dev/null
@@ -0,0 +1,24 @@
+# Test that we pass -arch flag to C compiler on Darwin (issue 43692).
+
+[!darwin] skip
+[!cgo] skip
+
+# clear CC, in case user sets it
+env CC=
+
+env CGO_ENABLED=1
+
+env GOARCH=amd64
+go build -n -x c.go
+stderr 'clang.*-arch x86_64'
+
+env GOARCH=arm64
+go build -n -x c.go
+stderr 'clang.*-arch arm64'
+
+-- c.go --
+package main
+
+import "C"
+
+func main() {}
diff --git a/libgo/go/cmd/go/testdata/script/build_dash_n_cgo.txt b/libgo/go/cmd/go/testdata/script/build_dash_n_cgo.txt
new file mode 100644 (file)
index 0000000..3f49ef6
--- /dev/null
@@ -0,0 +1,18 @@
+# Tests golang.org/issue/14944
+
+[!cgo] skip
+
+go build -n foo.go
+! stderr 'os.Stat .* no such file or directory' # there shouldn't be a stat of the archive file
+
+-- foo.go --
+package main
+
+/*
+#include <limits.h>
+*/
+import "C"
+
+func main() {
+        println(C.INT_MAX)
+}
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/build_dash_o_dev_null.txt b/libgo/go/cmd/go/testdata/script/build_dash_o_dev_null.txt
new file mode 100644 (file)
index 0000000..e415fc2
--- /dev/null
@@ -0,0 +1,13 @@
+# Issue #25579
+
+[short] skip
+
+go build -o $devnull hello.go
+! exists 'hello'$GOEXE
+
+-- hello.go --
+package main
+
+func main() {
+       println("hello, world")
+}
diff --git a/libgo/go/cmd/go/testdata/script/build_dash_x.txt b/libgo/go/cmd/go/testdata/script/build_dash_x.txt
new file mode 100644 (file)
index 0000000..6fd5bbe
--- /dev/null
@@ -0,0 +1,49 @@
+[short] skip
+[!cgo] skip
+
+[!exec:/usr/bin/env] skip
+[!exec:bash] skip
+[!exec:cat] skip
+
+mkdir $WORK/tmp/cache
+env GOCACHE=$WORK/tmp/cache
+
+# Before building our test main.go, ensure that an up-to-date copy of
+# runtime/cgo is present in the cache. If it isn't, the 'go build' step below
+# will fail with "can't open import". See golang.org/issue/29004.
+#
+# (The fix in golang.org/issue/29004 didn't completely fix the underlying issue:
+# cmd/go/internal/load adds a bunch of implicit dependencies
+# based on various heuristics, and, due to a bug described in
+# https://golang.org/issue/31544#issuecomment-490607180,
+# those implicit dependencies are not added early enough during
+# loading to properly affect the import graph.)
+go build runtime/cgo
+
+go build -x -o main main.go
+cp stderr commands.txt
+exec cat header.txt commands.txt
+cp stdout test.sh
+
+exec ./main
+cmp stderr hello.txt
+rm ./main
+
+exec /usr/bin/env bash -x test.sh
+exec ./main
+cmp stderr hello.txt
+
+grep '^WORK=(.*)\n' commands.txt
+
+-- main.go --
+package main
+
+import "C"
+
+func main() {
+       print("hello\n")
+}
+-- header.txt --
+set -e
+-- hello.txt --
+hello
diff --git a/libgo/go/cmd/go/testdata/script/build_exe.txt b/libgo/go/cmd/go/testdata/script/build_exe.txt
new file mode 100644 (file)
index 0000000..a994d17
--- /dev/null
@@ -0,0 +1,25 @@
+# go build with -o and -buildmode=exe should report an error on a non-main package.
+
+! go build -buildmode=exe -o out$GOEXE ./not_main
+stderr '-buildmode=exe requires exactly one main package'
+! exists out$GOEXE
+! go build -buildmode=exe -o out$GOEXE ./main_one ./main_two
+stderr '-buildmode=exe requires exactly one main package'
+! exists out$GOEXE
+
+-- go.mod --
+module m
+
+go 1.16
+-- not_main/not_main.go --
+package not_main
+
+func F() {}
+-- main_one/main_one.go --
+package main
+
+func main() {}
+-- main_two/main_two.go --
+package main
+
+func main() {}
diff --git a/libgo/go/cmd/go/testdata/script/build_gopath_order.txt b/libgo/go/cmd/go/testdata/script/build_gopath_order.txt
new file mode 100644 (file)
index 0000000..caf2502
--- /dev/null
@@ -0,0 +1,36 @@
+# golang.org/issue/14176#issuecomment-179895769
+# golang.org/issue/14192
+# -I arguments to compiler could end up not in GOPATH order,
+# leading to unexpected import resolution in the compiler.
+
+env GO111MODULE=off
+env GOPATH=$WORK/p1${:}$WORK/p2
+mkdir $WORK/p1/src/foo $WORK/p2/src/baz
+mkdir $WORK/p2/pkg/${GOOS}_${GOARCH} $WORK/p1/src/bar
+cp foo.go $WORK/p1/src/foo/foo.go
+cp baz.go $WORK/p2/src/baz/baz.go
+cp foo.a $WORK/p2/pkg/${GOOS}_${GOARCH}/foo.a
+cp bar.go $WORK/p1/src/bar/bar.go
+
+go install -x bar
+
+# add in baz.a to the mix
+mkdir $WORK/p1/pkg/${GOOS}_${GOARCH}
+cp baz.a $WORK/p1/pkg/${GOOS}_${GOARCH}/baz.a
+env GOPATH=$WORK/p1${:}$WORK/p2
+go install -x bar
+env GOPATH=$WORK/p2${:}$WORK/p1
+go install -x bar
+
+-- foo.go --
+package foo
+-- baz.go --
+package baz
+-- foo.a --
+bad
+-- baz.a --
+bad
+-- bar.go --
+package bar
+import _ "baz"
+import _ "foo"
diff --git a/libgo/go/cmd/go/testdata/script/build_i_deprecate.txt b/libgo/go/cmd/go/testdata/script/build_i_deprecate.txt
new file mode 100644 (file)
index 0000000..71356e5
--- /dev/null
@@ -0,0 +1,24 @@
+# Check that deprecation warnings are printed when the -i flag is used.
+# TODO(golang.org/issue/41696): remove the -i flag after Go 1.16, and this test.
+
+go build -n -i
+stderr '^go build: -i flag is deprecated$'
+
+go install -n -i
+stderr '^go install: -i flag is deprecated$'
+
+go test -n -i
+stderr '^go test: -i flag is deprecated$'
+
+
+# 'go clean -i' should not print a deprecation warning.
+# It will continue working.
+go clean -i .
+! stderr .
+
+-- go.mod --
+module m
+
+go 1.16
+-- m.go --
+package m
diff --git a/libgo/go/cmd/go/testdata/script/build_ignore_leading_bom.txt b/libgo/go/cmd/go/testdata/script/build_ignore_leading_bom.txt
new file mode 100644 (file)
index 0000000..37141f3
--- /dev/null
@@ -0,0 +1,27 @@
+# Per https://golang.org/ref/spec#Source_code_representation:
+# a compiler may ignore a UTF-8-encoded byte order mark (U+FEFF)
+# if it is the first Unicode code point in the source text.
+
+go list -f 'Imports: {{.Imports}} EmbedFiles: {{.EmbedFiles}}' .
+stdout '^Imports: \[embed m/hello\] EmbedFiles: \[.*file\]$'
+
+-- go.mod --
+module m
+
+go 1.16
+-- m.go --
+package main
+
+import (
+       _ "embed"
+
+       "m/hello"
+)
+
+//go:embed file
+var s string
+
+-- hello/hello.go --
+package hello
+
+-- file --
diff --git a/libgo/go/cmd/go/testdata/script/build_import_comment.txt b/libgo/go/cmd/go/testdata/script/build_import_comment.txt
new file mode 100644 (file)
index 0000000..b500340
--- /dev/null
@@ -0,0 +1,68 @@
+# Test in GOPATH mode first.
+env GO111MODULE=off
+cd m
+
+# Import comment matches
+go build -n works.go
+
+# Import comment mismatch
+! go build -n wrongplace.go
+stderr 'wrongplace expects import "my/x"'
+
+# Import comment syntax error
+! go build -n bad.go
+stderr 'cannot parse import comment'
+
+# Import comment conflict
+! go build -n conflict.go
+stderr 'found import comments'
+
+
+# Test in module mode.
+# We ignore import comments, so these commands should succeed.
+env GO111MODULE=on
+
+# Import comment matches
+go build -n works.go
+
+# Import comment mismatch
+go build -n wrongplace.go
+
+# Import comment syntax error
+go build -n bad.go
+
+# Import comment conflict
+go build -n conflict.go
+
+-- m/go.mod --
+module m
+
+go 1.16
+-- m/bad.go --
+package p
+
+import "m/bad"
+-- m/conflict.go --
+package p
+
+import "m/conflict"
+-- m/works.go --
+package p
+
+import _ "m/works/x"
+-- m/wrongplace.go --
+package p
+
+import "m/wrongplace"
+-- m/bad/bad.go --
+package bad // import
+-- m/conflict/a.go --
+package conflict // import "a"
+-- m/conflict/b.go --
+package conflict /* import "b" */
+-- m/works/x/x.go --
+package x // import "m/works/x"
+-- m/works/x/x1.go --
+package x // important! not an import comment
+-- m/wrongplace/x.go --
+package x // import "my/x"
diff --git a/libgo/go/cmd/go/testdata/script/build_import_cycle.txt b/libgo/go/cmd/go/testdata/script/build_import_cycle.txt
new file mode 100644 (file)
index 0000000..16e4e87
--- /dev/null
@@ -0,0 +1,13 @@
+# mod_import_cycle covers this error in module mode.
+env GO111MODULE=off
+
+! go build selfimport
+stderr -count=1 'import cycle not allowed'
+
+go list -e -f '{{.Error}}' selfimport # Don't hang forever
+stdout -count=1 'import cycle not allowed'
+
+-- selfimport/selfimport.go --
+package selfimport
+
+import "selfimport"
diff --git a/libgo/go/cmd/go/testdata/script/build_internal.txt b/libgo/go/cmd/go/testdata/script/build_internal.txt
new file mode 100644 (file)
index 0000000..25aa18c
--- /dev/null
@@ -0,0 +1,63 @@
+# Test internal package errors are handled
+cd testinternal3
+go list .
+stdout 'testinternal3'
+
+# Test internal cache
+cd ../testinternal4
+! go build testinternal4/p
+stderr 'internal'
+
+# Test internal packages outside GOROOT are respected
+cd ../testinternal2
+! go build -v .
+stderr 'p\.go:3:8: use of internal package .*internal/w not allowed'
+
+[gccgo] skip # gccgo does not have GOROOT
+cd ../testinternal
+! go build -v .
+stderr 'p\.go:3:8: use of internal package net/http/internal not allowed'
+
+-- testinternal/go.mod --
+module testinternal
+
+go 1.16
+-- testinternal/p.go --
+package p
+
+import _ "net/http/internal"
+-- testinternal2/go.mod --
+module testinternal2
+
+go 1.16
+-- testinternal2/p.go --
+package p
+
+import _ "./x/y/z/internal/w"
+-- testinternal2/x/y/z/internal/w/w.go --
+package w
+-- testinternal3/go.mod --
+module testinternal3
+
+go 1.16
+-- testinternal3/t.go --
+package t
+
+import _ "internal/does-not-exist"
+-- testinternal4/go.mod --
+module testinternal4
+
+go 1.16
+-- testinternal4/p/p.go --
+package p
+
+import (
+       _ "testinternal4/q/internal/x"
+       _ "testinternal4/q/j"
+)
+-- testinternal4/q/internal/x/x.go --
+package x
+-- testinternal4/q/j/j.go --
+package j
+
+import _ "testinternal4/q/internal/x"
diff --git a/libgo/go/cmd/go/testdata/script/build_issue6480.txt b/libgo/go/cmd/go/testdata/script/build_issue6480.txt
new file mode 100644 (file)
index 0000000..cf1e9ea
--- /dev/null
@@ -0,0 +1,128 @@
+# "go test -c -test.bench=XXX errors" should not hang.
+# "go test -c" should also produce reproducible binaries.
+# "go test -c" should also appear to write a new binary every time,
+# even if it's really just updating the mtime on an existing up-to-date binary.
+
+[gccgo] skip
+[short] skip
+
+# Install some commands to compare mtimes
+env GOBIN=$WORK/tmp/bin
+go install m/now m/mtime m/before
+
+# Initial builds
+go test -c -test.bench=XXX errors
+go test -c -o errors2.test errors
+cmp errors.test$GOEXE errors2.test # // errors2.test has no exeSuffix because -o above doesn't have it
+
+# Check errors.test mtime is updated
+exec $GOBIN/now
+cp stdout start_time.txt
+go test -x -c -test.bench=XXX errors
+! stderr '[\\/]link|gccgo' # make sure up-to-date test binary is not relinked
+exec $GOBIN/mtime errors.test$GOEXE
+cp stdout errors1_mod_time.txt
+exec $GOBIN/before start_time.txt errors1_mod_time.txt
+rm start_time.txt errors1_mod_time.txt
+
+# Check errors2.test mtime is updated
+exec $GOBIN/now
+cp stdout start_time.txt
+go test -x -c -o errors2.test errors
+! stderr '[\\/]link|gccgo' # make sure up-to-date test binary is not relinked
+exec $GOBIN/mtime errors2.test
+cp stdout errors2_mod_time.txt
+exec $GOBIN/before start_time.txt errors2_mod_time.txt
+
+-- go.mod --
+module m
+
+go 1.16
+-- now/now.go --
+// Writes time.Now() to a file
+package main
+
+import (
+       "encoding/json"
+       "fmt"
+       "os"
+       "time"
+)
+
+func main() {
+       if err := json.NewEncoder(os.Stdout).Encode(time.Now()); err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+}
+-- mtime/mtime.go --
+package main
+
+import (
+       "encoding/json"
+       "fmt"
+       "os"
+)
+
+func main() {
+       info, err := os.Stat(os.Args[1])
+       if err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+       if err := json.NewEncoder(os.Stdout).Encode(info.ModTime()); err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+}
+-- before/before.go --
+package main
+
+import (
+       "encoding/json"
+       "fmt"
+       "os"
+       "time"
+)
+
+func truncateLike(t, p time.Time) time.Time {
+       nano := p.UnixNano()
+       d := 1 * time.Nanosecond
+       for nano%int64(d) == 0 && d < 1*time.Second {
+               d *= 10
+       }
+       for nano%int64(d) == 0 && d < 2*time.Second {
+               d *= 2
+       }
+       return t.Truncate(d)
+}
+
+func main() {
+       var t1 time.Time
+       b1, err := os.ReadFile(os.Args[1])
+       if err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+       if err := json.Unmarshal(b1, &t1); err != nil  {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+
+       var t2 time.Time
+       b2, err := os.ReadFile(os.Args[2])
+       if err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+       if err := json.Unmarshal(b2, &t2); err != nil  {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+
+       t1 = truncateLike(t1, t2)
+       if !t1.Before(t2) {
+               fmt.Fprintf(os.Stderr, "time in %v (%v) is not before time in %v (%v)", os.Args[1], t1, os.Args[2], t2)
+               os.Exit(1)
+       }
+}
diff --git a/libgo/go/cmd/go/testdata/script/build_link_x_import_path_escape.txt b/libgo/go/cmd/go/testdata/script/build_link_x_import_path_escape.txt
new file mode 100644 (file)
index 0000000..f1de1e4
--- /dev/null
@@ -0,0 +1,22 @@
+[gccgo] skip 'gccgo does not support -ldflags -X'
+
+go build -o linkx$GOEXE -ldflags -X=my.pkg.Text=linkXworked my.pkg/main
+exec ./linkx$GOEXE
+stderr '^linkXworked$'
+
+-- go.mod --
+module my.pkg
+
+go 1.16
+-- main/main.go --
+package main
+
+import "my.pkg"
+
+func main() {
+       println(pkg.Text)
+}
+-- pkg.go --
+package pkg
+
+var Text = "unset"
diff --git a/libgo/go/cmd/go/testdata/script/build_n_cgo.txt b/libgo/go/cmd/go/testdata/script/build_n_cgo.txt
new file mode 100644 (file)
index 0000000..7aa77ae
--- /dev/null
@@ -0,0 +1,17 @@
+[!cgo] skip
+
+# Test that nothing is prepended to $WORK path prefix.
+# See issue golang.org/issue/37012.
+go build -n
+! stderr '[/\\]\$WORK'
+
+-- go.mod --
+module m
+
+go 1.16
+-- main.go --
+package main
+
+import "C"
+
+var _ C.int
diff --git a/libgo/go/cmd/go/testdata/script/build_no_go.txt b/libgo/go/cmd/go/testdata/script/build_no_go.txt
new file mode 100644 (file)
index 0000000..b61d752
--- /dev/null
@@ -0,0 +1,41 @@
+! go build ./empty/test
+stderr 'no non-test Go files in '
+
+! go build ./empty/xtest
+stderr 'no non-test Go files in '
+
+! go build ./empty/testxtest
+stderr 'no non-test Go files in '
+
+! go build ./exclude
+stderr 'build constraints exclude all Go files in '
+
+! go build ./exclude/ignore
+stderr 'no Go files in '
+
+! go build ./exclude/empty
+stderr 'no Go files in '
+
+-- go.mod --
+module m
+
+go 1.16
+-- empty/test/test_test.go --
+package p
+-- empty/testxtest/test_test.go --
+package p
+-- empty/testxtest/xtest_test.go --
+package p_test
+-- empty/xtest/xtest_test.go --
+package p_test
+-- exclude/empty/x.txt --
+-- exclude/ignore/_x.go --
+package x
+-- exclude/x.go --
+// +build linux,!linux
+
+package x
+-- exclude/x_linux.go --
+// +build windows
+
+package x
diff --git a/libgo/go/cmd/go/testdata/script/build_output.txt b/libgo/go/cmd/go/testdata/script/build_output.txt
new file mode 100644 (file)
index 0000000..1e82950
--- /dev/null
@@ -0,0 +1,117 @@
+[gccgo] skip 'gccgo has no standard packages'
+[short] skip
+
+[!windows] env NONEXE='.exe'
+[windows] env NONEXE=''
+
+env GOBIN=$WORK/tmp/bin
+go install m/isarchive &
+
+go build x.go
+exists -exec x$GOEXE
+rm x$GOEXE
+! exists x$NONEXE
+
+go build -o myprog x.go
+! exists x
+! exists x.exe
+exists -exec myprog
+! exists myprogr.exe
+
+! exists bin
+go build -o bin/x x.go
+exists -exec bin/x
+rm bin
+
+! exists bin
+go build -o bin/ x.go
+exists -exec bin/x$GOEXE
+rm bin
+
+[windows] ! exists bin
+[windows] go build -o bin\x x.go
+[windows] exists -exec bin\x
+[windows] rm bin
+
+[windows] ! exists bin
+[windows] go build -o bin\ x.go
+[windows] exists -exec bin\x.exe
+[windows] rm bin
+
+! exists bin
+mkdir bin
+go build -o bin x.go
+exists -exec bin/x$GOEXE
+rm bin
+
+go build p.go
+! exists p
+! exists p.a
+! exists p.o
+! exists p.exe
+
+wait # for isarchive
+
+go build -o p.a p.go
+exists p.a
+exec $GOBIN/isarchive p.a
+
+go build cmd/gofmt
+exists -exec gofmt$GOEXE
+rm gofmt$GOEXE
+! exists gofmt$NONEXE
+
+go build -o mygofmt cmd/gofmt
+exists -exec mygofmt
+! exists mygofmt.exe
+! exists gofmt
+! exists gofmt.exe
+
+go build sync/atomic
+! exists atomic
+! exists atomic.exe
+
+go build -o myatomic.a sync/atomic
+exists myatomic.a
+exec $GOBIN/isarchive myatomic.a
+! exists atomic
+! exists atomic.a
+! exists atomic.exe
+
+! go build -o whatever cmd/gofmt sync/atomic
+stderr 'multiple packages'
+
+-- go.mod --
+module m
+
+go 1.16
+-- x.go --
+package main
+
+func main() {}
+-- p.go --
+package p
+-- isarchive/isarchive.go --
+package main
+
+import (
+       "bytes"
+       "fmt"
+       "io"
+       "os"
+)
+
+func main() {
+       f, err := os.Open(os.Args[1])
+       if err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+       buf := make([]byte, 100)
+       io.ReadFull(f, buf)
+       f.Close()
+       if !bytes.HasPrefix(buf, []byte("!<arch>\n")) {
+               fmt.Fprintf(os.Stderr, "file %s exists but is not an archive\n", os.Args[1])
+               os.Exit(1)
+       }
+}
diff --git a/libgo/go/cmd/go/testdata/script/build_overlay.txt b/libgo/go/cmd/go/testdata/script/build_overlay.txt
new file mode 100644 (file)
index 0000000..2932b94
--- /dev/null
@@ -0,0 +1,308 @@
+[short] skip
+
+# Test building in overlays.
+# TODO(#39958): add a test case where the destination file in the replace map
+#   isn't a go file. Either completely exclude that case in fs.IsDirWithGoFiles
+#   if the compiler doesn't allow it, or test that it works all the way.
+# TODO(#39958): add a test that both gc and gccgo assembly files can include .h
+#   files.
+
+# The main package (m) is contained in an overlay. It imports m/dir2 which has one
+# file in an overlay and one file outside the overlay, which in turn imports m/dir,
+# which only has source files in the overlay.
+
+cd m
+
+! go build .
+go build -overlay overlay.json -o main$GOEXE .
+exec ./main$goexe
+stdout '^hello$'
+
+go build -overlay overlay.json -o print_abspath$GOEXE ./printpath
+exec ./print_abspath$GOEXE
+stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]main.go
+
+go build -overlay overlay.json -o print_trimpath$GOEXE -trimpath ./printpath
+exec ./print_trimpath$GOEXE
+stdout ^m[/\\]printpath[/\\]main.go
+
+go build -overlay overlay.json -o print_trimpath_two_files$GOEXE printpath/main.go printpath/other.go
+exec ./print_trimpath_two_files$GOEXE
+stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]main.go
+stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]other.go
+
+go build -overlay overlay.json -o main_cgo_replace$GOEXE ./cgo_hello_replace
+exec ./main_cgo_replace$GOEXE
+stdout '^hello cgo\r?\n'
+
+go build -overlay overlay.json -o main_cgo_quote$GOEXE ./cgo_hello_quote
+exec ./main_cgo_quote$GOEXE
+stdout '^hello cgo\r?\n'
+
+go build -overlay overlay.json -o main_cgo_angle$GOEXE ./cgo_hello_angle
+exec ./main_cgo_angle$GOEXE
+stdout '^hello cgo\r?\n'
+
+go build -overlay overlay.json -o main_call_asm$GOEXE ./call_asm
+exec ./main_call_asm$GOEXE
+! stdout .
+
+# Change the contents of a file in the overlay and ensure that makes the target stale
+go install -overlay overlay.json ./test_cache
+go list -overlay overlay.json -f '{{.Stale}}' ./test_cache
+stdout '^false$'
+cp overlay/test_cache_different.go overlay/test_cache.go
+go list -overlay overlay.json -f '{{.Stale}}' ./test_cache
+stdout '^true$'
+
+go list -compiled -overlay overlay.json -f '{{range .CompiledGoFiles}}{{. | printf "%s\n"}}{{end}}' ./cgo_hello_replace
+cp stdout compiled_cgo_sources.txt
+go run ../print_line_comments.go compiled_cgo_sources.txt
+stdout $GOPATH[/\\]src[/\\]m[/\\]cgo_hello_replace[/\\]cgo_hello_replace.go
+! stdout $GOPATH[/\\]src[/\\]m[/\\]overlay[/\\]hello.c
+
+# Run same tests but with gccgo.
+env GO111MODULE=off
+[!exec:gccgo] stop
+
+! go build -compiler=gccgo .
+go build -compiler=gccgo -overlay overlay.json -o main_gccgo$GOEXE .
+exec ./main_gccgo$goexe
+stdout '^hello$'
+
+go build -compiler=gccgo -overlay overlay.json -o print_abspath_gccgo$GOEXE ./printpath
+exec ./print_abspath_gccgo$GOEXE
+stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]main.go
+
+go build -compiler=gccgo -overlay overlay.json -o print_trimpath_gccgo$GOEXE -trimpath ./printpath
+exec ./print_trimpath_gccgo$GOEXE
+stdout ^\.[/\\]printpath[/\\]main.go
+
+
+go build -compiler=gccgo  -overlay overlay.json -o main_cgo_replace_gccgo$GOEXE ./cgo_hello_replace
+exec ./main_cgo_replace_gccgo$GOEXE
+stdout '^hello cgo\r?\n'
+
+go build -compiler=gccgo  -overlay overlay.json -o main_cgo_quote_gccgo$GOEXE ./cgo_hello_quote
+exec ./main_cgo_quote_gccgo$GOEXE
+stdout '^hello cgo\r?\n'
+
+go build -compiler=gccgo  -overlay overlay.json -o main_cgo_angle_gccgo$GOEXE ./cgo_hello_angle
+exec ./main_cgo_angle_gccgo$GOEXE
+stdout '^hello cgo\r?\n'
+
+go build -compiler=gccgo -overlay overlay.json -o main_call_asm_gccgo$GOEXE ./call_asm
+exec ./main_call_asm_gccgo$GOEXE
+! stdout .
+
+
+-- m/go.mod --
+// TODO(matloob): how do overlays work with go.mod (especially if mod=readonly)
+module m
+
+go 1.16
+
+-- m/dir2/h.go --
+package dir2
+
+func PrintMessage() {
+       printMessage()
+}
+-- m/dir/foo.txt --
+The build action code currently expects the package directory
+to exist, so it can run the compiler in that directory.
+TODO(matloob): Remove this requirement.
+-- m/printpath/about.txt --
+the actual code is in the overlay
+-- m/overlay.json --
+{
+       "Replace": {
+               "f.go": "overlay/f.go",
+               "dir/g.go": "overlay/dir_g.go",
+               "dir2/i.go": "overlay/dir2_i.go",
+               "printpath/main.go": "overlay/printpath.go",
+               "printpath/other.go": "overlay2/printpath2.go",
+               "call_asm/asm_gc.s": "overlay/asm_gc.s",
+               "call_asm/asm_gccgo.s": "overlay/asm_gccgo.s",
+               "test_cache/main.go": "overlay/test_cache.go",
+               "cgo_hello_replace/cgo_header.h": "overlay/cgo_head.h",
+               "cgo_hello_replace/hello.c": "overlay/hello.c",
+               "cgo_hello_quote/cgo_hello.go": "overlay/cgo_hello_quote.go",
+               "cgo_hello_quote/cgo_header.h": "overlay/cgo_head.h",
+               "cgo_hello_angle/cgo_hello.go": "overlay/cgo_hello_angle.go",
+               "cgo_hello_angle/cgo_header.h": "overlay/cgo_head.h"
+       }
+}
+-- m/cgo_hello_replace/cgo_hello_replace.go --
+package main
+
+// #include "cgo_header.h"
+import "C"
+
+func main() {
+       C.say_hello()
+}
+-- m/cgo_hello_replace/cgo_header.h --
+ // Test that this header is replaced with one that has the proper declaration.
+void say_goodbye();
+
+-- m/cgo_hello_replace/hello.c --
+#include <stdio.h>
+
+void say_goodbye() { puts("goodbye cgo\n"); fflush(stdout); }
+
+-- m/overlay/f.go --
+package main
+
+import "m/dir2"
+
+func main() {
+       dir2.PrintMessage()
+}
+-- m/call_asm/main.go --
+package main
+
+func foo() // There will be a "missing function body" error if the assembly file isn't found.
+
+func main() {
+       foo()
+}
+-- m/overlay/dir_g.go --
+package dir
+
+import "fmt"
+
+func PrintMessage() {
+       fmt.Println("hello")
+}
+-- m/overlay/printpath.go --
+package main
+
+import (
+       "fmt"
+       "path/filepath"
+       "runtime"
+)
+
+func main() {
+       _, file, _, _ := runtime.Caller(0)
+
+       // Since https://golang.org/cl/214286, the runtime's debug paths are
+       // slash-separated regardless of platform, so normalize them to system file
+       // paths.
+       fmt.Println(filepath.FromSlash(file))
+}
+-- m/overlay2/printpath2.go --
+package main
+
+import (
+       "fmt"
+       "path/filepath"
+       "runtime"
+)
+
+func init() {
+       _, file, _, _ := runtime.Caller(0)
+       fmt.Println(filepath.FromSlash(file))
+}
+-- m/overlay/dir2_i.go --
+package dir2
+
+import "m/dir"
+
+func printMessage() {
+       dir.PrintMessage()
+}
+-- m/overlay/cgo_hello_quote.go --
+package main
+
+// #include "cgo_header.h"
+import "C"
+
+func main() {
+       C.say_hello()
+}
+-- m/overlay/cgo_hello_angle.go --
+package main
+
+// #include <cgo_header.h>
+import "C"
+
+func main() {
+       C.say_hello()
+}
+-- m/overlay/cgo_head.h --
+void say_hello();
+-- m/overlay/hello.c --
+#include <stdio.h>
+
+void say_hello() { puts("hello cgo\n"); fflush(stdout); }
+-- m/overlay/asm_gc.s --
+// +build gc
+
+TEXT ·foo(SB),0,$0
+       RET
+
+-- m/overlay/asm_gccgo.s --
+// +build gccgo
+
+.globl main.foo
+.text
+main.foo:
+       ret
+
+-- m/overlay/test_cache.go --
+package foo
+
+import "fmt"
+
+func bar() {
+       fmt.Println("something")
+}
+-- m/overlay/test_cache_different.go --
+package foo
+
+import "fmt"
+
+func bar() {
+       fmt.Println("different")
+}
+-- m/cgo_hello_quote/hello.c --
+#include <stdio.h>
+
+void say_hello() { puts("hello cgo\n"); fflush(stdout); }
+-- m/cgo_hello_angle/hello.c --
+#include <stdio.h>
+
+void say_hello() { puts("hello cgo\n"); fflush(stdout); }
+
+-- print_line_comments.go --
+package main
+
+import (
+       "fmt"
+       "io/ioutil"
+       "log"
+       "os"
+       "strings"
+)
+
+func main() {
+       compiledGoFilesArg := os.Args[1]
+       b, err := ioutil.ReadFile(compiledGoFilesArg)
+       if err != nil {
+               log.Fatal(err)
+       }
+       compiledGoFiles := strings.Split(strings.TrimSpace(string(b)), "\n")
+       for _, f := range compiledGoFiles {
+               b, err := ioutil.ReadFile(f)
+               if err != nil {
+                       log.Fatal(err)
+               }
+               for _, line := range strings.Split(string(b), "\n") {
+                       if strings.HasPrefix(line, "#line") || strings.HasPrefix(line, "//line") {
+                               fmt.Println(line)
+                       }
+               }
+       }
+}
diff --git a/libgo/go/cmd/go/testdata/script/build_patterns_outside_gopath.txt b/libgo/go/cmd/go/testdata/script/build_patterns_outside_gopath.txt
new file mode 100644 (file)
index 0000000..6a600cf
--- /dev/null
@@ -0,0 +1,36 @@
+# Tests issue #18778
+[short] skip
+
+cd pkgs
+
+env GO111MODULE=off
+go build ./...
+! stdout .
+go test ./...
+stdout '^ok'
+go list ./...
+stdout 'pkgs$'
+stdout 'pkgs/a'
+
+-- pkgs/go.mod --
+module pkgs
+
+go 1.16
+-- pkgs/a.go --
+package x
+-- pkgs/a_test.go --
+package x_test
+
+import "testing"
+
+func TestX(t *testing.T) {
+}
+-- pkgs/a/a.go --
+package a
+-- pkgs/a/a_test.go --
+package a_test
+
+import "testing"
+
+func TestA(t *testing.T) {
+}
diff --git a/libgo/go/cmd/go/testdata/script/build_plugin_non_main.txt b/libgo/go/cmd/go/testdata/script/build_plugin_non_main.txt
new file mode 100644 (file)
index 0000000..e0bbbef
--- /dev/null
@@ -0,0 +1,13 @@
+# Plugins are not supported on all platforms.
+[!buildmode:plugin] skip
+
+go build -n testdep
+! go build -buildmode=plugin testdep
+stderr '-buildmode=plugin requires exactly one main package'
+
+-- go.mod --
+module testdep
+
+go 1.16
+-- testdep.go --
+package p
diff --git a/libgo/go/cmd/go/testdata/script/build_tag_goexperiment.txt b/libgo/go/cmd/go/testdata/script/build_tag_goexperiment.txt
new file mode 100644 (file)
index 0000000..bee218f
--- /dev/null
@@ -0,0 +1,31 @@
+[short] skip
+# Reset all experiments so fieldtrack is definitely off.
+env GOEXPERIMENT=none
+go run m
+stderr 'fieldtrack off'
+# Turn fieldtrack on.
+env GOEXPERIMENT=none,fieldtrack
+go run m
+stderr 'fieldtrack on'
+
+-- ft_off.go --
+// +build !goexperiment.fieldtrack
+
+package main
+
+func main() {
+       println("fieldtrack off")
+}
+
+-- ft_on.go --
+// +build goexperiment.fieldtrack
+
+package main
+
+func main() {
+       println("fieldtrack on")
+}
+
+-- go.mod --
+module m
+go 1.14
diff --git a/libgo/go/cmd/go/testdata/script/build_tags_no_comma.txt b/libgo/go/cmd/go/testdata/script/build_tags_no_comma.txt
new file mode 100644 (file)
index 0000000..f3eb282
--- /dev/null
@@ -0,0 +1,4 @@
+[gccgo] skip 'gccgo has no standard packages'
+go build -tags 'tag1 tag2' math
+! go build -tags 'tag1,tag2 tag3' math
+stderr 'space-separated list contains comma'
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/build_test_only.txt b/libgo/go/cmd/go/testdata/script/build_test_only.txt
new file mode 100644 (file)
index 0000000..8693a80
--- /dev/null
@@ -0,0 +1,19 @@
+# Named explicitly, test-only packages should be reported as
+# unbuildable/uninstallable, even if there is a wildcard also matching.
+! go build m/testonly m/testonly...
+stderr 'no non-test Go files in'
+! go install ./testonly
+stderr 'no non-test Go files in'
+
+# Named through a wildcard, the test-only packages should be silently ignored.
+go build m/testonly...
+go install ./testonly...
+
+-- go.mod --
+module m
+
+go 1.16
+-- testonly/t_test.go --
+package testonly
+-- testonly2/t.go --
+package testonly2
diff --git a/libgo/go/cmd/go/testdata/script/build_trimpath_cgo.txt b/libgo/go/cmd/go/testdata/script/build_trimpath_cgo.txt
new file mode 100644 (file)
index 0000000..3187b4d
--- /dev/null
@@ -0,0 +1,184 @@
+# This test builds a cgo binary and verifies the source directory path
+# does not appear in the binary, either literally or in compressed DWARF.
+# TODO(golang.org/issue/36072): ideally we should build a binary from identical
+# sources in different directories and verify the binary and all intermediate
+# files are identical.
+
+[short] skip
+[!cgo] skip
+
+# Check that the source path appears when -trimpath is not used.
+go build -o hello.exe .
+grep -q gopath[/\\]src hello.exe
+go run ./list-dwarf hello.exe
+stdout gopath[/\\]src
+
+# Check that the source path does not appear when -trimpath is used.
+[aix] stop # can't inspect XCOFF binaries
+go build -trimpath -o hello.exe .
+! grep -q gopath[/\\]src hello.exe
+go run ./list-dwarf hello.exe
+! stdout gopath/src
+
+
+# Do the above, with the cgo (but not .c) sources in an overlay
+# Check that the source path appears when -trimpath is not used.
+mkdir $WORK/overlay
+cp hello.go $WORK/overlay/hello.go
+mkdir hello_overlay
+cp hello.c hello_overlay/hello.c
+go build -overlay overlay.json -o hello_overlay.exe ./hello_overlay
+grep -q gopath[/\\]src hello_overlay.exe
+! grep -q $WORK[/\\]overlay hello_overlay.exe
+go run ./list-dwarf hello_overlay.exe
+stdout gopath[/\\]src
+! stdout $WORK[/\\]overlay
+
+# Check that the source path does not appear when -trimpath is used.
+go build -overlay overlay.json -trimpath -o hello_overlay.exe ./hello_overlay
+! grep -q gopath[/\\]src hello_overlay.exe
+! grep -q $WORK[/\\]overlay hello_overlay.exe
+go run ./list-dwarf hello_overlay.exe
+! stdout gopath/src
+! stdout $WORK[/\\]overlay
+
+-- go.mod --
+module m
+
+go 1.14
+-- overlay.json --
+{
+       "Replace": {
+               "hello_overlay/hello.go": "../../overlay/hello.go"
+       }
+}
+-- hello.c --
+#include <stdio.h>
+
+void say_hello() { puts("Hello, world!\n"); }
+
+-- hello.go --
+package main
+
+// void say_hello();
+import "C"
+
+func main() {
+       C.say_hello()
+}
+
+-- list-dwarf/list-dwarf.go --
+package main
+
+import (
+       "debug/dwarf"
+       "fmt"
+       "io"
+       "log"
+       "os"
+       "sort"
+)
+
+func main() {
+       files, err := run(os.Args[1])
+       if err != nil {
+               log.Fatal(err)
+       }
+       for _, file := range files {
+               fmt.Println(file)
+       }
+}
+
+func run(exePath string) ([]string, error) {
+       dwarfData, err := readDWARF(exePath)
+       if err != nil {
+               return nil, err
+       }
+
+       dwarfReader := dwarfData.Reader()
+       files := make(map[string]bool)
+       for {
+               e, err := dwarfReader.Next()
+               if err != nil {
+                       return nil, err
+               }
+               if e == nil {
+                       break
+               }
+               lr, err := dwarfData.LineReader(e)
+               if err != nil {
+                       return nil, err
+               }
+               if lr == nil {
+                       continue
+               }
+
+               var le dwarf.LineEntry
+               for {
+                       if err := lr.Next(&le); err != nil {
+                               if err == io.EOF {
+                                       break
+                               }
+                               return nil, err
+                       }
+                       files[le.File.Name] = true
+               }
+       }
+
+       sortedFiles := make([]string, 0, len(files))
+       for file := range files {
+               sortedFiles = append(sortedFiles, file)
+       }
+       sort.Strings(sortedFiles)
+       return sortedFiles, nil
+}
+-- list-dwarf/read_darwin.go --
+package main
+
+import (
+       "debug/dwarf"
+       "debug/macho"
+)
+
+func readDWARF(exePath string) (*dwarf.Data, error) {
+       machoFile, err := macho.Open(exePath)
+       if err != nil {
+               return nil, err
+       }
+       defer machoFile.Close()
+       return machoFile.DWARF()
+}
+-- list-dwarf/read_elf.go --
+// +build android dragonfly freebsd illumos linux netbsd openbsd solaris
+
+package main
+
+import (
+       "debug/dwarf"
+       "debug/elf"
+)
+
+func readDWARF(exePath string) (*dwarf.Data, error) {
+       elfFile, err := elf.Open(exePath)
+       if err != nil {
+               return nil, err
+       }
+       defer elfFile.Close()
+       return elfFile.DWARF()
+}
+-- list-dwarf/read_windows.go --
+package main
+
+import (
+       "debug/dwarf"
+       "debug/pe"
+)
+
+func readDWARF(exePath string) (*dwarf.Data, error) {
+       peFile, err := pe.Open(exePath)
+       if err != nil {
+               return nil, err
+       }
+       defer peFile.Close()
+       return peFile.DWARF()
+}
diff --git a/libgo/go/cmd/go/testdata/script/build_unsupported_goos.txt b/libgo/go/cmd/go/testdata/script/build_unsupported_goos.txt
new file mode 100644 (file)
index 0000000..d61e420
--- /dev/null
@@ -0,0 +1,6 @@
+[gccgo] skip # gccgo assumes cross-compilation is always possible
+
+env GOOS=windwos
+
+! go build -n exclude
+stderr 'unsupported GOOS/GOARCH pair'
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/build_vendor.txt b/libgo/go/cmd/go/testdata/script/build_vendor.txt
new file mode 100644 (file)
index 0000000..f430ff2
--- /dev/null
@@ -0,0 +1,42 @@
+# Build
+env GO111MODULE=off
+go build vend/x
+! stdout .
+! stderr .
+
+-- vend/dir1/dir1.go --
+package dir1
+-- vend/subdir/bad.go --
+package subdir
+
+import _ "r"
+-- vend/subdir/good.go --
+package subdir
+
+import _ "p"
+-- vend/vendor/p/p.go --
+package p
+-- vend/vendor/q/q.go --
+package q
+-- vend/vendor/vend/dir1/dir2/dir2.go --
+package dir2
+-- vend/x/invalid/invalid.go --
+package invalid
+
+import "vend/x/invalid/vendor/foo"
+-- vend/x/vendor/p/p/p.go --
+package p
+
+import _ "notfound"
+-- vend/x/vendor/p/p.go --
+package p
+-- vend/x/vendor/r/r.go --
+package r
+-- vend/x/x.go --
+package x
+
+import _ "p"
+import _ "q"
+import _ "r"
+import _ "vend/dir1"      // not vendored
+import _ "vend/dir1/dir2" // vendored
diff --git a/libgo/go/cmd/go/testdata/script/cgo_asm_error.txt b/libgo/go/cmd/go/testdata/script/cgo_asm_error.txt
new file mode 100644 (file)
index 0000000..7aaa713
--- /dev/null
@@ -0,0 +1,25 @@
+[!cgo] skip
+
+# Test that cgo package can't contain a go assembly file.
+
+# Ensure the build fails and reports that the package has a Go assembly file.
+! go build cgoasm
+stderr 'package using cgo has Go assembly file'
+
+-- go.mod --
+module cgoasm
+
+go 1.16
+-- p.go --
+package p
+
+/*
+// hi
+*/
+import "C"
+
+func F() {}
+-- p.s --
+TEXT asm(SB),$0
+       RET
+
diff --git a/libgo/go/cmd/go/testdata/script/cgo_bad_directives.txt b/libgo/go/cmd/go/testdata/script/cgo_bad_directives.txt
new file mode 100644 (file)
index 0000000..6bf3beb
--- /dev/null
@@ -0,0 +1,129 @@
+[!cgo] skip
+[short] skip
+
+cp x.go.txt x.go
+
+# Only allow //go:cgo_ldflag .* in cgo-generated code
+[gc] cp x_gc.go.txt x.go
+[gc] ! go build x
+[gc] stderr '//go:cgo_ldflag .* only allowed in cgo-generated code'
+
+# Ignore _* files
+rm x.go
+! go build .
+stderr 'no Go files'
+cp cgo_yy.go.txt _cgo_yy.go
+! go build .
+stderr 'no Go files' #_* files are ignored...
+
+[gc] ! go build _cgo_yy.go # ... but if forced, the comment is rejected
+# Actually, today there is a separate issue that _ files named
+# on the command line are ignored. Once that is fixed,
+# we want to see the cgo_ldflag error.
+[gc] stderr '//go:cgo_ldflag only allowed in cgo-generated code|no Go files'
+
+rm _cgo_yy.go
+
+# Reject #cgo CFLAGS: -fplugin=foo.so
+cp x.go.txt x.go
+cp y_fplugin.go.txt y.go
+! go build x
+stderr 'invalid flag in #cgo CFLAGS: -fplugin=foo.so'
+
+# Reject #cgo CFLAGS: -lbar -fplugin=foo.so
+cp y_lbar_fplugin.go.txt y.go
+! go build x
+stderr 'invalid flag in #cgo CFLAGS: -fplugin=foo.so'
+
+# Reject #cgo pkg-config: -foo
+cp y_pkgconfig_dash_foo.txt y.go
+! go build x
+stderr 'invalid pkg-config package name: -foo'
+
+# Reject #cgo pkg-config: @foo
+cp y_pkgconfig_at_foo.txt y.go
+! go build x
+stderr 'invalid pkg-config package name: @foo'
+
+# Reject #cgo CFLAGS: @foo
+cp y_cflags_at_foo.txt y.go
+! go build x
+stderr 'invalid flag in #cgo CFLAGS: @foo'
+
+# Reject #cgo CFLAGS: -D
+cp y_cflags_dash_d.txt y.go
+! go build x
+stderr 'invalid flag in #cgo CFLAGS: -D without argument'
+
+# Note that -I @foo is allowed because we rewrite it into -I /path/to/src/@foo
+# before the check is applied. There's no such rewrite for -D.
+
+# Reject #cgo CFLAGS: -D @foo
+cp y_cflags_dash_d_space_at_foo.txt y.go
+! go build x
+stderr 'invalid flag in #cgo CFLAGS: -D @foo'
+
+# Reject #cgo CFLAGS -D@foo
+cp y_cflags_dash_d_at_foo.txt y.go
+! go build x
+stderr 'invalid flag in #cgo CFLAGS: -D@foo'
+
+# Check for CFLAGS in commands
+env CGO_CFLAGS=-D@foo
+cp y_no_cflags.txt y.go
+go build -n x
+stderr '-D@foo'
+
+-- go.mod --
+module x
+
+go 1.16
+-- x_gc.go.txt --
+package x
+
+//go:cgo_ldflag "-fplugin=foo.so"
+
+import "C"
+-- cgo_yy.go.txt --
+package x
+
+//go:cgo_ldflag "-fplugin=foo.so"
+
+import "C"
+-- x.go.txt --
+package x
+-- y_fplugin.go.txt --
+package x
+// #cgo CFLAGS: -fplugin=foo.so
+import "C"
+-- y_lbar_fplugin.go.txt --
+package x
+// #cgo CFLAGS: -Ibar -fplugin=foo.so
+import "C"
+-- y_pkgconfig_dash_foo.txt --
+package x
+// #cgo pkg-config: -foo
+import "C"
+-- y_pkgconfig_at_foo.txt --
+package x
+// #cgo pkg-config: @foo
+import "C"
+-- y_cflags_at_foo.txt --
+package x
+// #cgo CFLAGS: @foo
+import "C"
+-- y_cflags_dash_d.txt --
+package x
+// #cgo CFLAGS: -D
+import "C"
+-- y_cflags_dash_d_space_at_foo.txt --
+package x
+// #cgo CFLAGS: -D @foo
+import "C"
+-- y_cflags_dash_d_at_foo.txt --
+package x
+// #cgo CFLAGS: -D@foo
+import "C"
+-- y_no_cflags.txt --
+package x
+import "C"
diff --git a/libgo/go/cmd/go/testdata/script/cgo_depends_on_syscall.txt b/libgo/go/cmd/go/testdata/script/cgo_depends_on_syscall.txt
new file mode 100644 (file)
index 0000000..bd4777c
--- /dev/null
@@ -0,0 +1,15 @@
+[!cgo] skip
+[!race] skip
+
+go list -race -deps foo
+stdout syscall
+
+-- go.mod --
+module foo
+
+go 1.16
+-- foo.go --
+package foo
+
+// #include <stdio.h>
+import "C"
diff --git a/libgo/go/cmd/go/testdata/script/cgo_flag_contains_space.txt b/libgo/go/cmd/go/testdata/script/cgo_flag_contains_space.txt
new file mode 100644 (file)
index 0000000..a3372bb
--- /dev/null
@@ -0,0 +1,16 @@
+[short] skip
+[!cgo] skip
+
+env GOCACHE=$WORK/gocache  # Looking for compile flags, so need a clean cache.
+go build -x -n main.go
+stderr '"-I[^"]+c flags"' # find quoted c flags
+! stderr '"-I[^"]+c flags".*"-I[^"]+c flags"' # don't find too many quoted c flags per line
+stderr '"-L[^"]+ld flags"' # find quoted ld flags
+! stderr '"-L[^"]+c flags".*"-L[^"]+c flags"' # don't find too many quoted ld flags per line
+
+-- main.go --
+package main
+// #cgo CFLAGS: -I"c flags"
+// #cgo LDFLAGS: -L"ld flags"
+import "C"
+func main() {}
diff --git a/libgo/go/cmd/go/testdata/script/cgo_path.txt b/libgo/go/cmd/go/testdata/script/cgo_path.txt
new file mode 100644 (file)
index 0000000..be9609e
--- /dev/null
@@ -0,0 +1,43 @@
+[!cgo] skip
+
+# Set CC explicitly to something that requires a PATH lookup.
+# Normally, the default is gcc or clang, but if CC was set during make.bash,
+# that becomes the default.
+[exec:clang] env CC=clang
+[exec:gcc] env CC=gcc
+[!exec:clang] [!exec:gcc] skip 'Unknown C compiler'
+
+env GOCACHE=$WORK/gocache  # Looking for compile flags, so need a clean cache.
+[!windows] env PATH=.:$PATH
+[!windows] chmod 0755 p/gcc p/clang
+[!windows] exists -exec p/gcc p/clang
+[windows] exists -exec p/gcc.bat p/clang.bat
+! exists p/bug.txt
+! go build -x
+stderr '^cgo: exec (clang|gcc): (clang|gcc) resolves to executable relative to current directory \(.[/\\](clang|gcc)(.bat)?\)$'
+! exists p/bug.txt
+
+-- go.mod --
+module m
+
+-- m.go --
+package m
+
+import _ "m/p"
+
+-- p/p.go --
+package p
+
+// #define X 1
+import "C"
+
+-- p/gcc --
+#!/bin/sh
+echo ran gcc >bug.txt
+-- p/clang --
+#!/bin/sh
+echo ran clang >bug.txt
+-- p/gcc.bat --
+echo ran gcc >bug.txt
+-- p/clang.bat --
+echo ran clang >bug.txt
diff --git a/libgo/go/cmd/go/testdata/script/cgo_path_space.txt b/libgo/go/cmd/go/testdata/script/cgo_path_space.txt
new file mode 100644 (file)
index 0000000..654295d
--- /dev/null
@@ -0,0 +1,56 @@
+# Check that if the PATH directory containing the C compiler has a space,
+# we can still use that compiler with cgo.
+# Verifies #43808.
+[!cgo] skip
+
+# Set CC explicitly to something that requires a PATH lookup.
+# Normally, the default is gcc or clang, but if CC was set during make.bash,
+# that becomes the default.
+[exec:clang] env CC=clang
+[exec:gcc] env CC=gcc
+[!exec:clang] [!exec:gcc] skip 'Unknown C compiler'
+
+[!windows] chmod 0755 $WORK/'program files'/clang
+[!windows] chmod 0755 $WORK/'program files'/gcc
+[!windows] exists -exec $WORK/'program files'/clang
+[!windows] exists -exec $WORK/'program files'/gcc
+[!windows] env PATH=$WORK/'program files':$PATH
+[windows] exists -exec $WORK/'program files'/gcc.bat
+[windows] exists -exec $WORK/'program files'/clang.bat
+[windows] env PATH=$WORK\'program files';%PATH%
+
+! exists $WORK/log.txt
+? go build -x
+exists $WORK/log.txt
+rm $WORK/log.txt
+
+# TODO(#41400, #43078): when CC is set explicitly, it should be allowed to
+# contain spaces separating arguments, and it should be possible to quote
+# arguments with spaces (including the path), as in CGO_CFLAGS and other
+# variables. For now, this doesn't work.
+[!windows] env CC=$WORK/'program files'/gcc
+[windows] env CC=$WORK\'program files'\gcc.bat
+! go build -x
+! exists $WORK/log.txt
+
+-- go.mod --
+module m
+
+-- m.go --
+package m
+
+// #define X 1
+import "C"
+
+-- $WORK/program files/gcc --
+#!/bin/sh
+
+echo ok >$WORK/log.txt
+-- $WORK/program files/clang --
+#!/bin/sh
+
+echo ok >$WORK/log.txt
+-- $WORK/program files/gcc.bat --
+echo ok >%WORK%\log.txt
+-- $WORK/program files/clang.bat --
+echo ok >%WORK%\log.txt
diff --git a/libgo/go/cmd/go/testdata/script/cgo_stale.txt b/libgo/go/cmd/go/testdata/script/cgo_stale.txt
new file mode 100644 (file)
index 0000000..9e46855
--- /dev/null
@@ -0,0 +1,39 @@
+# golang.org/issue/46347: a stale runtime/cgo should only force a single rebuild
+
+[!cgo] skip
+[short] skip
+
+
+# If we set a unique CGO_CFLAGS, the installed copy of runtime/cgo
+# should be reported as stale.
+
+env CGO_CFLAGS=-DTestScript_cgo_stale=true
+stale runtime/cgo
+
+
+# If we then build a package that uses cgo, runtime/cgo should be rebuilt and
+# cached with the new flag, but not installed to GOROOT (and thus still stale).
+
+env GOCACHE=$WORK/cache  # Use a fresh cache to avoid interference between runs.
+
+go build -x .
+stderr '[/\\]cgo'$GOEXE'["]? .* -importpath runtime/cgo'
+stale runtime/cgo
+
+
+# After runtime/cgo has been rebuilt and cached, it should not be rebuilt again
+# even though it is still reported as stale.
+
+go build -x .
+! stderr '[/\\]cgo'$GOEXE'["]? .* -importpath runtime/cgo'
+stale runtime/cgo
+
+
+-- go.mod --
+module example.com/m
+
+go 1.17
+-- m.go --
+package m
+
+import "C"
diff --git a/libgo/go/cmd/go/testdata/script/clean_binary.txt b/libgo/go/cmd/go/testdata/script/clean_binary.txt
new file mode 100644 (file)
index 0000000..7335f8a
--- /dev/null
@@ -0,0 +1,78 @@
+# Build something to create the executable, including several cases
+[short] skip
+
+# --------------------- clean executables -------------------------
+
+# case1: test file-named executable 'main'
+env GO111MODULE=on
+
+! exists main$GOEXE
+go build main.go
+exists -exec main$GOEXE
+go clean
+! exists main$GOEXE
+
+# case2: test module-named executable 'a.b.c'
+! exists a.b.c$GOEXE
+go build
+exists -exec a.b.c$GOEXE
+go clean
+! exists a.b.c$GOEXE
+
+# case3: directory-named executable 'src'
+env GO111MODULE=off
+
+! exists src$GOEXE
+go build
+exists -exec src$GOEXE
+go clean
+! exists src$GOEXE
+
+# --------------------- clean test files -------------------------
+
+# case1: test file-named test file
+env GO111MODULE=on
+
+! exists main.test$GOEXE
+go test -c main_test.go
+exists -exec main.test$GOEXE
+go clean
+! exists main.test$GOEXE
+
+# case2: test module-named test file
+! exists a.b.c.test$GOEXE
+go test -c
+exists -exec a.b.c.test$GOEXE
+go clean
+! exists a.b.c.test$GOEXE
+
+# case3: test directory-based test file
+env GO111MODULE=off
+
+! exists src.test$GOEXE
+go test -c
+exists -exec src.test$GOEXE
+go clean
+! exists src.test$GOEXE
+
+-- main.go --
+package main
+
+import "fmt"
+
+func main() {
+       fmt.Println("hello!")
+}
+
+-- main_test.go --
+package main
+
+import "testing"
+
+func TestSomething(t *testing.T) {
+}
+
+-- go.mod --
+module example.com/a.b.c/v2
+
+go 1.12
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/clean_cache_n.txt b/libgo/go/cmd/go/testdata/script/clean_cache_n.txt
new file mode 100644 (file)
index 0000000..4497b36
--- /dev/null
@@ -0,0 +1,25 @@
+# We're testing cache behavior, so start with a clean GOCACHE.
+env GOCACHE=$WORK/cache
+
+# Build something so that the cache gets populates
+go build main.go
+
+# Check that cache contains directories before running
+exists $GOCACHE/00
+
+# Run go clean -cache -n and ensure that directories weren't deleted
+go clean -cache -n
+exists $GOCACHE/00
+
+# Re-run go clean cache without the -n flag go ensure that directories were properly removed
+go clean -cache
+! exists $GOCACHE/00
+
+-- main.go --
+package main
+
+import "fmt"
+
+func main() {
+       fmt.Println("hello!")
+}
diff --git a/libgo/go/cmd/go/testdata/script/cover_asm.txt b/libgo/go/cmd/go/testdata/script/cover_asm.txt
new file mode 100644 (file)
index 0000000..57f76d6
--- /dev/null
@@ -0,0 +1,33 @@
+[short] skip
+[gccgo] skip # gccgo has no cover tool
+
+# Test cover for a package that has an assembly function.
+
+go test -outputdir=$WORK -coverprofile=cover.out coverasm
+go tool cover -func=$WORK/cover.out
+stdout '\tg\t*100.0%' # Check g is 100% covered.
+! stdout '\tf\t*[0-9]' # Check for no coverage on the assembly function
+
+-- go.mod --
+module coverasm
+
+go 1.16
+-- p.go --
+package p
+
+func f()
+
+func g() {
+       println("g")
+}
+-- p.s --
+// empty asm file,
+// so go test doesn't complain about declaration of f in p.go.
+-- p_test.go --
+package p
+
+import "testing"
+
+func Test(t *testing.T) {
+       g()
+}
diff --git a/libgo/go/cmd/go/testdata/script/cover_blank_func_decl.txt b/libgo/go/cmd/go/testdata/script/cover_blank_func_decl.txt
new file mode 100644 (file)
index 0000000..e7d5250
--- /dev/null
@@ -0,0 +1,35 @@
+[short] skip
+go test -cover coverblank
+stdout 'coverage: 100.0% of statements'
+
+
+-- go.mod --
+module coverblank
+
+go 1.16
+-- a.go --
+package coverblank
+
+func _() {
+       println("unreachable")
+}
+
+type X int
+
+func (x X) Print() {
+       println(x)
+}
+
+func (x X) _() {
+       println("unreachable")
+}
+
+-- a_test.go --
+package coverblank
+
+import "testing"
+
+func TestX(t *testing.T) {
+       var x X
+       x.Print()
+}
diff --git a/libgo/go/cmd/go/testdata/script/cover_cgo.txt b/libgo/go/cmd/go/testdata/script/cover_cgo.txt
new file mode 100644 (file)
index 0000000..9cf78f7
--- /dev/null
@@ -0,0 +1,42 @@
+[short] skip
+[!cgo] skip
+[gccgo] skip # gccgo has no cover tool
+
+# Test coverage on cgo code.
+
+go test -short -cover cgocover
+stdout  'coverage:.*[1-9][0-9.]+%'
+! stderr '[^0-9]0\.0%'
+
+-- go.mod --
+module cgocover
+
+go 1.16
+-- p.go --
+package p
+
+/*
+void
+f(void)
+{
+}
+*/
+import "C"
+
+var b bool
+
+func F() {
+       if b {
+               for {
+               }
+       }
+       C.f()
+}
+-- p_test.go --
+package p
+
+import "testing"
+
+func TestF(t *testing.T) {
+       F()
+}
diff --git a/libgo/go/cmd/go/testdata/script/cover_cgo_extra_file.txt b/libgo/go/cmd/go/testdata/script/cover_cgo_extra_file.txt
new file mode 100644 (file)
index 0000000..c53b979
--- /dev/null
@@ -0,0 +1,48 @@
+[short] skip
+[!cgo] skip
+[gccgo] skip # gccgo has no cover tool
+
+# Test coverage on cgo code. This test case includes an
+# extra empty non-cgo file in the package being checked.
+
+go test -short -cover cgocover4
+stdout  'coverage:.*[1-9][0-9.]+%'
+! stderr '[^0-9]0\.0%'
+
+-- go.mod --
+module cgocover4
+
+go 1.16
+-- notcgo.go --
+package p
+-- p.go --
+package p
+
+/*
+void
+f(void)
+{
+}
+*/
+import "C"
+
+var b bool
+
+func F() {
+       if b {
+               for {
+               }
+       }
+       C.f()
+}
+-- x_test.go --
+package p_test
+
+import (
+       . "cgocover4"
+       "testing"
+)
+
+func TestF(t *testing.T) {
+       F()
+}
diff --git a/libgo/go/cmd/go/testdata/script/cover_cgo_extra_test.txt b/libgo/go/cmd/go/testdata/script/cover_cgo_extra_test.txt
new file mode 100644 (file)
index 0000000..b501ab0
--- /dev/null
@@ -0,0 +1,49 @@
+[short] skip
+[!cgo] skip
+[gccgo] skip # gccgo has no cover tool
+
+# Test coverage on cgo code. This test case has an external
+# test that tests the code and an in-package test file with
+# no test cases.
+
+go test -short -cover cgocover3
+stdout  'coverage:.*[1-9][0-9.]+%'
+! stderr '[^0-9]0\.0%'
+
+-- go.mod --
+module cgocover3
+
+go 1.16
+-- p.go --
+package p
+
+/*
+void
+f(void)
+{
+}
+*/
+import "C"
+
+var b bool
+
+func F() {
+       if b {
+               for {
+               }
+       }
+       C.f()
+}
+-- p_test.go --
+package p
+-- x_test.go --
+package p_test
+
+import (
+       . "cgocover3"
+       "testing"
+)
+
+func TestF(t *testing.T) {
+       F()
+}
diff --git a/libgo/go/cmd/go/testdata/script/cover_cgo_xtest.txt b/libgo/go/cmd/go/testdata/script/cover_cgo_xtest.txt
new file mode 100644 (file)
index 0000000..79cc08c
--- /dev/null
@@ -0,0 +1,45 @@
+[short] skip
+[!cgo] skip
+[gccgo] skip # gccgo has no cover tool
+
+# Test cgo coverage with an external test.
+
+go test -short -cover cgocover2
+stdout  'coverage:.*[1-9][0-9.]+%'
+! stderr '[^0-9]0\.0%'
+
+-- go.mod --
+module cgocover2
+
+go 1.16
+-- p.go --
+package p
+
+/*
+void
+f(void)
+{
+}
+*/
+import "C"
+
+var b bool
+
+func F() {
+       if b {
+               for {
+               }
+       }
+       C.f()
+}
+-- x_test.go --
+package p_test
+
+import (
+       . "cgocover2"
+       "testing"
+)
+
+func TestF(t *testing.T) {
+       F()
+}
diff --git a/libgo/go/cmd/go/testdata/script/cover_dash_c.txt b/libgo/go/cmd/go/testdata/script/cover_dash_c.txt
new file mode 100644 (file)
index 0000000..8950f8d
--- /dev/null
@@ -0,0 +1,31 @@
+[short] skip
+[gccgo] skip
+
+# Test for issue 24588
+
+go test -c -o $WORK/coverdep -coverprofile=$WORK/no/such/dir/cover.out coverdep
+exists -exec $WORK/coverdep
+
+-- go.mod --
+module coverdep
+
+go 1.16
+-- p.go --
+package p
+
+import _ "coverdep/p1"
+
+func F() {
+}
+-- p1/p1.go --
+package p1
+
+import _ "errors"
+-- p_test.go --
+package p
+
+import "testing"
+
+func Test(t *testing.T) {
+       F()
+}
diff --git a/libgo/go/cmd/go/testdata/script/cover_dep_loop.txt b/libgo/go/cmd/go/testdata/script/cover_dep_loop.txt
new file mode 100644 (file)
index 0000000..36ea6e0
--- /dev/null
@@ -0,0 +1,36 @@
+[short] skip
+[gccgo] skip
+
+# coverdep2/p1's xtest imports coverdep2/p2 which imports coverdep2/p1.
+# Make sure that coverage on coverdep2/p2 recompiles coverdep2/p2.
+
+go test -short -cover coverdep2/p1
+stdout 'coverage: 100.0% of statements' # expect 100.0% coverage
+
+-- go.mod --
+module coverdep2
+
+go 1.16
+-- p1/p.go --
+package p1
+
+func F() int { return 1 }
+-- p1/p_test.go --
+package p1_test
+
+import (
+       "coverdep2/p2"
+       "testing"
+)
+
+func Test(t *testing.T) {
+       p2.F()
+}
+-- p2/p2.go --
+package p2
+
+import "coverdep2/p1"
+
+func F() {
+       p1.F()
+}
diff --git a/libgo/go/cmd/go/testdata/script/cover_dot_import.txt b/libgo/go/cmd/go/testdata/script/cover_dot_import.txt
new file mode 100644 (file)
index 0000000..d492e42
--- /dev/null
@@ -0,0 +1,29 @@
+[short] skip
+[gccgo] skip # gccgo has no cover tool
+
+go test -coverpkg=coverdot/a,coverdot/b coverdot/b
+! stderr '[^0-9]0\.0%'
+! stdout '[^0-9]0\.0%'
+
+-- go.mod --
+module coverdot
+
+go 1.16
+-- a/a.go --
+package a
+
+func F() {}
+-- b/b.go --
+package b
+
+import . "coverdot/a"
+
+func G() { F() }
+-- b/b_test.go --
+package b
+
+import "testing"
+
+func TestG(t *testing.T) {
+       G()
+}
diff --git a/libgo/go/cmd/go/testdata/script/cover_error.txt b/libgo/go/cmd/go/testdata/script/cover_error.txt
new file mode 100644 (file)
index 0000000..583a664
--- /dev/null
@@ -0,0 +1,74 @@
+[short] skip
+[gccgo] skip
+
+# Test line numbers in cover errors.
+
+# Get errors from a go test into stderr.txt
+! go test coverbad
+stderr 'p\.go:4' # look for error at coverbad/p.go:4
+[cgo] stderr 'p1\.go:6' # look for error at coverbad/p.go:6
+! stderr $WORK # make sure temporary directory isn't in error
+
+cp stderr $WORK/stderr.txt
+
+# Clean out character positions from stderr.txt
+# It's OK that stderr2 drops the character position in the error,
+# because of the //line directive (see golang.org/issue/22662).
+go run clean_charpos.go $WORK/stderr.txt &
+
+# Get errors from coverage into stderr2.txt
+! go test -cover coverbad
+cp stderr $WORK/stderr2.txt
+
+wait # for go run above
+
+cmp $WORK/stderr.txt $WORK/stderr2.txt
+
+-- go.mod --
+module coverbad
+
+go 1.16
+-- p.go --
+package p
+
+func f() {
+       g()
+}
+-- p1.go --
+package p
+
+import "C"
+
+func h() {
+       j()
+}
+-- p_test.go --
+package p
+
+import "testing"
+
+func Test(t *testing.T) {}
+-- clean_charpos.go --
+// +build ignore
+
+package main
+
+import (
+       "log"
+       "os"
+       "strings"
+)
+
+func main() {
+       log.SetFlags(0)
+       b, err := os.ReadFile(os.Args[1])
+       if err != nil {
+               log.Fatal(err)
+       }
+       s := strings.ReplaceAll(string(b), "p.go:4:2:", "p.go:4:")
+       s = strings.ReplaceAll(s, "p1.go:6:2:", "p1.go:6:")
+       os.WriteFile(os.Args[1], []byte(s), 0644)
+       if err != nil {
+               log.Fatal(err)
+       }
+}
diff --git a/libgo/go/cmd/go/testdata/script/cover_import_main_loop.txt b/libgo/go/cmd/go/testdata/script/cover_import_main_loop.txt
new file mode 100644 (file)
index 0000000..eb6de67
--- /dev/null
@@ -0,0 +1,26 @@
+[gccgo] skip # gccgo has no cover tool
+
+! go test -n importmain/test
+stderr 'not an importable package' # check that import main was detected
+! go test -n -cover importmain/test
+stderr 'not an importable package' # check that import main was detected
+
+-- go.mod --
+module importmain
+
+go 1.16
+-- ismain/main.go --
+package main
+
+import _ "importmain/test"
+
+func main() {}
+-- test/test.go --
+package test
+-- test/test_test.go --
+package test_test
+
+import "testing"
+import _ "importmain/ismain"
+
+func TestCase(t *testing.T) {}
diff --git a/libgo/go/cmd/go/testdata/script/cover_pattern.txt b/libgo/go/cmd/go/testdata/script/cover_pattern.txt
new file mode 100644 (file)
index 0000000..ec0850c
--- /dev/null
@@ -0,0 +1,41 @@
+[gccgo] skip
+
+# If coverpkg=m/sleepy... expands by package loading
+# (as opposed to pattern matching on deps)
+# then it will try to load sleepybad, which does not compile,
+# and the test command will fail.
+! go list m/sleepy...
+go test -c -n -coverprofile=$TMPDIR/cover.out -coverpkg=m/sleepy... -run=^$ m/sleepy1
+
+-- go.mod --
+module m
+
+go 1.16
+-- sleepy1/p_test.go --
+package p
+
+import (
+       "testing"
+       "time"
+)
+
+func Test1(t *testing.T) {
+       time.Sleep(200 * time.Millisecond)
+}
+-- sleepy2/p_test.go --
+package p
+
+import (
+       "testing"
+       "time"
+)
+
+func Test1(t *testing.T) {
+       time.Sleep(200 * time.Millisecond)
+}
+-- sleepybad/p.go --
+package p
+
+import ^
+
+var _ = io.DoesNotExist
diff --git a/libgo/go/cmd/go/testdata/script/cover_pkgall_imports.txt b/libgo/go/cmd/go/testdata/script/cover_pkgall_imports.txt
new file mode 100644 (file)
index 0000000..4e51726
--- /dev/null
@@ -0,0 +1,48 @@
+# This test checks that -coverpkg=all can be used
+# when the package pattern includes packages
+# which only have tests.
+# Verifies golang.org/issue/27333, golang.org/issue/43242.
+
+[short] skip
+cd $GOPATH/src/example.com/cov
+
+env GO111MODULE=on
+go test -coverpkg=all ./...
+
+env GO111MODULE=off
+go test -coverpkg=all ./...
+
+-- $GOPATH/src/example.com/cov/go.mod --
+module example.com/cov
+
+-- $GOPATH/src/example.com/cov/notest/notest.go --
+package notest
+
+func Foo() {}
+
+-- $GOPATH/src/example.com/cov/onlytest/onlytest_test.go --
+package onlytest_test
+
+import (
+       "testing"
+
+       "example.com/cov/notest"
+)
+
+func TestFoo(t *testing.T) {
+       notest.Foo()
+}
+
+-- $GOPATH/src/example.com/cov/withtest/withtest.go --
+package withtest
+
+func Bar() {}
+
+-- $GOPATH/src/example.com/cov/withtest/withtest_test.go --
+package withtest
+
+import "testing"
+
+func TestBar(t *testing.T) {
+       Bar()
+}
diff --git a/libgo/go/cmd/go/testdata/script/cover_runs.txt b/libgo/go/cmd/go/testdata/script/cover_runs.txt
new file mode 100644 (file)
index 0000000..38a7bb7
--- /dev/null
@@ -0,0 +1,13 @@
+[gccgo] skip 'gccgo has no cover tool'
+[short] skip
+
+go test -short -coverpkg=strings strings regexp
+! stdout '[^0-9]0\.0%'
+stdout  'strings.*coverage:.*[1-9][0-9.]+%'
+stdout  'regexp.*coverage:.*[1-9][0-9.]+%'
+
+go test -short -cover strings math regexp
+! stdout '[^0-9]0\.0%'
+stdout  'strings.*coverage:.*[1-9][0-9.]+%'
+stdout  'math.*coverage:.*[1-9][0-9.]+%'
+stdout  'regexp.*coverage:.*[1-9][0-9.]+%'
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/cover_statements.txt b/libgo/go/cmd/go/testdata/script/cover_statements.txt
new file mode 100644 (file)
index 0000000..4f3c9ca
--- /dev/null
@@ -0,0 +1,61 @@
+[short] skip
+go test -cover ./pkg1 ./pkg2 ./pkg3 ./pkg4
+stdout 'pkg1   \[no test files\]'
+stdout 'pkg2   \S+     coverage: 0.0% of statements \[no tests to run\]'
+stdout 'pkg3   \S+     coverage: 100.0% of statements'
+stdout 'pkg4   \S+     coverage: \[no statements\]'
+
+-- go.mod --
+module m
+
+go 1.16
+-- pkg1/a.go --
+package pkg1
+
+import "fmt"
+
+func F() {
+       fmt.Println("pkg1")
+}
+-- pkg2/a.go --
+package pkg2
+
+import "fmt"
+
+func F() {
+       fmt.Println("pkg2")
+}
+-- pkg2/a_test.go --
+package pkg2
+-- pkg3/a.go --
+package pkg3
+
+import "fmt"
+
+func F() {
+       fmt.Println("pkg3")
+}
+-- pkg3/a_test.go --
+package pkg3
+
+import "testing"
+
+func TestF(t *testing.T) {
+       F()
+}
+-- pkg4/a.go --
+package pkg4
+
+type T struct {
+       X bool
+}
+-- pkg4/a_test.go --
+package pkg4
+
+import (
+       "testing"
+)
+
+func TestT(t *testing.T) {
+       _ = T{}
+}
diff --git a/libgo/go/cmd/go/testdata/script/cover_sync_atomic_import.txt b/libgo/go/cmd/go/testdata/script/cover_sync_atomic_import.txt
new file mode 100644 (file)
index 0000000..433af9a
--- /dev/null
@@ -0,0 +1,28 @@
+[short] skip
+[gccgo] skip # gccgo has no cover tool
+
+go test -short -cover -covermode=atomic -coverpkg=coverdep/p1 coverdep
+
+-- go.mod --
+module coverdep
+
+go 1.16
+-- p.go --
+package p
+
+import _ "coverdep/p1"
+
+func F() {
+}
+-- p1/p1.go --
+package p1
+
+import _ "errors"
+-- p_test.go --
+package p
+
+import "testing"
+
+func Test(t *testing.T) {
+       F()
+}
diff --git a/libgo/go/cmd/go/testdata/script/doc.txt b/libgo/go/cmd/go/testdata/script/doc.txt
new file mode 100644 (file)
index 0000000..670308c
--- /dev/null
@@ -0,0 +1,77 @@
+[gccgo] skip
+
+# go doc --help
+! go doc --help
+stderr 'go doc'
+stderr 'go doc <pkg>'
+stderr 'go doc <sym>\[\.<methodOrField>\]'
+stderr 'go doc \[<pkg>\.\]<sym>\[\.<methodOrField>\]'
+stderr 'go doc \[<pkg>\.\]\[<sym>\.\]<methodOrField>'
+stderr 'go doc <pkg> <sym>\[\.<methodOrField>\]'
+
+# go help doc
+go help doc
+stdout 'go doc'
+stdout 'go doc <pkg>'
+stdout 'go doc <sym>\[\.<methodOrField>\]'
+stdout 'go doc \[<pkg>\.\]<sym>\[\.<methodOrField>\]'
+stdout 'go doc \[<pkg>\.\]\[<sym>\.\]<methodOrField>'
+stdout 'go doc <pkg> <sym>\[\.<methodOrField>\]'
+
+# go doc <pkg>
+go doc p/v2
+stdout .
+
+# go doc <pkg> <sym>
+go doc p/v2 Symbol
+stdout .
+
+# go doc <pkg> <sym> <method>
+! go doc p/v2 Symbol Method
+stderr .
+
+# go doc <pkg>.<sym>
+go doc p/v2.Symbol
+stdout .
+
+# go doc <pkg>.<sym>.<method>
+go doc p/v2.Symbol.Method
+stdout .
+
+# go doc <sym>
+go doc Symbol
+stdout .
+
+# go doc <sym> <method>
+! go doc Symbol Method
+stderr .
+
+# go doc <sym>.<method>
+go doc Symbol.Method
+stdout .
+
+# go doc <pkg>.<method>
+go doc p/v2.Method
+stdout .
+
+# go doc <pkg> <method>
+go doc p/v2 Method
+stdout .
+
+# go doc <method>
+go doc Method
+stdout .
+
+-- go.mod --
+module p/v2
+
+go 1.13
+
+-- p.go --
+package p
+
+type Symbol struct{}
+
+func (Symbol) Method() error {
+       return nil
+}
diff --git a/libgo/go/cmd/go/testdata/script/embed.txt b/libgo/go/cmd/go/testdata/script/embed.txt
new file mode 100644 (file)
index 0000000..04b17cd
--- /dev/null
@@ -0,0 +1,110 @@
+# go list shows patterns and files
+go list -f '{{.EmbedPatterns}}'
+stdout '\[x\*t\*t\]'
+go list -f '{{.EmbedFiles}}'
+stdout '\[x.txt\]'
+go list -test -f '{{.TestEmbedPatterns}}'
+stdout '\[y\*t\*t\]'
+go list -test -f '{{.TestEmbedFiles}}'
+stdout '\[y.txt\]'
+go list -test -f '{{.XTestEmbedPatterns}}'
+stdout '\[z\*t\*t\]'
+go list -test -f '{{.XTestEmbedFiles}}'
+stdout '\[z.txt\]'
+
+# build embeds x.txt
+go build -x
+stderr 'x.txt'
+
+# build uses cache correctly
+go build -x
+! stderr 'x.txt'
+cp x.txt2 x.txt
+go build -x
+stderr 'x.txt'
+
+# build rejects invalid names
+cp x.go2 x.go
+go build -x
+cp x.txt .git
+! go build -x
+stderr '^x.go:5:12: pattern [*]t: cannot embed file [.]git: invalid name [.]git$'
+rm .git
+
+# build rejects symlinks
+[symlink] symlink x.tzt -> x.txt
+[symlink] ! go build -x
+[symlink] stderr 'pattern [*]t: cannot embed irregular file x.tzt'
+[symlink] rm x.tzt
+
+# build rejects empty directories
+mkdir t
+! go build -x
+stderr '^x.go:5:12: pattern [*]t: cannot embed directory t: contains no embeddable files$'
+
+# build ignores symlinks and invalid names in directories
+cp x.txt t/.git
+! go build -x
+stderr '^x.go:5:12: pattern [*]t: cannot embed directory t: contains no embeddable files$'
+go list -e -f '{{.Incomplete}}'
+stdout 'true'
+[symlink] symlink t/x.link -> ../x.txt
+[symlink] ! go build -x
+[symlink] stderr '^x.go:5:12: pattern [*]t: cannot embed directory t: contains no embeddable files$'
+
+cp x.txt t/x.txt
+go build -x
+
+# build reports errors with positions in imported packages
+rm t/x.txt
+! go build m/use
+stderr '^x.go:5:12: pattern [*]t: cannot embed directory t: contains no embeddable files$'
+
+-- x.go --
+package p
+
+import "embed"
+
+//go:embed x*t*t
+var X embed.FS
+
+-- x_test.go --
+package p
+
+import "embed"
+
+//go:embed y*t*t
+var Y string
+
+-- x_x_test.go --
+package p_test
+
+import "embed"
+
+//go:embed z*t*t
+var Z string
+
+-- x.go2 --
+package p
+
+import "embed"
+
+//go:embed *t
+var X embed.FS
+
+-- x.txt --
+hello
+
+-- y.txt --
+-- z.txt --
+-- x.txt2 --
+not hello
+
+-- use/use.go --
+package use
+
+import _ "m"
+-- go.mod --
+module m
+
+go 1.16
diff --git a/libgo/go/cmd/go/testdata/script/embed_fmt.txt b/libgo/go/cmd/go/testdata/script/embed_fmt.txt
new file mode 100644 (file)
index 0000000..8a16afe
--- /dev/null
@@ -0,0 +1,22 @@
+# go fmt ignores file not found
+go fmt xnofmt.go
+cmp xnofmt.go xfmt.ref
+! go build xnofmt.go
+stderr 'xnofmt.go:5:12: pattern missing.txt: no matching files found'
+
+-- xnofmt.go --
+package p
+
+import "embed"
+
+//go:embed missing.txt
+var X  embed.FS
+-- xfmt.ref --
+package p
+
+import "embed"
+
+//go:embed missing.txt
+var X embed.FS
+-- go.mod --
+module m
diff --git a/libgo/go/cmd/go/testdata/script/env_cross_build.txt b/libgo/go/cmd/go/testdata/script/env_cross_build.txt
new file mode 100644 (file)
index 0000000..0643282
--- /dev/null
@@ -0,0 +1,31 @@
+# Test that the corect default GOEXPERIMENT is used when cross
+# building with GOENV (#46815).
+
+[gccgo] skip
+
+# Unset variables set by the TestScript harness. Users typically won't
+# explicitly configure these, and #46815 doesn't repro if they are.
+env GOOS=
+env GOARCH=
+env GOEXPERIMENT=
+
+env GOENV=windows-amd64
+go build internal/abi
+
+env GOENV=ios-arm64
+go build internal/abi
+
+env GOENV=linux-mips
+go build internal/abi
+
+-- windows-amd64 --
+GOOS=windows
+GOARCH=amd64
+
+-- ios-arm64 --
+GOOS=ios
+GOARCH=arm64
+
+-- linux-mips --
+GOOS=linux
+GOARCH=mips
diff --git a/libgo/go/cmd/go/testdata/script/env_exp.txt b/libgo/go/cmd/go/testdata/script/env_exp.txt
new file mode 100644 (file)
index 0000000..681512d
--- /dev/null
@@ -0,0 +1,17 @@
+# Test GOEXPERIMENT variable
+
+# go env shows default empty GOEXPERIMENT
+go env
+stdout GOEXPERIMENT=
+
+# go env shows valid experiments
+env GOEXPERIMENT=fieldtrack,staticlockranking
+go env GOEXPERIMENT
+stdout '.*fieldtrack.*staticlockranking.*'
+go env
+stdout 'GOEXPERIMENT=.*fieldtrack.*staticlockranking.*'
+
+# go env rejects unknown experiments
+env GOEXPERIMENT=bad
+! go env GOEXPERIMENT
+stderr 'unknown GOEXPERIMENT bad'
diff --git a/libgo/go/cmd/go/testdata/script/env_unset.txt b/libgo/go/cmd/go/testdata/script/env_unset.txt
new file mode 100644 (file)
index 0000000..647f265
--- /dev/null
@@ -0,0 +1,32 @@
+# Test that we can unset variables, even if initially invalid,
+# as long as resulting config is valid.
+
+[gccgo] skip
+
+env GOENV=badenv
+env GOOS=
+env GOARCH=
+env GOEXPERIMENT=
+
+! go env
+stderr '^go(\.exe)?: unknown GOEXPERIMENT badexp$'
+
+go env -u GOEXPERIMENT
+
+! go env
+stderr '^cmd/go: unsupported GOOS/GOARCH pair bados/badarch$'
+
+! go env -u GOOS
+stderr '^go env -u: unsupported GOOS/GOARCH pair \w+/badarch$'
+
+! go env -u GOARCH
+stderr '^go env -u: unsupported GOOS/GOARCH pair bados/\w+$'
+
+go env -u GOOS GOARCH
+
+go env
+
+-- badenv --
+GOOS=bados
+GOARCH=badarch
+GOEXPERIMENT=badexp
index dc6965241198c8c4e278f298876fc5639fde1ed0..7920fbaceff90ddb2964f06398919d494f1933f2 100644 (file)
@@ -174,3 +174,15 @@ go env -w GOOS=linux GOARCH=mips
 env GOOS=windows
 ! go env -u GOOS
 stderr 'unsupported GOOS/GOARCH.*windows/mips$'
+
+# go env -w should reject relative paths in GOMODCACHE environment.
+! go env -w GOMODCACHE=~/test
+stderr 'go env -w: GOMODCACHE entry is relative; must be absolute path: "~/test"'
+! go env -w GOMODCACHE=./test
+stderr 'go env -w: GOMODCACHE entry is relative; must be absolute path: "./test"'
+
+# go env -w checks validity of GOEXPERIMENT
+env GOEXPERIMENT=
+! go env -w GOEXPERIMENT=badexp
+stderr 'unknown GOEXPERIMENT badexp'
+go env -w GOEXPERIMENT=fieldtrack
index 297ec0fe3c7c28d533065de426e99e229388f54b..84bf41cfbafacd175597b77c26b9525e8f4c6e03 100644 (file)
@@ -6,6 +6,17 @@ go fmt -n exclude
 stdout 'exclude[/\\]x\.go'
 stdout 'exclude[/\\]x_linux\.go'
 
+# Test edge cases with gofmt.
+# Note that this execs GOROOT/bin/gofmt.
+
+! exec gofmt does-not-exist
+
+exec gofmt gofmt-dir/no-extension
+stdout 'package x'
+
+exec gofmt gofmt-dir
+! stdout 'package x'
+
 -- exclude/empty/x.txt --
 -- exclude/ignore/_x.go --
 package x
@@ -17,3 +28,5 @@ package x
 // +build windows
 
 package x
+-- gofmt-dir/no-extension --
+package x
diff --git a/libgo/go/cmd/go/testdata/script/gccgo_link_c.txt b/libgo/go/cmd/go/testdata/script/gccgo_link_c.txt
new file mode 100644 (file)
index 0000000..db2a291
--- /dev/null
@@ -0,0 +1,16 @@
+# Issue #7573
+# cmd/cgo: undefined reference when linking a C-library using gccgo
+
+[!cgo] skip
+[!exec:gccgo] skip
+
+go build -n -compiler gccgo cgoref
+stderr 'gccgo.*\-L [^ ]*alibpath \-lalib' # make sure that Go-inline "#cgo LDFLAGS:" ("-L alibpath -lalib") passed to gccgo linking stage
+
+-- cgoref/cgoref.go --
+package main
+// #cgo LDFLAGS: -L alibpath -lalib
+// void f(void) {}
+import "C"
+
+func main() { C.f() }
diff --git a/libgo/go/cmd/go/testdata/script/generate.txt b/libgo/go/cmd/go/testdata/script/generate.txt
new file mode 100644 (file)
index 0000000..73f5bbd
--- /dev/null
@@ -0,0 +1,99 @@
+[short] skip
+
+# Install an echo command because Windows doesn't have it.
+env GOBIN=$WORK/tmp/bin
+go install echo.go
+env PATH=$GOBIN${:}$PATH
+
+# Test go generate handles a simple command
+go generate ./generate/simple.go
+stdout 'Success'
+
+# Test go generate handles a command alias
+go generate './generate/alias.go'
+stdout 'Now is the time for all good men'
+
+# Test go generate's variable substitution
+go generate './generate/substitution.go'
+stdout $GOARCH' substitution.go:7 pabc xyzp/substitution.go/123'
+
+# Test go generate's run flag
+go generate -run y.s './generate/flag.go'
+stdout 'yes' # flag.go should select yes
+! stdout 'no' # flag.go should not select no
+
+# Test go generate provides the right "$GOPACKAGE" name in an x_test
+go generate './generate/env_test.go'
+stdout 'main_test'
+
+# Test go generate provides the right "$PWD"
+go generate './generate/env_pwd.go'
+stdout $WORK'[/\\]gopath[/\\]src[/\\]generate'
+
+-- echo.go --
+package main
+
+import (
+       "fmt"
+       "os"
+       "strings"
+)
+
+func main() {
+       fmt.Println(strings.Join(os.Args[1:], " "))
+       fmt.Println()
+}
+-- generate/simple.go --
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Simple test for go generate.
+
+// We include a build tag that go generate should ignore.
+
+// +build ignore
+
+//go:generate echo Success
+
+package p
+-- generate/alias.go --
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that go generate handles command aliases.
+
+//go:generate -command run echo Now is the time
+//go:generate run for all good men
+
+package p
+-- generate/substitution.go --
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test go generate variable substitution.
+
+//go:generate echo $GOARCH $GOFILE:$GOLINE ${GOPACKAGE}abc xyz$GOPACKAGE/$GOFILE/123
+
+package p
+-- generate/flag.go --
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test -run flag
+
+//go:generate echo oh yes my man
+//go:generate echo no, no, a thousand times no
+
+package p
+-- generate/env_test.go --
+package main_test
+
+//go:generate echo $GOPACKAGE
+-- generate/env_pwd.go --
+package p
+
+//go:generate echo $PWD
diff --git a/libgo/go/cmd/go/testdata/script/generate_bad_imports.txt b/libgo/go/cmd/go/testdata/script/generate_bad_imports.txt
new file mode 100644 (file)
index 0000000..4d31573
--- /dev/null
@@ -0,0 +1,15 @@
+[windows] skip # skip because windows has no echo command
+
+go generate gencycle
+stdout 'hello world' # check go generate gencycle ran the generator
+
+-- go.mod --
+module gencycle
+
+go 1.16
+-- gencycle.go --
+//go:generate echo hello world
+
+package gencycle
+
+import _ "gencycle"
diff --git a/libgo/go/cmd/go/testdata/script/generate_env.txt b/libgo/go/cmd/go/testdata/script/generate_env.txt
new file mode 100644 (file)
index 0000000..2df1663
--- /dev/null
@@ -0,0 +1,32 @@
+# Install an env command because Windows and plan9 don't have it.
+env GOBIN=$WORK/tmp/bin
+go install env.go
+[plan9] env path=$GOBIN${:}$path
+[!plan9] env PATH=$GOBIN${:}$PATH
+
+# Test generators have access to the environment
+go generate ./printenv.go
+stdout '^GOARCH='$GOARCH
+stdout '^GOOS='$GOOS
+stdout '^GOFILE='
+stdout '^GOLINE='
+stdout '^GOPACKAGE='
+stdout '^DOLLAR='
+
+-- env.go --
+package main
+
+import (
+       "fmt"
+       "os"
+)
+
+func main() {
+       for _, v := range os.Environ() {
+               fmt.Println(v)
+       }
+}
+-- printenv.go --
+package main
+
+//go:generate env
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/generate_invalid.txt b/libgo/go/cmd/go/testdata/script/generate_invalid.txt
new file mode 100644 (file)
index 0000000..e18e62c
--- /dev/null
@@ -0,0 +1,203 @@
+[short] skip
+
+# Install an echo command because Windows doesn't have it.
+env GOBIN=$WORK/tmp/bin
+go install echo.go
+env PATH=$GOBIN${:}$PATH
+
+# Test go generate for directory with no go files
+go generate ./nogo
+! stdout 'Fail'
+
+# Test go generate for package where all .go files are excluded by build
+# constraints
+go generate -v ./excluded
+! stdout 'Fail'
+! stderr 'go' # -v shouldn't list any files
+
+# Test go generate for "package" with no package clause in any file
+go generate ./nopkg
+stdout 'Success a'
+! stdout 'Fail'
+
+# Test go generate for package with inconsistent package clauses
+# $GOPACKAGE should depend on each file's package clause
+go generate ./inconsistent
+stdout 'Success a'
+stdout 'Success b'
+stdout -count=2 'Success c'
+! stdout 'Fail'
+
+# Test go generate for syntax errors before and after package clauses
+go generate ./syntax
+stdout 'Success a'
+stdout 'Success b'
+! stdout 'Fail'
+
+# Test go generate for files importing non-existent packages
+go generate ./importerr
+stdout 'Success a'
+stdout 'Success b'
+stdout 'Success c'
+
+-- echo.go --
+package main
+
+import (
+       "fmt"
+       "os"
+       "strings"
+)
+
+func main() {
+       fmt.Println(strings.Join(os.Args[1:], " "))
+       fmt.Println()
+}
+
+-- go.mod --
+module m
+
+go 1.16
+-- nogo/foo.txt --
+Text file in a directory without go files.
+Go generate should ignore this directory.
+//go:generate echo Fail nogo
+
+-- excluded/a.go --
+// Include a build tag that go generate should exclude.
+// Go generate should ignore this file.
+
+// +build a
+
+//go:generate echo Fail a
+
+package excluded
+
+-- excluded/b.go --
+// Include a build tag that go generate should exclude.
+// Go generate should ignore this file.
+
+//go:generate echo Fail b
+
+// +build b
+
+package excluded
+
+
+-- nopkg/a.go --
+// Go file with package clause after comment.
+// Go generate should process this file.
+
+/* Pre-comment */ package nopkg
+//go:generate echo Success a
+
+-- nopkg/b.go --
+// Go file with commented package clause.
+// Go generate should ignore this file.
+
+//package nopkg
+
+//go:generate echo Fail b
+
+-- nopkg/c.go --
+// Go file with package clause inside multiline comment.
+// Go generate should ignore this file.
+
+/*
+package nopkg
+*/
+
+//go:generate echo Fail c
+
+-- nopkg/d.go --
+// Go file with package clause inside raw string literal.
+// Go generate should ignore this file.
+
+const foo = `
+package nopkg
+`
+//go:generate echo Fail d
+
+-- nopkg/e.go --
+// Go file without package clause.
+// Go generate should ignore this file.
+
+//go:generate echo Fail e
+
+-- inconsistent/a.go --
+// Valid go file with inconsistent package name.
+// Go generate should process this file with GOPACKAGE=a
+
+package a
+//go:generate echo Success $GOPACKAGE
+
+-- inconsistent/b.go --
+// Valid go file with inconsistent package name.
+// Go generate should process this file with GOPACKAGE=b
+
+//go:generate echo Success $GOPACKAGE
+package b
+
+-- inconsistent/c.go --
+// Go file with two package clauses.
+// Go generate should process this file with GOPACKAGE=c
+
+//go:generate echo Success $GOPACKAGE
+package c
+// Invalid package clause, should be ignored:
+package cinvalid
+//go:generate echo Success $GOPACKAGE
+
+-- inconsistent/d.go --
+// Go file with invalid package name.
+// Go generate should ignore this file.
+
+package +d+
+//go:generate echo Fail $GOPACKAGE
+
+-- syntax/a.go --
+// Go file with syntax error after package clause.
+// Go generate should process this file.
+
+package syntax
+123
+//go:generate echo Success a
+
+-- syntax/b.go --
+// Go file with syntax error after package clause.
+// Go generate should process this file.
+
+package syntax; 123
+//go:generate echo Success b
+
+-- syntax/c.go --
+// Go file with syntax error before package clause.
+// Go generate should ignore this file.
+
+foo
+package syntax
+//go:generate echo Fail c
+
+-- importerr/a.go --
+// Go file which imports non-existing package.
+// Go generate should process this file.
+
+package importerr
+//go:generate echo Success a
+import "foo"
+
+-- importerr/b.go --
+// Go file which imports non-existing package.
+// Go generate should process this file.
+
+//go:generate echo Success b
+package importerr
+import "bar"
+
+-- importerr/c.go --
+// Go file which imports non-existing package.
+// Go generate should process this file.
+
+package importerr
+import "moo"
+//go:generate echo Success c
index b71cc7fe010a1e182342d70ed003aced170fee88..ec4f8d32432179bc97c5fe9fccb56d1527c664e3 100644 (file)
@@ -3,9 +3,10 @@
 [!net] skip
 [!exec:git] skip
 
+env GONOSUMDB=bazil.org,github.com,golang.org
 env GO111MODULE=off
-go get -d -insecure bazil.org/fuse/fs/fstestutil
+go get -d bazil.org/fuse/fs/fstestutil
 
 env GO111MODULE=on
 env GOPROXY=direct
-go get -d -insecure bazil.org/fuse/fs/fstestutil
+go get -d bazil.org/fuse/fs/fstestutil
diff --git a/libgo/go/cmd/go/testdata/script/get_custom_domain_wildcard.txt b/libgo/go/cmd/go/testdata/script/get_custom_domain_wildcard.txt
new file mode 100644 (file)
index 0000000..cda25e1
--- /dev/null
@@ -0,0 +1,6 @@
+[!net] skip
+[!exec:git] skip
+env GO111MODULE=off
+
+go get -u rsc.io/pdf/...
+exists $GOPATH/bin/pdfpasswd$GOEXE
diff --git a/libgo/go/cmd/go/testdata/script/get_dash_t.txt b/libgo/go/cmd/go/testdata/script/get_dash_t.txt
new file mode 100644 (file)
index 0000000..baac916
--- /dev/null
@@ -0,0 +1,9 @@
+# Tests issue 8181
+
+[!net] skip
+[!exec:git] skip
+env GO111MODULE=off
+
+go get -v -t github.com/rsc/go-get-issue-8181/a github.com/rsc/go-get-issue-8181/b
+go list ...
+stdout 'x/build/gerrit'
diff --git a/libgo/go/cmd/go/testdata/script/get_domain_root.txt b/libgo/go/cmd/go/testdata/script/get_domain_root.txt
new file mode 100644 (file)
index 0000000..9187848
--- /dev/null
@@ -0,0 +1,20 @@
+# Tests issue #9357
+# go get foo.io (not foo.io/subdir) was not working consistently.
+
+[!net] skip
+[!exec:git] skip
+env GO111MODULE=off
+
+# go-get-issue-9357.appspot.com is running
+# the code at github.com/rsc/go-get-issue-9357,
+# a trivial Go on App Engine app that serves a
+# <meta> tag for the domain root.
+go get -d go-get-issue-9357.appspot.com
+go get go-get-issue-9357.appspot.com
+go get -u go-get-issue-9357.appspot.com
+
+rm $GOPATH/src/go-get-issue-9357.appspot.com
+go get go-get-issue-9357.appspot.com
+
+rm $GOPATH/src/go-get-issue-9357.appspot.com
+go get -u go-get-issue-9357.appspot.com
diff --git a/libgo/go/cmd/go/testdata/script/get_dot_slash_download.txt b/libgo/go/cmd/go/testdata/script/get_dot_slash_download.txt
new file mode 100644 (file)
index 0000000..dbaf46c
--- /dev/null
@@ -0,0 +1,10 @@
+[!net] skip
+[!exec:git] skip
+env GO111MODULE=off
+
+# Tests Issues #9797 and #19769
+
+mkdir $WORK/tmp/src/rsc.io
+env GOPATH=$WORK/tmp
+cd $WORK/tmp/src/rsc.io
+go get ./pprof_mac_fix
diff --git a/libgo/go/cmd/go/testdata/script/get_go_file.txt b/libgo/go/cmd/go/testdata/script/get_go_file.txt
new file mode 100644 (file)
index 0000000..bed8720
--- /dev/null
@@ -0,0 +1,60 @@
+# Tests Issue #38478
+# Tests that go get in GOPATH mode returns a specific error if the argument
+# ends with '.go', and either has no slash or refers to an existing file.
+
+env GO111MODULE=off
+
+# argument doesn't have .go suffix
+go get -d test
+
+# argument has .go suffix, is a file and exists
+! go get -d test.go
+stderr 'go get test.go: arguments must be package or module paths'
+
+# argument has .go suffix, doesn't exist and has no slashes
+! go get -d test_missing.go
+stderr 'go get test_missing.go: arguments must be package or module paths'
+
+# argument has .go suffix, is a file and exists in sub-directory
+! go get -d test/test.go
+stderr 'go get: test/test.go exists as a file, but ''go get'' requires package arguments'
+
+# argument has .go suffix, doesn't exist and has slashes
+! go get -d test/test_missing.go
+! stderr 'arguments must be package or module paths'
+! stderr 'exists as a file, but ''go get'' requires package arguments'
+
+# argument has .go suffix, is a symlink and exists
+[symlink] symlink test_sym.go -> test.go
+[symlink] ! go get -d test_sym.go
+[symlink] stderr 'go get test_sym.go: arguments must be package or module paths'
+[symlink] rm test_sym.go
+
+# argument has .go suffix, is a symlink and exists in sub-directory
+[symlink] symlink test/test_sym.go -> test.go
+[symlink] ! go get -d test/test_sym.go
+[symlink] stderr 'go get: test/test_sym.go exists as a file, but ''go get'' requires package arguments'
+[symlink] rm test_sym.go
+
+# argument has .go suffix, is a directory and exists
+mkdir test_dir.go
+! go get -d test_dir.go
+stderr 'go get test_dir.go: arguments must be package or module paths'
+rm test_dir.go
+
+# argument has .go suffix, is a directory and exists in sub-directory
+mkdir test/test_dir.go
+! go get -d test/test_dir.go
+! stderr 'arguments must be package or module paths'
+! stderr 'exists as a file, but ''go get'' requires package arguments'
+rm test/test_dir.go
+
+
+-- test.go --
+package main
+func main() {println("test")}
+
+
+-- test/test.go --
+package main
+func main() {println("test")}
diff --git a/libgo/go/cmd/go/testdata/script/get_goroot.txt b/libgo/go/cmd/go/testdata/script/get_goroot.txt
new file mode 100644 (file)
index 0000000..929435a
--- /dev/null
@@ -0,0 +1,53 @@
+[!net] skip
+env GO111MODULE=off
+
+# Issue 4186. go get cannot be used to download packages to $GOROOT.
+# Test that without GOPATH set, go get should fail.
+
+# Fails because GOROOT=GOPATH
+env GOPATH=$WORK/tmp
+env GOROOT=$WORK/tmp
+! go get -d github.com/golang/example/hello
+stderr 'warning: GOPATH set to GOROOT'
+stderr '\$GOPATH must not be set to \$GOROOT'
+
+# Fails because GOROOT=GOPATH after cleaning.
+env GOPATH=$WORK/tmp/
+env GOROOT=$WORK/tmp
+! go get -d github.com/golang/example/hello
+stderr 'warning: GOPATH set to GOROOT'
+stderr '\$GOPATH must not be set to \$GOROOT'
+
+env GOPATH=$WORK/tmp
+env GOROOT=$WORK/tmp/
+! go get -d github.com/golang/example/hello
+stderr 'warning: GOPATH set to GOROOT'
+stderr '\$GOPATH must not be set to \$GOROOT'
+
+# Make a home directory
+mkdir $WORK/home/go
+
+# Fails because GOROOT=$HOME/go so default GOPATH unset.
+[windows] env USERPROFILE=$WORK/home
+[plan9] env home=$WORK/home
+[!windows] [!plan9] env HOME=$WORK/home
+env GOPATH=
+env GOROOT=$WORK/home/go
+! go get -d github.com/golang/example/hello
+stderr '\$GOPATH not set'
+
+[windows] env USERPROFILE=$WORK/home/
+[plan9] env home=$WORK/home/
+[!windows] [!plan9] env HOME=$WORK/home/
+env GOPATH=
+env GOROOT=$WORK/home/go
+! go get -d github.com/golang/example/hello
+stderr '\$GOPATH not set'
+
+[windows] env USERPROFILE=$WORK/home
+[plan9] env home=$WORK/home
+[!windows] [!plan9] env HOME=$WORK/home
+env GOPATH=
+env GOROOT=$WORK/home/go/
+! go get -d github.com/golang/example/hello
+stderr '\$GOPATH not set'
diff --git a/libgo/go/cmd/go/testdata/script/get_insecure.txt b/libgo/go/cmd/go/testdata/script/get_insecure.txt
new file mode 100644 (file)
index 0000000..69930f7
--- /dev/null
@@ -0,0 +1,57 @@
+# TODO(matloob): Split this test into two? It's one of the slowest tests we have.
+
+[!net] skip
+[!exec:git] skip
+
+env PATH=$WORK/tmp/bin${:}$PATH
+go build -o $WORK/tmp/bin/ssh ssh.go
+
+# GOPATH: Set up
+env GO111MODULE=off
+
+# GOPATH: Try go get -d of HTTP-only repo (should fail).
+! go get -d insecure.go-get-issue-15410.appspot.com/pkg/p
+
+# GOPATH: Try again with GOINSECURE (should succeed).
+env GOINSECURE=insecure.go-get-issue-15410.appspot.com
+go get -d insecure.go-get-issue-15410.appspot.com/pkg/p
+
+# GOPATH: Try updating without GOINSECURE (should fail).
+env GOINSECURE=''
+! go get -d -u -f insecure.go-get-issue-15410.appspot.com/pkg/p
+
+# Modules: Set up
+env GOPATH=$WORK/m/gp
+mkdir $WORK/m
+cp module_file $WORK/m/go.mod
+cd $WORK/m
+env GO111MODULE=on
+env GOPROXY=''
+
+# Modules: Try go get -d of HTTP-only repo (should fail).
+! go get -d insecure.go-get-issue-15410.appspot.com/pkg/p
+
+# Modules: Try again with GOINSECURE (should succeed).
+env GOINSECURE=insecure.go-get-issue-15410.appspot.com
+env GONOSUMDB=insecure.go-get-issue-15410.appspot.com
+go get -d insecure.go-get-issue-15410.appspot.com/pkg/p
+
+# Modules: Try updating without GOINSECURE (should fail).
+env GOINSECURE=''
+env GONOSUMDB=''
+! go get -d -u -f insecure.go-get-issue-15410.appspot.com/pkg/p
+
+go list -m ...
+stdout 'insecure.go-get-issue'
+
+-- ssh.go --
+// stub out uses of ssh by go get
+package main
+
+import "os"
+
+func main() {
+       os.Exit(1)
+}
+-- module_file --
+module m
diff --git a/libgo/go/cmd/go/testdata/script/get_insecure_custom_domain.txt b/libgo/go/cmd/go/testdata/script/get_insecure_custom_domain.txt
new file mode 100644 (file)
index 0000000..7eba42e
--- /dev/null
@@ -0,0 +1,8 @@
+[!net] skip
+[!exec:git] skip
+env GO111MODULE=off
+
+! go get -d insecure.go-get-issue-15410.appspot.com/pkg/p
+
+env GOINSECURE=insecure.go-get-issue-15410.appspot.com
+go get -d insecure.go-get-issue-15410.appspot.com/pkg/p
diff --git a/libgo/go/cmd/go/testdata/script/get_insecure_env.txt b/libgo/go/cmd/go/testdata/script/get_insecure_env.txt
new file mode 100644 (file)
index 0000000..8d88427
--- /dev/null
@@ -0,0 +1,29 @@
+[!net] skip
+[!exec:git] skip
+
+# GOPATH: Set up
+env GO111MODULE=off
+
+# GOPATH: Try go get -d of HTTP-only repo (should fail).
+! go get -d insecure.go-get-issue-15410.appspot.com/pkg/p
+
+# GOPATH: Try again with invalid GOINSECURE (should fail).
+env GOINSECURE=insecure.go-get-issue-15410.appspot.com/pkg/q
+! go get -d insecure.go-get-issue-15410.appspot.com/pkg/p
+
+# GOPATH: Try with correct GOINSECURE (should succeed).
+env GOINSECURE=insecure.go-get-issue-15410.appspot.com/pkg/p
+go get -d insecure.go-get-issue-15410.appspot.com/pkg/p
+
+# GOPATH: Try updating without GOINSECURE (should fail).
+env GOINSECURE=
+! go get -d -u -f insecure.go-get-issue-15410.appspot.com/pkg/p
+
+# GOPATH: Try updating with GOINSECURE glob (should succeed).
+env GOINSECURE=*.go-get-*.appspot.com
+go get -d -u -f insecure.go-get-issue-15410.appspot.com/pkg/p
+
+# GOPATH: Try updating with GOINSECURE base URL (should succeed).
+env GOINSECURE=insecure.go-get-issue-15410.appspot.com
+go get -d -u -f insecure.go-get-issue-15410.appspot.com/pkg/p
+
diff --git a/libgo/go/cmd/go/testdata/script/get_insecure_no_longer_supported.txt b/libgo/go/cmd/go/testdata/script/get_insecure_no_longer_supported.txt
new file mode 100644 (file)
index 0000000..2517664
--- /dev/null
@@ -0,0 +1,13 @@
+# GOPATH: Set up
+env GO111MODULE=off
+
+# GOPATH: Fetch with insecure, should error
+! go get -insecure test
+stderr 'go get: -insecure flag is no longer supported; use GOINSECURE instead'
+
+# Modules: Set up
+env GO111MODULE=on
+
+# Modules: Fetch with insecure, should error
+! go get -insecure test
+stderr 'go get: -insecure flag is no longer supported; use GOINSECURE instead'
index 0478d1f75dea2f99b0281dd7b2ec3e76688d732d..fb5f26951cdad9dfdd72f67775db707149f7e9a4 100644 (file)
@@ -1,4 +1,4 @@
-# golang.org/issue/29591: 'go get' was following plain-HTTP redirects even without -insecure.
+# golang.org/issue/29591: 'go get' was following plain-HTTP redirects even without -insecure (now replaced by GOINSECURE).
 # golang.org/issue/34049: 'go get' would panic in case of an insecure redirect in GOPATH mode
 
 [!net] skip
@@ -9,4 +9,5 @@ env GO111MODULE=off
 ! go get -d vcs-test.golang.org/insecure/go/insecure
 stderr 'redirected .* to insecure URL'
 
-go get -d -insecure vcs-test.golang.org/insecure/go/insecure
+env GOINSECURE=vcs-test.golang.org/insecure/go/insecure
+go get -d vcs-test.golang.org/insecure/go/insecure
diff --git a/libgo/go/cmd/go/testdata/script/get_insecure_update.txt b/libgo/go/cmd/go/testdata/script/get_insecure_update.txt
new file mode 100644 (file)
index 0000000..e1a1a23
--- /dev/null
@@ -0,0 +1,14 @@
+[!net] skip
+[!exec:git] skip
+env GO111MODULE=off
+
+# Clone the repo via HTTP manually.
+exec git clone -q http://github.com/golang/example github.com/golang/example
+
+# Update without GOINSECURE should fail.
+# We need -f to ignore import comments.
+! go get -d -u -f github.com/golang/example/hello
+
+# Update with GOINSECURE should succeed.
+env GOINSECURE=github.com/golang/example/hello
+go get -d -u -f github.com/golang/example/hello
diff --git a/libgo/go/cmd/go/testdata/script/get_internal_wildcard.txt b/libgo/go/cmd/go/testdata/script/get_internal_wildcard.txt
new file mode 100644 (file)
index 0000000..ff20d4b
--- /dev/null
@@ -0,0 +1,6 @@
+[!net] skip
+[!exec:git] skip
+env GO111MODULE=off
+
+# This used to fail with errors about internal packages
+go get github.com/rsc/go-get-issue-11960/...
diff --git a/libgo/go/cmd/go/testdata/script/get_issue11307.txt b/libgo/go/cmd/go/testdata/script/get_issue11307.txt
new file mode 100644 (file)
index 0000000..9d6b7dd
--- /dev/null
@@ -0,0 +1,9 @@
+# go get -u was not working except in checkout directory
+
+[!net] skip
+[!exec:git] skip
+env GO111MODULE=off
+
+env GOPATH=$WORK/tmp/gopath
+go get github.com/rsc/go-get-issue-11307
+go get -u github.com/rsc/go-get-issue-11307 # was failing
diff --git a/libgo/go/cmd/go/testdata/script/get_legacy.txt b/libgo/go/cmd/go/testdata/script/get_legacy.txt
new file mode 100644 (file)
index 0000000..938d428
--- /dev/null
@@ -0,0 +1,58 @@
+# This test was converted from a test in vendor_test.go (which no longer exists).
+# That seems to imply that it's about vendoring semantics, but the test doesn't
+# use 'go -mod=vendor' (and none of the fetched repos have vendor folders).
+# The test still seems to be useful as a test of direct-mode go get.
+
+[short] skip
+[!exec:git] skip
+env GO111MODULE=off
+
+env GOPATH=$WORK/tmp/d1
+go get vcs-test.golang.org/git/modlegacy1-old.git/p1
+go list -f '{{.Deps}}' vcs-test.golang.org/git/modlegacy1-old.git/p1
+stdout 'new.git/p2' # old/p1 should depend on new/p2
+! stdout new.git/v2/p2 # old/p1 should NOT depend on new/v2/p2
+go build vcs-test.golang.org/git/modlegacy1-old.git/p1 vcs-test.golang.org/git/modlegacy1-new.git/p1
+! stdout .
+
+env GOPATH=$WORK/tmp/d2
+
+rm $GOPATH
+go get github.com/rsc/vgotest5
+go get github.com/rsc/vgotest4
+go get github.com/myitcv/vgo_example_compat
+
+rm $GOPATH
+go get github.com/rsc/vgotest4
+go get github.com/rsc/vgotest5
+go get github.com/myitcv/vgo_example_compat
+
+rm $GOPATH
+go get github.com/rsc/vgotest4 github.com/rsc/vgotest5
+go get github.com/myitcv/vgo_example_compat
+
+rm $GOPATH
+go get github.com/rsc/vgotest5 github.com/rsc/vgotest4
+go get github.com/myitcv/vgo_example_compat
+
+rm $GOPATH
+go get github.com/myitcv/vgo_example_compat
+go get github.com/rsc/vgotest5 github.com/rsc/vgotest4
+
+rm $GOPATH
+go get github.com/myitcv/vgo_example_compat github.com/rsc/vgotest4 github.com/rsc/vgotest5
+
+rm $GOPATH
+go get github.com/myitcv/vgo_example_compat github.com/rsc/vgotest5 github.com/rsc/vgotest4
+
+rm $GOPATH
+go get github.com/rsc/vgotest4 github.com/myitcv/vgo_example_compat github.com/rsc/vgotest5
+
+rm $GOPATH
+go get github.com/rsc/vgotest4 github.com/rsc/vgotest5 github.com/myitcv/vgo_example_compat
+
+rm $GOPATH
+go get github.com/rsc/vgotest5 github.com/myitcv/vgo_example_compat github.com/rsc/vgotest4
+
+rm $GOPATH
+go get github.com/rsc/vgotest5 github.com/rsc/vgotest4 github.com/myitcv/vgo_example_compat
diff --git a/libgo/go/cmd/go/testdata/script/get_non_pkg.txt b/libgo/go/cmd/go/testdata/script/get_non_pkg.txt
new file mode 100644 (file)
index 0000000..a878530
--- /dev/null
@@ -0,0 +1,14 @@
+[!net] skip
+[!exec:git] skip
+
+env GOBIN=$WORK/tmp/gobin
+env GO111MODULE=off
+
+! go get -d golang.org/x/tools
+stderr 'golang.org/x/tools: no Go files'
+
+! go get -d -u golang.org/x/tools
+stderr 'golang.org/x/tools: no Go files'
+
+! go get -d golang.org/x/tools
+stderr 'golang.org/x/tools: no Go files'
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/get_race.txt b/libgo/go/cmd/go/testdata/script/get_race.txt
new file mode 100644 (file)
index 0000000..16a560a
--- /dev/null
@@ -0,0 +1,8 @@
+# Tests issue #20502
+
+[!net] skip
+[!exec:git] skip
+[!race] skip
+env GO111MODULE=off
+
+go get -race github.com/rsc/go-get-issue-9224-cmd
diff --git a/libgo/go/cmd/go/testdata/script/get_test_only.txt b/libgo/go/cmd/go/testdata/script/get_test_only.txt
new file mode 100644 (file)
index 0000000..a3f38dd
--- /dev/null
@@ -0,0 +1,6 @@
+[!net] skip
+[!exec:git] skip
+env GO111MODULE=off
+
+go get golang.org/x/tour/content...
+go get -t golang.org/x/tour/content...
diff --git a/libgo/go/cmd/go/testdata/script/get_update.txt b/libgo/go/cmd/go/testdata/script/get_update.txt
new file mode 100644 (file)
index 0000000..9afce6a
--- /dev/null
@@ -0,0 +1,25 @@
+# Tests Issue #9224
+# The recursive updating was trying to walk to
+# former dependencies, not current ones.
+
+[!net] skip
+[!exec:git] skip
+env GO111MODULE=off
+
+# Rewind
+go get github.com/rsc/go-get-issue-9224-cmd
+cd $GOPATH/src/github.com/rsc/go-get-issue-9224-lib
+exec git reset --hard HEAD~
+cd $GOPATH/src
+
+# Run get
+go get -u 'github.com/rsc/go-get-issue-9224-cmd'
+
+# (Again with -d -u) Rewind
+go get github.com/rsc/go-get-issue-9224-cmd
+cd $GOPATH/src/github.com/rsc/go-get-issue-9224-lib
+exec git reset --hard HEAD~
+cd $GOPATH/src
+
+# (Again with -d -u) Run get
+go get -d -u 'github.com/rsc/go-get-issue-9224-cmd'
diff --git a/libgo/go/cmd/go/testdata/script/get_update_all.txt b/libgo/go/cmd/go/testdata/script/get_update_all.txt
new file mode 100644 (file)
index 0000000..2b75849
--- /dev/null
@@ -0,0 +1,9 @@
+# Issue 14444: go get -u .../ duplicate loads errors
+# Check that go get update -u ... does not try to load duplicates
+
+[!net] skip
+
+env GO111MODULE=off
+
+go get -u -n .../
+! stderr 'duplicate loads of' # make sure old packages are removed from cache
diff --git a/libgo/go/cmd/go/testdata/script/get_update_unknown_protocol.txt b/libgo/go/cmd/go/testdata/script/get_update_unknown_protocol.txt
new file mode 100644 (file)
index 0000000..b00adea
--- /dev/null
@@ -0,0 +1,14 @@
+[!net] skip
+[!exec:git] skip
+env GO111MODULE=off
+
+# Clone the repo via HTTPS manually.
+exec git clone -q https://github.com/golang/example github.com/golang/example
+
+# Configure the repo to use a protocol unknown to cmd/go
+# that still actually works.
+cd github.com/golang/example
+exec git remote set-url origin xyz://github.com/golang/example
+exec git config --local url.https://github.com/.insteadOf xyz://github.com/
+
+go get -d -u -f github.com/golang/example/hello
diff --git a/libgo/go/cmd/go/testdata/script/get_update_wildcard.txt b/libgo/go/cmd/go/testdata/script/get_update_wildcard.txt
new file mode 100644 (file)
index 0000000..4e66004
--- /dev/null
@@ -0,0 +1,16 @@
+# Issue 14450: go get -u .../ tried to import not downloaded package
+
+[!net] skip
+[!exec:git] skip
+env GO111MODULE=off
+
+go get github.com/tmwh/go-get-issue-14450/a
+! go get -u .../
+stderr 'cannot find package.*d-dependency/e'
+
+# Even though get -u failed, the source for others should be downloaded.
+exists github.com/tmwh/go-get-issue-14450/b
+exists github.com/tmwh/go-get-issue-14450-b-dependency/c
+exists github.com/tmwh/go-get-issue-14450-b-dependency/d
+
+! exists github.com/tmwh/go-get-issue-14450-c-dependency/e
diff --git a/libgo/go/cmd/go/testdata/script/get_vcs_error_message.txt b/libgo/go/cmd/go/testdata/script/get_vcs_error_message.txt
new file mode 100644 (file)
index 0000000..8dc84fc
--- /dev/null
@@ -0,0 +1,9 @@
+# Test that the Version Control error message includes the correct directory
+env GO111MODULE=off
+! go get -u foo
+stderr gopath(\\\\|/)src(\\\\|/)foo
+
+-- foo/foo.go --
+package foo
+-- math/math.go --
+package math
diff --git a/libgo/go/cmd/go/testdata/script/get_vendor.txt b/libgo/go/cmd/go/testdata/script/get_vendor.txt
new file mode 100644 (file)
index 0000000..4ebb8a2
--- /dev/null
@@ -0,0 +1,95 @@
+[short] skip
+env GO111MODULE=off
+
+cd $GOPATH/src/v
+go run m.go
+go test
+go list -f '{{.Imports}}'
+stdout 'v/vendor/vendor.org/p'
+go list -f '{{.TestImports}}'
+stdout 'v/vendor/vendor.org/p'
+go get -d
+go get -t -d
+
+[!net] stop
+[!exec:git] stop
+
+cd $GOPATH/src
+
+# Update
+go get 'github.com/rsc/go-get-issue-11864'
+go get -u 'github.com/rsc/go-get-issue-11864'
+exists github.com/rsc/go-get-issue-11864/vendor
+
+# get -u
+rm $GOPATH
+mkdir $GOPATH/src
+go get -u 'github.com/rsc/go-get-issue-11864'
+exists github.com/rsc/go-get-issue-11864/vendor
+
+# get -t -u
+rm $GOPATH
+mkdir $GOPATH/src
+go get -t -u 'github.com/rsc/go-get-issue-11864/...'
+exists github.com/rsc/go-get-issue-11864/vendor
+
+# Submodules
+rm $GOPATH
+mkdir $GOPATH/src
+go get -d 'github.com/rsc/go-get-issue-12612'
+go get -u -d 'github.com/rsc/go-get-issue-12612'
+exists github.com/rsc/go-get-issue-12612/vendor/golang.org/x/crypto/.git
+
+# Bad vendor (bad/imp)
+rm $GOPATH
+mkdir $GOPATH/src
+! go get -t -u 'github.com/rsc/go-get-issue-18219/bad/imp'
+stderr 'must be imported as'
+! exists github.com/rsc/go-get-issue-11864/vendor
+
+# Bad vendor (bad/imp2)
+rm $GOPATH
+mkdir $GOPATH/src
+! go get -t -u 'github.com/rsc/go-get-issue-18219/bad/imp2'
+stderr 'must be imported as'
+! exists github.com/rsc/go-get-issue-11864/vendor
+
+# Bad vendor (bad/imp3)
+rm $GOPATH
+mkdir $GOPATH/src
+! go get -t -u 'github.com/rsc/go-get-issue-18219/bad/imp3'
+stderr 'must be imported as'
+! exists github.com/rsc/go-get-issue-11864/vendor
+
+# Bad vendor (bad/...)
+rm $GOPATH
+mkdir $GOPATH/src
+! go get -t -u 'github.com/rsc/go-get-issue-18219/bad/...'
+stderr 'must be imported as'
+! exists github.com/rsc/go-get-issue-11864/vendor
+
+-- v/m.go --
+package main
+
+import (
+       "fmt"
+       "vendor.org/p"
+)
+
+func main() {
+       fmt.Println(p.C)
+}
+-- v/m_test.go --
+package main
+import (
+       "fmt"
+       "testing"
+       "vendor.org/p"
+)
+
+func TestNothing(t *testing.T) {
+       fmt.Println(p.C)
+}
+-- v/vendor/vendor.org/p/p.go --
+package p
+const C = 1
diff --git a/libgo/go/cmd/go/testdata/script/gopath_vendor_dup_err.txt b/libgo/go/cmd/go/testdata/script/gopath_vendor_dup_err.txt
new file mode 100644 (file)
index 0000000..22e6048
--- /dev/null
@@ -0,0 +1,25 @@
+[!net] skip
+env GO111MODULE=off
+
+# Issue 17119: Test more duplicate load errors.
+! go build dupload
+! stderr 'duplicate load|internal error'
+stderr 'dupload/vendor/p must be imported as p'
+
+-- dupload/dupload.go --
+package main
+
+import (
+       _ "dupload/p2"
+       _ "p"
+)
+
+func main() {}
+-- dupload/p/p.go --
+package p
+-- dupload/p2/p2.go --
+package p2
+
+import _ "dupload/vendor/p"
+-- dupload/vendor/p/p.go --
+package p
diff --git a/libgo/go/cmd/go/testdata/script/goroot_executable.txt b/libgo/go/cmd/go/testdata/script/goroot_executable.txt
new file mode 100644 (file)
index 0000000..fdbcde0
--- /dev/null
@@ -0,0 +1,111 @@
+[gccgo] skip
+
+mkdir $WORK/new/bin
+
+# In this test, we are specifically checking the logic for deriving
+# the value of GOROOT from runtime.GOROOT.
+# GOROOT_FINAL changes the default behavior of runtime.GOROOT,
+# and will thus cause the test to fail if it is set when our
+# new cmd/go is built.
+env GOROOT_FINAL=
+
+go build -o $WORK/new/bin/go$GOEXE cmd/go &
+go build -o $WORK/bin/check$GOEXE check.go &
+wait
+
+env TESTGOROOT=$GOROOT
+env GOROOT=
+
+# Relocated Executable
+# cp $TESTGOROOT/bin/go$GOEXE $WORK/new/bin/go$GOEXE
+exec $WORK/bin/check$GOEXE $WORK/new/bin/go$GOEXE $TESTGOROOT
+
+# Relocated Tree:
+# If the binary is sitting in a bin dir next to ../pkg/tool, that counts as a GOROOT,
+# so it should find the new tree.
+mkdir $WORK/new/pkg/tool
+exec $WORK/bin/check$GOEXE $WORK/new/bin/go$GOEXE $WORK/new
+
+[!symlink] stop 'The rest of the test cases require symlinks'
+
+# Symlinked Executable:
+# With a symlink into go tree, we should still find the go tree.
+mkdir $WORK/other/bin
+symlink $WORK/other/bin/go$GOEXE -> $WORK/new/bin/go$GOEXE
+exec $WORK/bin/check$GOEXE $WORK/new/bin/go$GOEXE $WORK/new
+
+rm $WORK/new/pkg
+
+# Runtime GOROOT:
+# Binaries built in the new tree should report the
+# new tree when they call runtime.GOROOT.
+symlink $WORK/new/src -> $TESTGOROOT/src
+symlink $WORK/new/pkg -> $TESTGOROOT/pkg
+exec $WORK/new/bin/go$GOEXE run check_runtime_goroot.go $WORK/new
+
+-- check.go --
+package main
+
+import (
+       "fmt"
+       "os"
+       "os/exec"
+       "path/filepath"
+       "strings"
+)
+
+func main() {
+       exe := os.Args[1]
+       want := os.Args[2]
+       cmd := exec.Command(exe, "env", "GOROOT")
+       out, err := cmd.CombinedOutput()
+       if err != nil {
+               fmt.Fprintf(os.Stderr, "%s env GOROOT: %v, %s\n", exe, err, out)
+               os.Exit(1)
+       }
+       goroot, err := filepath.EvalSymlinks(strings.TrimSpace(string(out)))
+       if err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+       want, err = filepath.EvalSymlinks(want)
+       if err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+       if !strings.EqualFold(goroot, want) {
+               fmt.Fprintf(os.Stderr, "go env GOROOT:\nhave %s\nwant %s\n", goroot, want)
+               os.Exit(1)
+       }
+       fmt.Fprintf(os.Stderr, "go env GOROOT: %s\n", goroot)
+
+}
+-- check_runtime_goroot.go --
+package main
+
+import (
+       "fmt"
+       "os"
+       "path/filepath"
+       "runtime"
+       "strings"
+)
+
+func main() {
+       goroot, err := filepath.EvalSymlinks(runtime.GOROOT())
+       if err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+       want, err := filepath.EvalSymlinks(os.Args[1])
+       if err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+       if !strings.EqualFold(goroot, want) {
+               fmt.Fprintf(os.Stderr, "go env GOROOT:\nhave %s\nwant %s\n", goroot, want)
+               os.Exit(1)
+       }
+       fmt.Fprintf(os.Stderr, "go env GOROOT: %s\n", goroot)
+
+}
diff --git a/libgo/go/cmd/go/testdata/script/govcs.txt b/libgo/go/cmd/go/testdata/script/govcs.txt
new file mode 100644 (file)
index 0000000..4180d7d
--- /dev/null
@@ -0,0 +1,174 @@
+env GO111MODULE=on
+env proxy=$GOPROXY
+env GOPROXY=direct
+
+# GOVCS stops go get
+env GOVCS='*:none'
+! go get github.com/google/go-cmp
+stderr '^go get: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$'
+env GOPRIVATE='github.com/google'
+! go get github.com/google/go-cmp
+stderr '^go get: GOVCS disallows using git for private github.com/google/go-cmp; see ''go help vcs''$'
+
+# public pattern works
+env GOPRIVATE='github.com/google'
+env GOVCS='public:all,private:none'
+! go get github.com/google/go-cmp
+stderr '^go get: GOVCS disallows using git for private github.com/google/go-cmp; see ''go help vcs''$'
+
+# private pattern works
+env GOPRIVATE='hubgit.com/google'
+env GOVCS='private:all,public:none'
+! go get github.com/google/go-cmp
+stderr '^go get: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$'
+
+# other patterns work (for more patterns, see TestGOVCS)
+env GOPRIVATE=
+env GOVCS='github.com:svn|hg'
+! go get github.com/google/go-cmp
+stderr '^go get: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$'
+env GOVCS='github.com/google/go-cmp/inner:git,github.com:svn|hg'
+! go get github.com/google/go-cmp
+stderr '^go get: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$'
+
+# bad patterns are reported (for more bad patterns, see TestGOVCSErrors)
+env GOVCS='git'
+! go get github.com/google/go-cmp
+stderr '^go get github.com/google/go-cmp: malformed entry in GOVCS \(missing colon\): "git"$'
+
+env GOVCS=github.com:hg,github.com:git
+! go get github.com/google/go-cmp
+stderr '^go get github.com/google/go-cmp: unreachable pattern in GOVCS: "github.com:git" after "github.com:hg"$'
+
+# bad GOVCS patterns do not stop commands that do not need to check VCS
+go list
+env GOPROXY=$proxy
+go get -d rsc.io/quote # ok because used proxy
+env GOPROXY=direct
+
+# svn is disallowed by default
+env GOPRIVATE=
+env GOVCS=
+! go get rsc.io/nonexist.svn/hello
+stderr '^go get rsc.io/nonexist.svn/hello: GOVCS disallows using svn for public rsc.io/nonexist.svn; see ''go help vcs''$'
+
+# fossil is disallowed by default
+env GOPRIVATE=
+env GOVCS=
+! go get rsc.io/nonexist.fossil/hello
+stderr '^go get rsc.io/nonexist.fossil/hello: GOVCS disallows using fossil for public rsc.io/nonexist.fossil; see ''go help vcs''$'
+
+# bzr is disallowed by default
+env GOPRIVATE=
+env GOVCS=
+! go get rsc.io/nonexist.bzr/hello
+stderr '^go get rsc.io/nonexist.bzr/hello: GOVCS disallows using bzr for public rsc.io/nonexist.bzr; see ''go help vcs''$'
+
+# git is OK by default
+env GOVCS=
+env GONOSUMDB='*'
+[net] [exec:git] [!short] go get rsc.io/sampler
+
+# hg is OK by default
+env GOVCS=
+env GONOSUMDB='*'
+[net] [exec:hg] [!short] go get vcs-test.golang.org/go/custom-hg-hello
+
+# git can be disallowed
+env GOVCS=public:hg
+! go get rsc.io/nonexist.git/hello
+stderr '^go get rsc.io/nonexist.git/hello: GOVCS disallows using git for public rsc.io/nonexist.git; see ''go help vcs''$'
+
+# hg can be disallowed
+env GOVCS=public:git
+! go get rsc.io/nonexist.hg/hello
+stderr '^go get rsc.io/nonexist.hg/hello: GOVCS disallows using hg for public rsc.io/nonexist.hg; see ''go help vcs''$'
+
+# Repeat in GOPATH mode. Error texts slightly different.
+
+env GO111MODULE=off
+
+# GOVCS stops go get
+env GOVCS='*:none'
+! go get github.com/google/go-cmp
+stderr '^package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$'
+env GOPRIVATE='github.com/google'
+! go get github.com/google/go-cmp
+stderr '^package github.com/google/go-cmp: GOVCS disallows using git for private github.com/google/go-cmp; see ''go help vcs''$'
+
+# public pattern works
+env GOPRIVATE='github.com/google'
+env GOVCS='public:all,private:none'
+! go get github.com/google/go-cmp
+stderr '^package github.com/google/go-cmp: GOVCS disallows using git for private github.com/google/go-cmp; see ''go help vcs''$'
+
+# private pattern works
+env GOPRIVATE='hubgit.com/google'
+env GOVCS='private:all,public:none'
+! go get github.com/google/go-cmp
+stderr '^package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$'
+
+# other patterns work (for more patterns, see TestGOVCS)
+env GOPRIVATE=
+env GOVCS='github.com:svn|hg'
+! go get github.com/google/go-cmp
+stderr '^package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$'
+env GOVCS='github.com/google/go-cmp/inner:git,github.com:svn|hg'
+! go get github.com/google/go-cmp
+stderr '^package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$'
+
+# bad patterns are reported (for more bad patterns, see TestGOVCSErrors)
+env GOVCS='git'
+! go get github.com/google/go-cmp
+stderr '^package github.com/google/go-cmp: malformed entry in GOVCS \(missing colon\): "git"$'
+
+env GOVCS=github.com:hg,github.com:git
+! go get github.com/google/go-cmp
+stderr '^package github.com/google/go-cmp: unreachable pattern in GOVCS: "github.com:git" after "github.com:hg"$'
+
+# bad GOVCS patterns do not stop commands that do not need to check VCS
+go list
+
+# svn is disallowed by default
+env GOPRIVATE=
+env GOVCS=
+! go get rsc.io/nonexist.svn/hello
+stderr '^package rsc.io/nonexist.svn/hello: GOVCS disallows using svn for public rsc.io/nonexist.svn; see ''go help vcs''$'
+
+# fossil is disallowed by default
+env GOPRIVATE=
+env GOVCS=
+! go get rsc.io/nonexist.fossil/hello
+stderr '^package rsc.io/nonexist.fossil/hello: GOVCS disallows using fossil for public rsc.io/nonexist.fossil; see ''go help vcs''$'
+
+# bzr is disallowed by default
+env GOPRIVATE=
+env GOVCS=
+! go get rsc.io/nonexist.bzr/hello
+stderr '^package rsc.io/nonexist.bzr/hello: GOVCS disallows using bzr for public rsc.io/nonexist.bzr; see ''go help vcs''$'
+
+# git is OK by default
+env GOVCS=
+env GONOSUMDB='*'
+[net] [exec:git] [!short] go get rsc.io/sampler
+
+# hg is OK by default
+env GOVCS=
+env GONOSUMDB='*'
+[net] [exec:hg] [!short] go get vcs-test.golang.org/go/custom-hg-hello
+
+# git can be disallowed
+env GOVCS=public:hg
+! go get rsc.io/nonexist.git/hello
+stderr '^package rsc.io/nonexist.git/hello: GOVCS disallows using git for public rsc.io/nonexist.git; see ''go help vcs''$'
+
+# hg can be disallowed
+env GOVCS=public:git
+! go get rsc.io/nonexist.hg/hello
+stderr '^package rsc.io/nonexist.hg/hello: GOVCS disallows using hg for public rsc.io/nonexist.hg; see ''go help vcs''$'
+
+-- go.mod --
+module m
+
+-- p.go --
+package p
diff --git a/libgo/go/cmd/go/testdata/script/import_cycle.txt b/libgo/go/cmd/go/testdata/script/import_cycle.txt
new file mode 100644 (file)
index 0000000..901f43c
--- /dev/null
@@ -0,0 +1,12 @@
+env GO111MODULE=off
+
+! go build selfimport
+stderr -count=1 'import cycle not allowed'
+
+# 'go list' shouldn't hang forever.
+go list -e -json selfimport
+
+-- $GOPATH/src/selfimport/selfimport.go --
+package selfimport
+
+import "selfimport"
diff --git a/libgo/go/cmd/go/testdata/script/import_ignore.txt b/libgo/go/cmd/go/testdata/script/import_ignore.txt
new file mode 100644 (file)
index 0000000..83a39a0
--- /dev/null
@@ -0,0 +1,11 @@
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod go.mod.orig
+
+-- go.mod --
+module m.test
+
+go 1.16
+-- .ignore.go --
+package p
+import _ "golang.org/x/mod/modfile"
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/install_cgo_excluded.txt b/libgo/go/cmd/go/testdata/script/install_cgo_excluded.txt
new file mode 100644 (file)
index 0000000..5a2b460
--- /dev/null
@@ -0,0 +1,15 @@
+env CGO_ENABLED=0
+
+! go install cgotest
+stderr 'build constraints exclude all Go files'
+
+-- go.mod --
+module cgotest
+
+go 1.16
+-- m.go --
+package cgotest
+
+import "C"
+
+var _ C.int
diff --git a/libgo/go/cmd/go/testdata/script/install_msan_and_race_require_cgo.txt b/libgo/go/cmd/go/testdata/script/install_msan_and_race_require_cgo.txt
new file mode 100644 (file)
index 0000000..7985cd2
--- /dev/null
@@ -0,0 +1,18 @@
+# Tests Issue #21895
+
+[!msan] [!race] skip 'skipping because both msan and the race detector are not supported'
+
+env CGO_ENABLED=0
+
+[race] ! go install -race triv.go
+[race] stderr '-race requires cgo'
+[race] ! stderr '-msan'
+
+[msan] ! go install -msan triv.go
+[msan] stderr '-msan requires cgo'
+[msan] ! stderr '-race'
+
+-- triv.go --
+package main
+
+func main() {}
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/install_relative_gobin_fail.txt b/libgo/go/cmd/go/testdata/script/install_relative_gobin_fail.txt
new file mode 100644 (file)
index 0000000..aa14524
--- /dev/null
@@ -0,0 +1,12 @@
+env GOBIN=.
+! go install
+stderr 'cannot install, GOBIN must be an absolute path'
+
+-- go.mod --
+module triv
+
+go 1.16
+-- triv.go --
+package main
+
+func main() {}
diff --git a/libgo/go/cmd/go/testdata/script/install_shadow_gopath.txt b/libgo/go/cmd/go/testdata/script/install_shadow_gopath.txt
new file mode 100644 (file)
index 0000000..2039d9e
--- /dev/null
@@ -0,0 +1,20 @@
+# Tests Issue #3562
+# go get foo.io (not foo.io/subdir) was not working consistently.
+
+[!net] skip
+
+env GO111MODULE=off
+env GOPATH=$WORK/gopath1${:}$WORK/gopath2
+
+mkdir $WORK/gopath1/src/test
+mkdir $WORK/gopath2/src/test
+cp main.go $WORK/gopath2/src/test/main.go
+cd $WORK/gopath2/src/test
+
+! go install
+stderr 'no install location for.*gopath2.src.test: hidden by .*gopath1.src.test'
+
+-- main.go --
+package main
+
+func main() {}
diff --git a/libgo/go/cmd/go/testdata/script/issue36000.txt b/libgo/go/cmd/go/testdata/script/issue36000.txt
new file mode 100644 (file)
index 0000000..4173275
--- /dev/null
@@ -0,0 +1,6 @@
+# Tests golang.org/issue/36000
+
+[!cgo] skip
+
+# go env with CGO flags should not make NUL file
+go env CGO_CFLAGS
diff --git a/libgo/go/cmd/go/testdata/script/ldflag.txt b/libgo/go/cmd/go/testdata/script/ldflag.txt
new file mode 100644 (file)
index 0000000..258af8d
--- /dev/null
@@ -0,0 +1,44 @@
+# Issue #42565
+
+[!cgo] skip
+
+# We can't build package bad, which uses #cgo LDFLAGS.
+cd bad
+! go build
+stderr no-such-warning
+
+# We can build package ok with the same flags in CGO_LDFLAGS.
+env CGO_LDFLAGS=-Wno-such-warning -Wno-unknown-warning-option
+cd ../ok
+go build
+
+# Build a main program that actually uses LDFLAGS.
+cd ..
+[!gccgo] go build -ldflags=-v
+
+# Because we passed -v the Go linker should print the external linker
+# command which should include the flag we passed in CGO_LDFLAGS.
+[!gccgo] stderr no-such-warning
+
+-- go.mod --
+module ldflag
+
+-- bad/bad.go --
+package bad
+
+// #cgo LDFLAGS: -Wno-such-warning -Wno-unknown-warning
+import "C"
+
+func F() {}
+-- ok/ok.go --
+package ok
+
+import "C"
+
+func F() {}
+-- main.go --
+package main
+
+import _ "ldflag/ok"
+
+func main() {}
diff --git a/libgo/go/cmd/go/testdata/script/link_matching_actionid.txt b/libgo/go/cmd/go/testdata/script/link_matching_actionid.txt
new file mode 100644 (file)
index 0000000..b8d423d
--- /dev/null
@@ -0,0 +1,38 @@
+# Checks that an identical binary is built with -trimpath from the same
+# source files, with GOROOT in two different locations.
+# Verifies golang.org/issue/38989
+
+[short] skip
+[!symlink] skip
+
+# Symlink the compiler to a local path
+env GOROOT=$WORK/goroot1
+symlink $GOROOT -> $TESTGO_GOROOT
+
+# Set up fresh GOCACHE
+env GOCACHE=$WORK/gocache1
+mkdir $GOCACHE
+
+# Build a simple binary
+go build -o binary1 -trimpath -x main.go
+
+# Now repeat the same process with the compiler at a different local path
+env GOROOT=$WORK/goroot2
+symlink $GOROOT -> $TESTGO_GOROOT
+
+env GOCACHE=$WORK/gocache2
+mkdir $GOCACHE
+
+go build -o binary2 -trimpath -x main.go
+
+# Check that the binaries match exactly
+go tool buildid binary1
+cp stdout buildid1
+go tool buildid binary2
+cp stdout buildid2
+cmp buildid1 buildid2
+
+
+-- main.go --
+package main
+func main() {}
diff --git a/libgo/go/cmd/go/testdata/script/list_case_collision.txt b/libgo/go/cmd/go/testdata/script/list_case_collision.txt
new file mode 100644 (file)
index 0000000..181a202
--- /dev/null
@@ -0,0 +1,41 @@
+# Tests golang.org/issue/4773
+
+go list -json example/a
+stdout 'case-insensitive import collision'
+
+! go build example/a
+stderr 'case-insensitive import collision'
+
+# List files explicitly on command line, to encounter case-checking
+# logic even on case-insensitive filesystems.
+cp b/file.go b/FILE.go  # no-op on case-insensitive filesystems
+! go list b/file.go b/FILE.go
+stderr 'case-insensitive file name collision'
+
+mkdir a/Pkg  # no-op on case-insensitive filesystems
+cp a/pkg/pkg.go a/Pkg/pkg.go  # no-op on case-insensitive filesystems
+! go list example/a/pkg example/a/Pkg
+
+# Test that the path reported with an indirect import is correct.
+cp b/file.go b/FILE.go
+[case-sensitive] ! go build example/c
+[case-sensitive] stderr '^package example/c\n\timports example/b: case-insensitive file name collision: "FILE.go" and "file.go"$'
+
+-- go.mod --
+module example
+
+go 1.16
+-- a/a.go --
+package p
+import (
+       _ "example/a/pkg"
+       _ "example/a/Pkg"
+)
+-- a/pkg/pkg.go --
+package pkg
+-- b/file.go --
+package b
+-- c/c.go --
+package c
+
+import _ "example/b"
diff --git a/libgo/go/cmd/go/testdata/script/list_cgo_compiled_importmap.txt b/libgo/go/cmd/go/testdata/script/list_cgo_compiled_importmap.txt
new file mode 100644 (file)
index 0000000..3d68ef3
--- /dev/null
@@ -0,0 +1,38 @@
+# Regression test for https://golang.org/issue/46462.
+#
+# The "runtime/cgo" import found in synthesized .go files (reported in
+# the CompiledGoFiles field) should have a corresponding entry in the
+# ImportMap field when a runtime/cgo variant (such as a test variant)
+# will be used.
+
+[short] skip  # -compiled can be slow (because it compiles things)
+[!cgo] skip
+
+env CGO_ENABLED=1
+env GOFLAGS=-tags=netcgo  # Force net to use cgo even on Windows.
+
+
+# "runtime/cgo [runtime.test]" appears in the the test dependencies of "runtime",
+# because "runtime/cgo" itself depends on "runtime"
+
+go list -deps -test -compiled -f '{{if eq .ImportPath "net [runtime.test]"}}{{printf "%q" .Imports}}{{end}}' runtime
+
+       # Control case: the explicitly-imported package "sync" is a test variant,
+       # because "sync" depends on "runtime".
+stdout '"sync \[runtime\.test\]"'
+! stdout '"sync"'
+
+       # Experiment: the implicitly-imported package "runtime/cgo" is also a test variant,
+       # because "runtime/cgo" also depends on "runtime".
+stdout '"runtime/cgo \[runtime\.test\]"'
+! stdout '"runtime/cgo"'
+
+
+# Because the import of "runtime/cgo" in the cgo-generated file actually refers
+# to "runtime/cgo [runtime.test]", the latter should be listed in the ImportMap.
+# BUG(#46462): Today, it is not.
+
+go list -deps -test -compiled -f '{{if eq .ImportPath "net [runtime.test]"}}{{printf "%q" .ImportMap}}{{end}}' runtime
+
+stdout '"sync":"sync \[runtime\.test\]"'                # control
+stdout '"runtime/cgo":"runtime/cgo \[runtime\.test\]"'  # experiment
diff --git a/libgo/go/cmd/go/testdata/script/list_dedup_packages.txt b/libgo/go/cmd/go/testdata/script/list_dedup_packages.txt
new file mode 100644 (file)
index 0000000..30c68dd
--- /dev/null
@@ -0,0 +1,31 @@
+# Setup
+env GO111MODULE=off
+mkdir $WORK/tmp/testdata/src/xtestonly
+cp f.go $WORK/tmp/testdata/src/xtestonly/f.go
+cp f_test.go $WORK/tmp/testdata/src/xtestonly/f_test.go
+env GOPATH=$WORK/tmp/testdata
+cd $WORK
+
+# Check output of go list to ensure no duplicates
+go list xtestonly ./tmp/testdata/src/xtestonly/...
+cmp stdout $WORK/gopath/src/wantstdout
+
+-- wantstdout --
+xtestonly
+-- f.go --
+package xtestonly
+
+func F() int { return 42 }
+-- f_test.go --
+package xtestonly_test
+
+import (
+       "testing"
+       "xtestonly"
+)
+
+func TestF(t *testing.T) {
+       if x := xtestonly.F(); x != 42 {
+               t.Errorf("f.F() = %d, want 42", x)
+       }
+}
diff --git a/libgo/go/cmd/go/testdata/script/list_err_cycle.txt b/libgo/go/cmd/go/testdata/script/list_err_cycle.txt
new file mode 100644 (file)
index 0000000..44b82a6
--- /dev/null
@@ -0,0 +1,15 @@
+# Check that we don't get infinite recursion when loading a package with
+# an import cycle and another error. Verifies #25830.
+! go list
+stderr 'found packages a \(a.go\) and b \(b.go\)'
+
+-- go.mod --
+module errcycle
+
+go 1.16
+-- a.go --
+package a
+
+import _ "errcycle"
+-- b.go --
+package b
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/list_err_stack.txt b/libgo/go/cmd/go/testdata/script/list_err_stack.txt
new file mode 100644 (file)
index 0000000..a7be9fd
--- /dev/null
@@ -0,0 +1,27 @@
+
+# golang.org/issue/40544: regression in error stacks for parse errors
+
+env GO111MODULE=off
+cd sandbox/foo
+go list -e -json .
+stdout '"sandbox/foo"'
+stdout '"sandbox/bar"'
+stdout '"Pos": "..(/|\\\\)bar(/|\\\\)bar.go:1:1"'
+stdout '"Err": "expected ''package'', found ackage"'
+
+env GO111MODULE=on
+go list -e -json .
+stdout '"sandbox/foo"'
+stdout '"sandbox/bar"'
+stdout '"Pos": "..(/|\\\\)bar(/|\\\\)bar.go:1:1"'
+stdout '"Err": "expected ''package'', found ackage"'
+
+-- sandbox/go.mod --
+module sandbox
+
+-- sandbox/foo/foo.go --
+package pkg
+
+import "sandbox/bar"
+-- sandbox/bar/bar.go --
+ackage bar
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/list_find_nodeps.txt b/libgo/go/cmd/go/testdata/script/list_find_nodeps.txt
new file mode 100644 (file)
index 0000000..e08ce78
--- /dev/null
@@ -0,0 +1,49 @@
+# Issue #46092
+# go list -find should always return a package with an empty Deps list
+
+# The linker loads implicit dependencies
+go list -find -f {{.Deps}} ./cmd
+stdout '\[\]'
+
+# Cgo translation may add imports of "unsafe", "runtime/cgo" and "syscall"
+go list -find -f {{.Deps}} ./cgo
+stdout '\[\]'
+
+# SWIG adds imports of some standard packages
+go list -find -f {{.Deps}} ./swig
+stdout '\[\]'
+
+-- go.mod --
+module listfind
+
+-- cmd/main.go --
+package main
+
+func main() {}
+
+-- cgo/pkg.go --
+package cgopkg
+
+/*
+#include <limits.h>
+*/
+import "C"
+
+func F() {
+    println(C.INT_MAX)
+}
+
+-- cgo/pkg_notcgo.go --
+//go:build !cgo
+// +build !cgo
+
+package cgopkg
+
+func F() {
+    println(0)
+}
+
+-- swig/pkg.go --
+package swigpkg
+
+-- swig/a.swigcxx --
diff --git a/libgo/go/cmd/go/testdata/script/list_gofile_in_goroot.txt b/libgo/go/cmd/go/testdata/script/list_gofile_in_goroot.txt
new file mode 100644 (file)
index 0000000..d3d7cc8
--- /dev/null
@@ -0,0 +1,78 @@
+# Return an error if the user tries to list a go source file directly in $GOROOT/src.
+# Tests golang.org/issue/36587
+
+[gccgo] skip
+
+env GOROOT=$WORK/goroot
+env GOPATH=$WORK/gopath
+
+go env GOROOT
+stdout $WORK[/\\]goroot
+
+# switch to GOROOT/src
+cd $GOROOT/src
+
+# In module mode, 'go list ./...' should not treat .go files in GOROOT/src as an
+# importable package, since that directory has no valid import path.
+env GO111MODULE=on
+go list ...
+stdout -count=1 '^.+$'
+stdout '^fmt$'
+! stdout foo
+
+go list ./...
+stdout -count=1 '^.+$'
+stdout '^fmt$'
+! stdout foo
+
+go list std
+stdout -count=1 '^.+$'
+stdout '^fmt$'
+
+! go list .
+stderr '^GOROOT/src is not an importable package$'
+
+# In GOPATH mode, 'go list ./...' should synthesize a legacy GOPATH-mode path —
+# not a standard-library or empty path — for the errant package.
+env GO111MODULE=off
+go list ./...
+stdout -count=2 '^.+$' # Both 'fmt' and GOROOT/src should be listed.
+stdout '^fmt$'
+[!windows] stdout ^_$WORK/goroot/src$
+[windows] stdout goroot/src$ # On windows the ":" in the volume name is mangled
+
+go list ...
+! stdout goroot/src
+
+go list std
+! stdout goroot/src
+
+go list .
+[!windows] stdout ^_$WORK/goroot/src$
+[windows] stdout goroot/src$
+
+# switch to GOPATH/src
+cd $GOPATH/src
+
+# GO111MODULE=off,GOPATH
+env GO111MODULE=off
+go list ./...
+[!windows] stdout ^_$WORK/gopath/src$
+[windows] stdout gopath/src$
+
+go list all
+! stdout gopath/src
+
+-- $WORK/goroot/src/go.mod --
+module std
+
+go 1.14
+-- $WORK/goroot/src/foo.go --
+package foo
+-- $WORK/goroot/src/fmt/fmt.go --
+package fmt
+-- $WORK/goroot/src/cmd/README --
+This directory must exist in order for the 'cmd' pattern to have something to
+match against.
+-- $GOPATH/src/foo.go --
+package foo
diff --git a/libgo/go/cmd/go/testdata/script/list_gomod_in_gopath.txt b/libgo/go/cmd/go/testdata/script/list_gomod_in_gopath.txt
new file mode 100644 (file)
index 0000000..064f33a
--- /dev/null
@@ -0,0 +1,23 @@
+# Issue 46119
+
+# When a module is inside a GOPATH workspace, Package.Root should be set to
+# Module.Dir instead of $GOPATH/src.
+
+env GOPATH=$WORK/tmp
+cd $WORK/tmp/src/test
+
+go list -f {{.Root}}
+stdout ^$PWD$
+
+# Were we really inside a GOPATH workspace?
+env GO111MODULE=off
+go list -f {{.Root}}
+stdout ^$WORK/tmp$
+
+-- $WORK/tmp/src/test/go.mod --
+module test
+
+-- $WORK/tmp/src/test/main.go --
+package main
+
+func main() {}
diff --git a/libgo/go/cmd/go/testdata/script/list_json_with_f.txt b/libgo/go/cmd/go/testdata/script/list_json_with_f.txt
new file mode 100644 (file)
index 0000000..2011a6e
--- /dev/null
@@ -0,0 +1,20 @@
+[short] skip
+
+# list -json should generate output on stdout
+go list -json ./...
+stdout .
+# list -f should generate output on stdout
+go list -f '{{.}}' ./...
+stdout .
+
+# test passing first -json then -f
+! go list -json -f '{{.}}' ./...
+stderr '^go list -f cannot be used with -json$'
+
+# test passing first -f then -json
+! go list -f '{{.}}' -json ./...
+stderr '^go list -f cannot be used with -json$'
+-- go.mod --
+module m
+-- list_test.go --
+package list_test
diff --git a/libgo/go/cmd/go/testdata/script/list_load_err.txt b/libgo/go/cmd/go/testdata/script/list_load_err.txt
new file mode 100644 (file)
index 0000000..0cfa7fb
--- /dev/null
@@ -0,0 +1,95 @@
+# go list -e -deps should list imports from any file it can read, even if
+# other files in the same package cause go/build.Import to return an error.
+# Verfifies golang.org/issue/38568
+
+go list -e -deps ./scan
+stdout m/want
+
+go list -e -deps ./multi
+stdout m/want
+
+go list -e -deps ./constraint
+stdout m/want
+
+[cgo] go list -e -test -deps ./cgotest
+[cgo] stdout m/want
+
+[cgo] go list -e -deps ./cgoflag
+[cgo] stdout m/want
+
+
+# go list -e should include files with errors in GoFiles, TestGoFiles, and
+# other lists, assuming they match constraints.
+# Verifies golang.org/issue/39986
+go list -e -f '{{range .GoFiles}}{{.}},{{end}}' ./scan
+stdout '^good.go,scan.go,$'
+
+go list -e -f '{{range .GoFiles}}{{.}},{{end}}' ./multi
+stdout '^a.go,b.go,$'
+
+go list -e -f '{{range .GoFiles}}{{.}},{{end}}' ./constraint
+stdout '^good.go,$'
+go list -e -f '{{range .IgnoredGoFiles}}{{.}},{{end}}' ./constraint
+stdout '^constraint.go,$'
+
+[cgo] go list -e -f '{{range .XTestGoFiles}}{{.}},{{end}}' ./cgotest
+[cgo] stdout '^cgo_test.go,$'
+
+[cgo] go list -e -f '{{range .GoFiles}}{{.}},{{end}}' ./cgoflag
+[cgo] stdout '^cgoflag.go,$'
+
+-- go.mod --
+module m
+
+go 1.14
+
+-- want/want.go --
+package want
+
+-- scan/scan.go --
+// scan error
+ʕ◔ϖ◔ʔ
+
+-- scan/good.go --
+package scan
+
+import _ "m/want"
+
+-- multi/a.go --
+package a
+
+-- multi/b.go --
+package b
+
+import _ "m/want"
+
+-- constraint/constraint.go --
+// +build !!nope
+
+package constraint
+
+-- constraint/good.go --
+package constraint
+
+import _ "m/want"
+
+-- cgotest/cgo_test.go --
+package cgo_test
+
+// cgo is not allowed in tests.
+// See golang.org/issue/18647
+
+import "C"
+import (
+       "testing"
+       _ "m/want"
+)
+
+func Test(t *testing.T) {}
+
+-- cgoflag/cgoflag.go --
+package cgoflag
+
+// #cgo ʕ◔ϖ◔ʔ:
+
+import _ "m/want"
diff --git a/libgo/go/cmd/go/testdata/script/list_module_when_error.txt b/libgo/go/cmd/go/testdata/script/list_module_when_error.txt
new file mode 100644 (file)
index 0000000..844164c
--- /dev/null
@@ -0,0 +1,19 @@
+# The Module field should be populated even if there is an error loading the package.
+
+env GO111MODULE=on
+
+go list -e -f {{.Module}}
+stdout '^mod.com$'
+
+-- go.mod --
+module mod.com
+
+go 1.16
+
+-- blah.go --
+package blah
+
+import _ "embed"
+
+//go:embed README.md
+var readme string
diff --git a/libgo/go/cmd/go/testdata/script/list_overlay.txt b/libgo/go/cmd/go/testdata/script/list_overlay.txt
new file mode 100644 (file)
index 0000000..1153975
--- /dev/null
@@ -0,0 +1,63 @@
+# Test listing with overlays
+
+# Overlay in an existing directory
+go list -overlay overlay.json  -f '{{.GoFiles}}' .
+stdout '^\[f.go\]$'
+
+# Overlays in a non-existing directory
+go list -overlay overlay.json -f '{{.GoFiles}}' ./dir
+stdout '^\[g.go\]$'
+
+# Overlays in an existing directory with already existing files
+go list -overlay overlay.json -f '{{.GoFiles}}' ./dir2
+stdout '^\[h.go i.go\]$'
+
+# Overlay that removes a file from a directory
+! go list ./dir3 # contains a file without a package statement
+go list -overlay overlay.json -f '{{.GoFiles}}' ./dir3 # overlay removes that file
+
+# Walking through an overlay
+go list -overlay overlay.json ./...
+cmp stdout want-list.txt
+
+# TODO(#39958): assembly files, C files, files that require cgo preprocessing
+
+-- want-list.txt --
+m
+m/dir
+m/dir2
+m/dir3
+-- go.mod --
+// TODO(#39958): Support and test overlays including go.mod itself (especially if mod=readonly)
+module m
+
+go 1.16
+
+-- dir2/h.go --
+package dir2
+
+-- dir3/good.go --
+package dir3
+-- dir3/bad.go --
+// no package statement
+-- overlay.json --
+{
+    "Replace": {
+        "f.go": "overlay/f_go",
+        "dir/g.go": "overlay/dir_g_go",
+        "dir2/i.go": "overlay/dir2_i_go",
+        "dir3/bad.go": ""
+    }
+}
+-- overlay/f_go --
+package m
+
+func f() {
+}
+-- overlay/dir_g_go --
+package m
+
+func g() {
+}
+-- overlay/dir2_i_go --
+package dir2
diff --git a/libgo/go/cmd/go/testdata/script/list_permissions.txt b/libgo/go/cmd/go/testdata/script/list_permissions.txt
new file mode 100644 (file)
index 0000000..f65896c
--- /dev/null
@@ -0,0 +1,84 @@
+env GO111MODULE=on
+
+# Establish baseline behavior, before mucking with file permissions.
+
+go list ./noread/...
+stdout '^example.com/noread$'
+
+go list example.com/noread/...
+stdout '^example.com/noread$'
+
+go list ./empty/...
+stderr 'matched no packages'
+
+[root] stop # Root typically ignores file permissions.
+
+# Make the directory ./noread unreadable, and verify that 'go list' reports an
+# explicit error for a pattern that should match it (rather than treating it as
+# equivalent to an empty directory).
+
+[windows] skip # Does not have Unix-style directory permissions.
+[plan9] skip   # Might not have Unix-style directory permissions.
+
+chmod 000 noread
+
+# Check explicit paths.
+
+! go list ./noread
+! stdout '^example.com/noread$'
+! stderr 'matched no packages'
+
+! go list example.com/noread
+! stdout '^example.com/noread$'
+! stderr 'matched no packages'
+
+# Check filesystem-relative patterns.
+
+! go list ./...
+! stdout '^example.com/noread$'
+! stderr 'matched no packages'
+stderr '^pattern ./...: '
+
+! go list ./noread/...
+! stdout '^example.com/noread$'
+! stderr 'matched no packages'
+stderr '^pattern ./noread/...: '
+
+
+# Check module-prefix patterns.
+
+! go list example.com/...
+! stdout '^example.com/noread$'
+! stderr 'matched no packages'
+stderr '^pattern example.com/...: '
+
+! go list example.com/noread/...
+! stdout '^example.com/noread$'
+! stderr 'matched no packages'
+stderr '^pattern example.com/noread/...: '
+
+
+[short] stop
+
+# Check global patterns, which should still
+# fail due to errors in the local module.
+
+! go list all
+! stdout '^example.com/noread$'
+! stderr 'matched no packages'
+stderr '^pattern all: '
+
+! go list ...
+! stdout '^example.com/noread$'
+! stderr 'matched no packages'
+stderr '^pattern ...: '
+
+
+-- go.mod --
+module example.com
+go 1.15
+-- noread/noread.go --
+// Package noread exists, but will be made unreadable.
+package noread
+-- empty/README.txt --
+This directory intentionally left empty.
diff --git a/libgo/go/cmd/go/testdata/script/list_shadow.txt b/libgo/go/cmd/go/testdata/script/list_shadow.txt
new file mode 100644 (file)
index 0000000..00e3f6f
--- /dev/null
@@ -0,0 +1,27 @@
+[gccgo] skip
+
+env GO111MODULE=off
+env GOPATH=$WORK/gopath/src/shadow/root1${:}$WORK/gopath/src/shadow/root2
+
+# The math in root1 is not "math" because the standard math is.
+go list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./shadow/root1/src/math
+stdout '^\(.*(\\|/)src(\\|/)shadow(\\|/)root1(\\|/)src(\\|/)math\) \('$GOROOT'(\\|/)?src(\\|/)math\)$'
+
+# The foo in root1 is "foo".
+go list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./shadow/root1/src/foo
+stdout '^\(foo\) \(\)$'
+
+# The foo in root2 is not "foo" because the foo in root1 got there first.
+go list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./shadow/root2/src/foo
+stdout '^\(.*gopath(\\|/)src(\\|/)shadow(\\|/)root2(\\|/)src(\\|/)foo\) \('$WORK'(\\|/)?gopath(\\|/)src(\\|/)shadow(\\|/)root1(\\|/)src(\\|/)foo\)$'
+
+# The error for go install should mention the conflicting directory.
+! go install -n ./shadow/root2/src/foo
+stderr 'go install: no install location for '$WORK'(\\|/)?gopath(\\|/)src(\\|/)shadow(\\|/)root2(\\|/)src(\\|/)foo: hidden by '$WORK'(\\|/)?gopath(\\|/)src(\\|/)shadow(\\|/)root1(\\|/)src(\\|/)foo'
+
+-- shadow/root1/src/foo/foo.go --
+package foo
+-- shadow/root1/src/math/math.go --
+package math
+-- shadow/root2/src/foo/foo.go --
+package foo
diff --git a/libgo/go/cmd/go/testdata/script/list_std_vendor.txt b/libgo/go/cmd/go/testdata/script/list_std_vendor.txt
new file mode 100644 (file)
index 0000000..821ec14
--- /dev/null
@@ -0,0 +1,34 @@
+# https://golang.org/issue/44725: packages in std should have the same
+# dependencies regardless of whether they are listed from within or outside
+# GOROOT/src.
+
+[gccgo] skip
+
+# Control case: net, viewed from outside the 'std' module,
+# should depend on vendor/golang.org/… instead of golang.org/….
+
+go list -deps net
+stdout '^vendor/golang.org/x/net'
+! stdout '^golang.org/x/net'
+cp stdout $WORK/net-deps.txt
+
+
+# It should still report the same package dependencies when viewed from
+# within GOROOT/src.
+
+cd $GOROOT/src
+
+go list -deps net
+stdout '^vendor/golang.org/x/net'
+! stdout '^golang.org/x/net'
+cmp stdout $WORK/net-deps.txt
+
+
+# However, 'go mod' and 'go get' subcommands should report the original module
+# dependencies, not the vendored packages.
+
+[!net] stop
+
+env GOPROXY=
+go mod why -m golang.org/x/net
+stdout '^# golang.org/x/net\nnet\ngolang.org/x/net'
diff --git a/libgo/go/cmd/go/testdata/script/list_swigcxx.txt b/libgo/go/cmd/go/testdata/script/list_swigcxx.txt
new file mode 100644 (file)
index 0000000..c6acd9e
--- /dev/null
@@ -0,0 +1,27 @@
+# go list should not report SWIG-generated C++ files in CompiledGoFiles.
+
+[!exec:swig] skip
+[!exec:g++] skip
+
+# CompiledGoFiles should contain 4 files:
+#  a.go
+#  a.swigcxx.go
+#  _cgo_gotypes.go
+#  a.cgo1.go
+
+go list -f '{{.CompiledGoFiles}}' -compiled=true example/swig
+
+# These names we see here, other than a.go, will be from the build cache,
+# so we just count them.
+stdout a\.go
+stdout -count=3 $GOCACHE
+
+-- go.mod --
+module example
+
+go 1.16
+
+-- swig/a.go --
+package swig
+
+-- swig/a.swigcxx --
diff --git a/libgo/go/cmd/go/testdata/script/list_symlink.txt b/libgo/go/cmd/go/testdata/script/list_symlink.txt
new file mode 100644 (file)
index 0000000..f74ca86
--- /dev/null
@@ -0,0 +1,12 @@
+[!symlink] skip
+env GO111MODULE=off
+
+mkdir $WORK/tmp/src
+symlink $WORK/tmp/src/dir1 -> $WORK/tmp
+cp p.go $WORK/tmp/src/dir1/p.go
+env GOPATH=$WORK/tmp
+go list -f '{{.Root}}' dir1
+stdout '^'$WORK/tmp'$'
+
+-- p.go --
+package p
diff --git a/libgo/go/cmd/go/testdata/script/list_symlink_internal.txt b/libgo/go/cmd/go/testdata/script/list_symlink_internal.txt
new file mode 100644 (file)
index 0000000..f756a56
--- /dev/null
@@ -0,0 +1,27 @@
+[!symlink] skip
+env GO111MODULE=off
+
+mkdir $WORK/tmp/gopath/src/dir1/internal/v
+cp p.go $WORK/tmp/gopath/src/dir1/p.go
+cp v.go $WORK/tmp/gopath/src/dir1/internal/v/v.go
+symlink $WORK/tmp/symdir1 -> $WORK/tmp/gopath/src/dir1
+env GOPATH=$WORK/tmp/gopath
+cd $WORK/tmp/symdir1
+go list -f '{{.Root}}' .
+stdout '^'$WORK/tmp/gopath'$'
+
+# All of these should succeed, not die in internal-handling code.
+go run p.go &
+go build &
+go install &
+
+wait
+
+-- p.go --
+package main
+
+import _ `dir1/internal/v`
+
+func main() {}
+-- v.go --
+package v
diff --git a/libgo/go/cmd/go/testdata/script/list_symlink_issue35941.txt b/libgo/go/cmd/go/testdata/script/list_symlink_issue35941.txt
new file mode 100644 (file)
index 0000000..eb12bde
--- /dev/null
@@ -0,0 +1,18 @@
+[!symlink] skip
+env GO111MODULE=off
+
+# Issue 35941: suppress symlink warnings when running 'go list all'.
+symlink goproj/css -> $GOPATH/src/css
+
+go list all
+! stderr 'warning: ignoring symlink'
+
+# Show symlink warnings when patterns contain '...'.
+go list goproj/...
+stderr 'warning: ignoring symlink'
+
+-- goproj/a.go --
+package a
+
+-- css/index.css --
+body {}
diff --git a/libgo/go/cmd/go/testdata/script/list_symlink_vendor_issue14054.txt b/libgo/go/cmd/go/testdata/script/list_symlink_vendor_issue14054.txt
new file mode 100644 (file)
index 0000000..8e63a5a
--- /dev/null
@@ -0,0 +1,28 @@
+[!symlink] skip
+env GO111MODULE=off
+
+mkdir $WORK/tmp/gopath/src/dir1/vendor/v
+cp p.go $WORK/tmp/gopath/src/dir1/p.go
+cp v.go $WORK/tmp/gopath/src/dir1/vendor/v/v.go
+symlink $WORK/tmp/symdir1 -> $WORK/tmp/gopath/src/dir1
+env GOPATH=$WORK/tmp/gopath
+cd $WORK/tmp/symdir1
+
+go list -f '{{.Root}}' .
+stdout '^'$WORK/tmp/gopath'$'
+
+# All of these should succeed, not die in vendor-handling code.
+go run p.go &
+go build &
+go install &
+
+wait
+
+-- p.go --
+package main
+
+import _ `v`
+
+func main () {}
+-- v.go --
+package v
diff --git a/libgo/go/cmd/go/testdata/script/list_symlink_vendor_issue15201.txt b/libgo/go/cmd/go/testdata/script/list_symlink_vendor_issue15201.txt
new file mode 100644 (file)
index 0000000..19f2138
--- /dev/null
@@ -0,0 +1,21 @@
+[!symlink] skip
+env GO111MODULE=off
+
+mkdir $WORK/tmp/gopath/src/x/y/_vendor/src/x
+symlink $WORK/tmp/gopath/src/x/y/_vendor/src/x/y -> ../../..
+mkdir $WORK/tmp/gopath/src/x/y/_vendor/src/x/y/w
+cp w.go $WORK/tmp/gopath/src/x/y/w/w.go
+symlink $WORK/tmp/gopath/src/x/y/w/vendor -> ../_vendor/src
+mkdir $WORK/tmp/gopath/src/x/y/_vendor/src/x/y/z
+cp z.go $WORK/tmp/gopath/src/x/y/z/z.go
+
+env GOPATH=$WORK/tmp/gopath/src/x/y/_vendor${:}$WORK/tmp/gopath
+cd $WORK/tmp/gopath/src
+go list ./...
+
+-- w.go --
+package w
+
+import "x/y/z"
+-- z.go --
+package z
diff --git a/libgo/go/cmd/go/testdata/script/list_test_simple.txt b/libgo/go/cmd/go/testdata/script/list_test_simple.txt
new file mode 100644 (file)
index 0000000..954897c
--- /dev/null
@@ -0,0 +1,67 @@
+[short] skip
+
+# Test
+go test -list=Test
+stdout TestSimple
+
+# Benchmark
+go test -list=Benchmark
+stdout BenchmarkSimple
+
+# Examples
+go test -list=Example
+stdout ExampleSimple
+stdout ExampleWithEmptyOutput
+
+-- go.mod --
+module m
+
+go 1.16
+-- bench_test.go --
+package testlist
+
+import (
+       "fmt"
+       "testing"
+)
+
+func BenchmarkSimplefunc(b *testing.B) {
+       b.StopTimer()
+       b.StartTimer()
+       for i := 0; i < b.N; i++ {
+               _ = fmt.Sprint("Test for bench")
+       }
+}
+-- example_test.go --
+package testlist
+
+import (
+       "fmt"
+)
+
+func ExampleSimple() {
+       fmt.Println("Test with Output.")
+
+       // Output: Test with Output.
+}
+
+func ExampleWithEmptyOutput() {
+       fmt.Println("")
+
+       // Output:
+}
+
+func ExampleNoOutput() {
+       _ = fmt.Sprint("Test with no output")
+}
+-- test_test.go --
+package testlist
+
+import (
+       "fmt"
+       "testing"
+)
+
+func TestSimple(t *testing.T) {
+       _ = fmt.Sprint("Test simple")
+}
diff --git a/libgo/go/cmd/go/testdata/script/list_wildcard_skip_nonmatching.txt b/libgo/go/cmd/go/testdata/script/list_wildcard_skip_nonmatching.txt
new file mode 100644 (file)
index 0000000..02b1088
--- /dev/null
@@ -0,0 +1,17 @@
+# Test that wildcards don't look in useless directories.
+
+# First make sure that badpkg fails the list of '...'.
+! go list ./...
+stderr badpkg
+
+# Check that the list of './goodpkg...' succeeds. That implies badpkg was skipped.
+go list ./goodpkg...
+
+-- go.mod --
+module m
+
+go 1.16
+-- goodpkg/x.go --
+package goodpkg
+-- badpkg/x.go --
+pkg badpkg
diff --git a/libgo/go/cmd/go/testdata/script/load_test_pkg_err.txt b/libgo/go/cmd/go/testdata/script/load_test_pkg_err.txt
new file mode 100644 (file)
index 0000000..d088ee4
--- /dev/null
@@ -0,0 +1,30 @@
+# Tests issue 37971. Check that tests are still loaded even when the package has an error.
+
+go list -e -test d
+cmp stdout want_stdout
+
+go list -e -test -deps d
+stdout golang.org/fake/d
+
+-- want_stdout --
+d
+d.test
+d_test [d.test]
+-- go.mod --
+module d
+
+go 1.16
+-- d.go --
+package d
+
+import "net/http"
+
+const d = http.MethodGet
+func Get() string { return d; }
+-- d2.go --
+-- d_test.go --
+package d_test
+
+import "testing"
+import "golang.org/fake/d"
+func TestD(t *testing.T) { d.Get(); }
diff --git a/libgo/go/cmd/go/testdata/script/mod_all.txt b/libgo/go/cmd/go/testdata/script/mod_all.txt
new file mode 100644 (file)
index 0000000..090eeee
--- /dev/null
@@ -0,0 +1,468 @@
+# This test illustrates the relationship between the 'all' pattern and
+# the dependencies of the main module.
+
+# The package import graph used in this test looks like:
+#
+# main --------- a --------- b
+# |              |
+# |              a_test ---- c
+# |                          |
+# |                          c_test ---- d
+# |
+# main_test ---- t --------- u
+#                |
+#                t_test ---- w
+#                            |
+#                            w_test ---- x
+#
+# main/testonly_test ---- q --------- r
+#                         |
+#                         q_test ---- s
+#
+# And the module dependency graph looks like:
+#
+# main --- a.1 ---- b.1
+#  \   \    \
+#   \   \    c.1 -- d.1
+#    \   \
+#     \    t.1 ---- u.1
+#      \    \
+#       \    w.1 -- x.1
+#        \
+#          q.1 ---- r.1
+#           \
+#            s.1
+
+env PKGFMT='{{if .Module}}{{.ImportPath}}{{end}}'
+env MODFMT='{{.Path}}'
+
+
+# 'go list -deps' lists packages and tests in the main module,
+# along with their transitive dependencies.
+
+go list -f $PKGFMT -deps ./...
+stdout -count=4 '^.'
+stdout '^example.com/a$'
+stdout '^example.com/b$'
+stdout '^example.com/main$'
+stdout '^example.com/main/testonly'
+
+
+# 'go list -deps -test' lists transitive imports of tests and non-tests in the
+# main module.
+
+go list -f $PKGFMT -deps -test ./...
+stdout -count=13 '^.'
+stdout '^example.com/a$'
+stdout '^example.com/b$'
+stdout '^example.com/main$'
+stdout '^example.com/main.test$'
+stdout '^example.com/main \[example.com/main.test\]$'
+stdout '^example.com/main_test \[example.com/main.test\]$'
+stdout '^example.com/main/testonly$'
+stdout '^example.com/main/testonly.test$'
+stdout '^example.com/main/testonly_test \[example.com/main/testonly.test\]$'
+stdout '^example.com/q$'
+stdout '^example.com/r$'
+stdout '^example.com/t$'
+stdout '^example.com/u$'
+
+
+# 'go list all' lists the fixpoint of iterating 'go list -deps -test' starting
+# with the packages in the main module, then reducing to only the non-test
+# variants of those packages.
+
+go list -f $PKGFMT all
+stdout -count=13 '^.'
+stdout '^example.com/a$'
+stdout '^example.com/b$'
+stdout '^example.com/c$'
+stdout '^example.com/d$'
+stdout '^example.com/main$'
+stdout '^example.com/main/testonly$'
+stdout '^example.com/q$'
+stdout '^example.com/r$'
+stdout '^example.com/s$'
+stdout '^example.com/t$'
+stdout '^example.com/u$'
+stdout '^example.com/w$'
+stdout '^example.com/x$'
+
+
+# 'go list -test all' is equivalent to 'go list -test $(go list all)'
+# and both should include tests for every package in 'all'.
+
+go list -test -f $PKGFMT example.com/a example.com/b example.com/c example.com/d example.com/main example.com/main/testonly example.com/q example.com/r example.com/s example.com/t example.com/u example.com/w example.com/x
+cp stdout list-test-explicit.txt
+
+go list -test -f $PKGFMT all
+cmp stdout list-test-explicit.txt
+stdout -count=36 '^.'
+stdout '^example.com/a$'
+stdout '^example.com/b$'
+stdout '^example.com/c$'
+stdout '^example.com/d$'
+stdout '^example.com/main$'
+stdout '^example.com/main/testonly$'
+stdout '^example.com/q$'
+stdout '^example.com/r$'
+stdout '^example.com/s$'
+stdout '^example.com/t$'
+stdout '^example.com/u$'
+stdout '^example.com/w$'
+stdout '^example.com/x$'
+stdout '^example.com/a.test$'
+stdout '^example.com/a_test \[example.com/a.test\]$'
+stdout '^example.com/b.test$'
+stdout '^example.com/b_test \[example.com/b.test\]$'
+stdout '^example.com/c.test$'
+stdout '^example.com/c_test \[example.com/c.test\]$'
+stdout '^example.com/main.test$'
+stdout '^example.com/main \[example.com/main.test\]$'
+stdout '^example.com/main_test \[example.com/main.test\]$'
+stdout '^example.com/main/testonly.test$'
+stdout '^example.com/main/testonly_test \[example.com/main/testonly.test\]$'
+stdout '^example.com/q.test$'
+stdout '^example.com/q_test \[example.com/q.test\]$'
+stdout '^example.com/r.test$'
+stdout '^example.com/r_test \[example.com/r.test\]$'
+stdout '^example.com/s.test$'
+stdout '^example.com/s_test \[example.com/s.test\]$'
+stdout '^example.com/t.test$'
+stdout '^example.com/t_test \[example.com/t.test\]$'
+stdout '^example.com/u.test$'
+stdout '^example.com/u_test \[example.com/u.test\]$'
+stdout '^example.com/w.test$'
+stdout '^example.com/w_test \[example.com/w.test\]$'
+
+
+# 'go list -m all' covers the packages in 'go list -test -deps all'.
+
+go list -m -f $MODFMT all
+stdout -count=12 '^.'
+stdout '^example.com/a$'
+stdout '^example.com/b$'
+stdout '^example.com/c$'
+stdout '^example.com/d$'
+stdout '^example.com/main$'
+stdout '^example.com/q$'
+stdout '^example.com/r$'
+stdout '^example.com/s$'
+stdout '^example.com/t$'
+stdout '^example.com/u$'
+stdout '^example.com/w$'
+stdout '^example.com/x$'
+
+
+# 'go mod vendor' copies in only the packages transitively imported by the main
+# module, and omits their tests. As a result, the 'all' and '...' patterns
+# report fewer packages when using '-mod=vendor'.
+
+go mod vendor
+
+go list -f $PKGFMT -mod=vendor all
+stdout -count=8 '^.'
+stdout '^example.com/a$'
+stdout '^example.com/b$'
+stdout '^example.com/main$'
+stdout '^example.com/main/testonly$'
+stdout '^example.com/q$'
+stdout '^example.com/r$'
+stdout '^example.com/t$'
+stdout '^example.com/u$'
+
+go list -test -f $PKGFMT -mod=vendor all
+stdout -count=13 '^.'
+stdout '^example.com/a$'
+stdout '^example.com/b$'
+stdout '^example.com/main$'
+stdout '^example.com/main/testonly$'
+stdout '^example.com/q$'
+stdout '^example.com/r$'
+stdout '^example.com/t$'
+stdout '^example.com/u$'
+stdout '^example.com/main.test$'
+stdout '^example.com/main \[example.com/main.test\]$'
+stdout '^example.com/main_test \[example.com/main.test\]$'
+stdout '^example.com/main/testonly.test$'
+stdout '^example.com/main/testonly_test \[example.com/main/testonly.test\]$'
+
+rm vendor
+
+# Convert all modules to go 1.17 to enable lazy loading.
+go mod edit -go=1.17 a/go.mod
+go mod edit -go=1.17 b/go.mod
+go mod edit -go=1.17 c/go.mod
+go mod edit -go=1.17 d/go.mod
+go mod edit -go=1.17 q/go.mod
+go mod edit -go=1.17 r/go.mod
+go mod edit -go=1.17 s/go.mod
+go mod edit -go=1.17 t/go.mod
+go mod edit -go=1.17 u/go.mod
+go mod edit -go=1.17 w/go.mod
+go mod edit -go=1.17 x/go.mod
+go mod edit -go=1.17
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod go.mod.orig
+
+# With lazy loading, 'go list all' with neither -mod=vendor nor -test should
+# match -mod=vendor without -test in 1.15.
+
+go list -f $PKGFMT all
+stdout -count=8 '^.'
+stdout '^example.com/a$'
+stdout '^example.com/b$'
+stdout '^example.com/main$'
+stdout '^example.com/main/testonly$'
+stdout '^example.com/q$'
+stdout '^example.com/r$'
+stdout '^example.com/t$'
+stdout '^example.com/u$'
+
+# 'go list -test all' should expand that to include the test variants of the
+# packages in 'all', but not the dependencies of outside tests.
+
+go list -test -f $PKGFMT all
+stdout -count=25 '^.'
+stdout '^example.com/a$'
+stdout '^example.com/b$'
+stdout '^example.com/main$'
+stdout '^example.com/main/testonly$'
+stdout '^example.com/q$'
+stdout '^example.com/r$'
+stdout '^example.com/t$'
+stdout '^example.com/u$'
+stdout '^example.com/a.test$'
+stdout '^example.com/a_test \[example.com/a.test\]$'
+stdout '^example.com/b.test$'
+stdout '^example.com/b_test \[example.com/b.test\]$'
+stdout '^example.com/main.test$'
+stdout '^example.com/main \[example.com/main.test\]$'
+stdout '^example.com/main_test \[example.com/main.test\]$'
+stdout '^example.com/main/testonly.test$'
+stdout '^example.com/main/testonly_test \[example.com/main/testonly.test\]$'
+stdout '^example.com/q.test$'
+stdout '^example.com/q_test \[example.com/q.test\]$'
+stdout '^example.com/r.test$'
+stdout '^example.com/r_test \[example.com/r.test\]$'
+stdout '^example.com/t.test$'
+stdout '^example.com/t_test \[example.com/t.test\]$'
+stdout '^example.com/u.test$'
+stdout '^example.com/u_test \[example.com/u.test\]$'
+
+# 'go list -test -deps all' should include the dependencies of those tests,
+# but not the tests of the dependencies of outside tests.
+
+go list -test -deps -f $PKGFMT all
+stdout -count=28 '^.'
+stdout '^example.com/a$'
+stdout '^example.com/b$'
+stdout '^example.com/c$'
+stdout '^example.com/main$'
+stdout '^example.com/main/testonly$'
+stdout '^example.com/q$'
+stdout '^example.com/r$'
+stdout '^example.com/s$'
+stdout '^example.com/t$'
+stdout '^example.com/u$'
+stdout '^example.com/w$'
+stdout '^example.com/a.test$'
+stdout '^example.com/a_test \[example.com/a.test\]$'
+stdout '^example.com/b.test$'
+stdout '^example.com/b_test \[example.com/b.test\]$'
+stdout '^example.com/main.test$'
+stdout '^example.com/main \[example.com/main.test\]$'
+stdout '^example.com/main_test \[example.com/main.test\]$'
+stdout '^example.com/main/testonly.test$'
+stdout '^example.com/main/testonly_test \[example.com/main/testonly.test\]$'
+stdout '^example.com/q.test$'
+stdout '^example.com/q_test \[example.com/q.test\]$'
+stdout '^example.com/r.test$'
+stdout '^example.com/r_test \[example.com/r.test\]$'
+stdout '^example.com/t.test$'
+stdout '^example.com/t_test \[example.com/t.test\]$'
+stdout '^example.com/u.test$'
+stdout '^example.com/u_test \[example.com/u.test\]$'
+
+# 'go list -m all' should cover all of the modules providing packages in
+# 'go list -test -deps all', but should exclude modules d and x,
+# which are not relevant to the main module and are outside of the
+# lazy-loading horizon.
+
+go list -m -f $MODFMT all
+stdout -count=10 '^.'
+stdout '^example.com/a$'
+stdout '^example.com/b$'
+stdout '^example.com/c$'
+! stdout '^example.com/d$'
+stdout '^example.com/main$'
+stdout '^example.com/q$'
+stdout '^example.com/r$'
+stdout '^example.com/s$'
+stdout '^example.com/t$'
+stdout '^example.com/u$'
+stdout '^example.com/w$'
+! stdout '^example.com/x$'
+
+-- go.mod --
+module example.com/main
+
+// Note: this go.mod file initially specifies go 1.15,
+// but includes some redundant roots so that it
+// also already obeys the 1.17 lazy loading invariants.
+go 1.15
+
+require (
+       example.com/a v0.1.0
+       example.com/b v0.1.0
+       example.com/q v0.1.0
+       example.com/r v0.1.0 // indirect
+       example.com/t v0.1.0
+       example.com/u v0.1.0 // indirect
+)
+
+replace (
+       example.com/a v0.1.0 => ./a
+       example.com/b v0.1.0 => ./b
+       example.com/c v0.1.0 => ./c
+       example.com/d v0.1.0 => ./d
+       example.com/q v0.1.0 => ./q
+       example.com/r v0.1.0 => ./r
+       example.com/s v0.1.0 => ./s
+       example.com/t v0.1.0 => ./t
+       example.com/u v0.1.0 => ./u
+       example.com/w v0.1.0 => ./w
+       example.com/x v0.1.0 => ./x
+)
+-- main.go --
+package main
+
+import _ "example.com/a"
+
+func main() {}
+-- main_test.go --
+package main_test
+
+import _ "example.com/t"
+-- testonly/testonly_test.go --
+package testonly_test
+
+import _ "example.com/q"
+-- a/go.mod --
+module example.com/a
+
+go 1.15
+
+require (
+       example.com/b v0.1.0
+       example.com/c v0.1.0
+)
+-- a/a.go --
+package a
+
+import _ "example.com/b"
+-- a/a_test.go --
+package a_test
+
+import _ "example.com/c"
+-- b/go.mod --
+module example.com/b
+
+go 1.15
+-- b/b.go --
+package b
+-- b/b_test.go --
+package b_test
+-- c/go.mod --
+module example.com/c
+
+go 1.15
+
+require example.com/d v0.1.0
+-- c/c.go --
+package c
+-- c/c_test.go --
+package c_test
+
+import _ "example.com/d"
+-- d/go.mod --
+module example.com/d
+
+go 1.15
+-- d/d.go --
+package d
+-- q/go.mod --
+module example.com/q
+
+go 1.15
+
+require (
+       example.com/r v0.1.0
+       example.com/s v0.1.0
+)
+-- q/q.go --
+package q
+import _ "example.com/r"
+-- q/q_test.go --
+package q_test
+import _ "example.com/s"
+-- r/go.mod --
+module example.com/r
+
+go 1.15
+-- r/r.go --
+package r
+-- r/r_test.go --
+package r_test
+-- s/go.mod --
+module example.com/s
+
+go 1.15
+-- s/s.go --
+package s
+-- s/s_test.go --
+package s_test
+-- t/go.mod --
+module example.com/t
+
+go 1.15
+
+require (
+       example.com/u v0.1.0
+       example.com/w v0.1.0
+)
+-- t/t.go --
+package t
+
+import _ "example.com/u"
+-- t/t_test.go --
+package t_test
+
+import _ "example.com/w"
+-- u/go.mod --
+module example.com/u
+
+go 1.15
+-- u/u.go --
+package u
+-- u/u_test.go --
+package u_test
+-- w/go.mod --
+module example.com/w
+
+go 1.15
+
+require example.com/x v0.1.0
+-- w/w.go --
+package w
+-- w/w_test.go --
+package w_test
+
+import _ "example.com/x"
+-- x/go.mod --
+module example.com/x
+
+go 1.15
+-- x/x.go --
+package x
diff --git a/libgo/go/cmd/go/testdata/script/mod_cache_dir.txt b/libgo/go/cmd/go/testdata/script/mod_cache_dir.txt
new file mode 100644 (file)
index 0000000..7284ccf
--- /dev/null
@@ -0,0 +1,11 @@
+env GO111MODULE=on
+
+# Go should reject relative paths in GOMODCACHE environment.
+
+env GOMODCACHE="~/test"
+! go get example.com/tools/cmd/hello
+stderr 'must be absolute path'
+
+env GOMODCACHE="./test"
+! go get example.com/tools/cmd/hello
+stderr 'must be absolute path'
diff --git a/libgo/go/cmd/go/testdata/script/mod_convert.txt b/libgo/go/cmd/go/testdata/script/mod_convert.txt
new file mode 100644 (file)
index 0000000..f60fe87
--- /dev/null
@@ -0,0 +1,66 @@
+[short] skip
+[!net] skip
+[!exec:git] skip
+
+env GO111MODULE=on
+env GOPROXY=
+env GOSUMDB=
+
+go mod download github.com/docker/distribution@v0.0.0-20150410205453-85de3967aa93
+mkdir x/Godeps
+cp $GOPATH/pkg/mod/github.com/docker/distribution@v0.0.0-20150410205453-85de3967aa93/Godeps/Godeps.json x/Godeps
+cd x
+go mod init github.com/docker/distribution
+cmpenv go.mod go.mod.want
+
+go mod download github.com/fishy/gcsbucket@v0.0.0-20180217031846-618d60fe84e0
+cp $GOPATH/pkg/mod/github.com/fishy/gcsbucket@v0.0.0-20180217031846-618d60fe84e0/Gopkg.lock ../y
+cd ../y
+go mod init github.com/fishy/gcsbucket
+cmpenv go.mod go.mod.want
+
+-- x/go.mod.want --
+module github.com/docker/distribution
+
+go $goversion
+
+require (
+       github.com/AdRoll/goamz v0.0.0-20150130162828-d3664b76d905
+       github.com/MSOpenTech/azure-sdk-for-go v0.0.0-20150323223030-d90753bcad2e
+       github.com/Sirupsen/logrus v0.7.3
+       github.com/bugsnag/bugsnag-go v1.0.3-0.20141110184014-b1d153021fcd
+       github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b
+       github.com/bugsnag/panicwrap v0.0.0-20141110184334-e5f9854865b9
+       github.com/codegangsta/cli v1.4.2-0.20150131031259-6086d7927ec3
+       github.com/docker/docker v1.4.2-0.20150204013315-165ea5c158cf
+       github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1
+       github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7
+       github.com/gorilla/context v0.0.0-20140604161150-14f550f51af5
+       github.com/gorilla/handlers v0.0.0-20140825150757-0e84b7d810c1
+       github.com/gorilla/mux v0.0.0-20140926153814-e444e69cbd2e
+       github.com/jlhawn/go-crypto v0.0.0-20150401213827-cd738dde20f0
+       github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43
+       github.com/yvasiyarov/gorelic v0.0.7-0.20141212073537-a9bba5b9ab50
+       github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f
+       golang.org/x/net v0.0.0-20150202051010-1dfe7915deaf
+       gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789
+       gopkg.in/yaml.v2 v2.0.0-20150116202057-bef53efd0c76
+)
+-- y/go.mod.want --
+module github.com/fishy/gcsbucket
+
+go $goversion
+
+require (
+       cloud.google.com/go v0.18.0
+       github.com/fishy/fsdb v0.0.0-20180217030800-5527ded01371
+       github.com/golang/protobuf v1.0.0
+       github.com/googleapis/gax-go v2.0.0+incompatible
+       golang.org/x/net v0.0.0-20180216171745-136a25c244d3
+       golang.org/x/oauth2 v0.0.0-20180207181906-543e37812f10
+       golang.org/x/text v0.3.1-0.20180208041248-4e4a3210bb54
+       google.golang.org/api v0.0.0-20180217000815-c7a403bb5fe1
+       google.golang.org/appengine v1.0.0
+       google.golang.org/genproto v0.0.0-20180206005123-2b5a72b8730b
+       google.golang.org/grpc v1.10.0
+)
index ddb0c081996ed7653b1adfac836b3d017007d7ce..283e2d99366bb8c914f9b4428943355fdd286077 100644 (file)
@@ -1,4 +1,6 @@
 env GO111MODULE=on
+env GOPROXY=direct
+env GOSUMDB=off
 
 [!net] skip
 [!exec:git] skip
diff --git a/libgo/go/cmd/go/testdata/script/mod_deprecate_message.txt b/libgo/go/cmd/go/testdata/script/mod_deprecate_message.txt
new file mode 100644 (file)
index 0000000..5670279
--- /dev/null
@@ -0,0 +1,73 @@
+# When there is a short single-line message, 'go get' should print it all.
+go get -d short
+stderr '^go: module short is deprecated: short$'
+go list -m -u -f '{{.Deprecated}}' short
+stdout '^short$'
+
+# When there is a multi-line message, 'go get' should print the first line.
+go get -d multiline
+stderr '^go: module multiline is deprecated: first line$'
+! stderr 'second line'
+go list -m -u -f '{{.Deprecated}}' multiline
+stdout '^first line\nsecond line.$'
+
+# When there is a long message, 'go get' should print a placeholder.
+go get -d long
+stderr '^go: module long is deprecated: \(message omitted: too long\)$'
+go list -m -u -f '{{.Deprecated}}' long
+stdout '^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$'
+
+# When a message contains unprintable chracters, 'go get' should say that
+# without printing the message.
+go get -d unprintable
+stderr '^go: module unprintable is deprecated: \(message omitted: contains non-printable characters\)$'
+go list -m -u -f '{{.Deprecated}}' unprintable
+stdout '^message contains ASCII BEL\x07$'
+
+-- go.mod --
+module use
+
+go 1.16
+
+require (
+       short v0.0.0
+       multiline v0.0.0
+       long v0.0.0
+       unprintable v0.0.0
+)
+
+replace (
+       short v0.0.0 => ./short
+       multiline v0.0.0 => ./multiline
+       long v0.0.0 => ./long
+       unprintable v0.0.0 => ./unprintable
+)
+-- short/go.mod --
+// Deprecated: short
+module short
+
+go 1.16
+-- short/short.go --
+package short
+-- multiline/go.mod --
+// Deprecated: first line
+// second line.
+module multiline
+
+go 1.16
+-- multiline/multiline.go --
+package multiline
+-- long/go.mod --
+// Deprecated: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+module long
+
+go 1.16
+-- long/long.go --
+package long
+-- unprintable/go.mod --
+// Deprecated: message contains ASCII BEL\a
+module unprintable
+
+go 1.16
+-- unprintable/unprintable.go --
+package unprintable
diff --git a/libgo/go/cmd/go/testdata/script/mod_download_concurrent_read.txt b/libgo/go/cmd/go/testdata/script/mod_download_concurrent_read.txt
new file mode 100644 (file)
index 0000000..231babd
--- /dev/null
@@ -0,0 +1,110 @@
+# This test simulates a process watching for changes and reading files in
+# module cache as a module is extracted.
+#
+# Before Go 1.16, we extracted each module zip to a temporary directory with
+# a random name, then renamed that into place with os.Rename. On Windows,
+# this failed with ERROR_ACCESS_DENIED when another process (usually an
+# anti-virus scanner) opened files in the temporary directory. This test
+# simulates that behavior, verifying golang.org/issue/36568.
+#
+# Since 1.16, we extract to the final directory, but we create a .partial file
+# so that if we crash, other processes know the directory is incomplete.
+
+[!windows] skip
+[short] skip
+
+go run downloader.go
+
+-- go.mod --
+module example.com/m
+
+go 1.14
+
+-- downloader.go --
+package main
+
+import (
+       "fmt"
+       "log"
+       "os"
+       "os/exec"
+       "path/filepath"
+)
+
+func main() {
+       if err := run(); err != nil {
+               log.Fatal(err)
+       }
+}
+
+// run repeatedly downloads a module while opening files in the module cache
+// in a background goroutine.
+//
+// run uses a different temporary module cache in each iteration so that we
+// don't need to clean the cache or synchronize closing files after each
+// iteration.
+func run() (err error) {
+       tmpDir, err := os.MkdirTemp("", "")
+       if err != nil {
+               return err
+       }
+       defer func() {
+               if rmErr := os.RemoveAll(tmpDir); err == nil && rmErr != nil {
+                       err = rmErr
+               }
+       }()
+       for i := 0; i < 10; i++ {
+    gopath := filepath.Join(tmpDir, fmt.Sprintf("gopath%d", i))
+               var err error
+               done := make(chan struct{})
+               go func() {
+                       err = download(gopath)
+                       close(done)
+               }()
+               readCache(gopath, done)
+               if err != nil {
+                       return err
+               }
+       }
+       return nil
+}
+
+// download downloads a module into the given cache using 'go mod download'.
+func download(gopath string) error {
+       cmd := exec.Command("go", "mod", "download", "-modcacherw", "rsc.io/quote@v1.5.2")
+       cmd.Stderr = os.Stderr
+       cmd.Env = append(os.Environ(), "GOPATH="+gopath)
+       return cmd.Run()
+}
+
+// readCache repeatedly globs for go.mod files in the given cache, then opens
+// those files for reading. When the done chan is closed, readCache closes
+// files and returns.
+func readCache(gopath string, done <-chan struct{}) {
+       files := make(map[string]*os.File)
+       defer func() {
+               for _, f := range files {
+                       f.Close()
+               }
+       }()
+
+       pattern := filepath.Join(gopath, "pkg/mod/rsc.io/quote@v1.5.2*/go.mod")
+       for {
+               select {
+               case <-done:
+                       return
+               default:
+               }
+
+               names, _ := filepath.Glob(pattern)
+               for _, name := range names {
+                       if files[name] != nil {
+                               continue
+                       }
+                       f, _ := os.Open(name)
+                       if f != nil {
+                               files[name] = f
+                       }
+               }
+       }
+}
diff --git a/libgo/go/cmd/go/testdata/script/mod_download_partial.txt b/libgo/go/cmd/go/testdata/script/mod_download_partial.txt
new file mode 100644 (file)
index 0000000..0aab60d
--- /dev/null
@@ -0,0 +1,68 @@
+# Download modules and populate go.sum.
+go get -d -modcacherw
+exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/go.mod
+
+# 'go mod verify' should fail if we delete a file.
+go mod verify
+rm $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/go.mod
+! go mod verify
+
+# Create a .partial file to simulate an failure extracting the zip file.
+cp empty $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.partial
+
+# 'go mod verify' should not fail, since the module hasn't been completely
+# ingested into the cache.
+go mod verify
+
+# 'go list' should not load packages from the directory.
+# NOTE: the message "directory $dir outside available modules" is reported
+# for directories not in the main module, active modules in the module cache,
+# or local replacements. In this case, the directory is in the right place,
+# but it's incomplete, so 'go list' acts as if it's not an active module.
+! go list $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
+stderr 'outside available modules'
+
+# 'go list -m' should not print the directory.
+go list -m -f '{{.Dir}}' rsc.io/quote
+! stdout .
+
+# 'go mod download' should re-extract the module and remove the .partial file.
+go mod download -modcacherw rsc.io/quote
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.partial
+exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/go.mod
+
+# 'go list' should succeed.
+go list $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
+stdout '^rsc.io/quote$'
+
+# 'go list -m' should print the directory.
+go list -m -f '{{.Dir}}' rsc.io/quote
+stdout 'pkg[/\\]mod[/\\]rsc.io[/\\]quote@v1.5.2'
+
+# go mod verify should fail if we delete a file.
+go mod verify
+rm $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/go.mod
+! go mod verify
+
+# 'go mod download' should not leave behind a directory or a .partial file
+# if there is an error extracting the zip file.
+rm $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
+cp empty $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
+! go mod download
+stderr 'not a valid zip file'
+! exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.partial
+
+-- go.mod --
+module m
+
+go 1.14
+
+require rsc.io/quote v1.5.2
+
+-- use.go --
+package use
+
+import _ "rsc.io/quote"
+
+-- empty --
diff --git a/libgo/go/cmd/go/testdata/script/mod_e.txt b/libgo/go/cmd/go/testdata/script/mod_e.txt
new file mode 100644 (file)
index 0000000..3a0d18d
--- /dev/null
@@ -0,0 +1,89 @@
+cp go.mod go.mod.orig
+
+
+# If a dependency cannot be resolved, 'go mod tidy' fails with an error message
+# explaining the problem and does not update the go.mod file.
+# TODO(bcmills): Ideally, with less redundancy than these error messages!
+
+! go mod tidy
+
+stderr '^example.com/untidy imports\n\texample.net/directnotfound: cannot find module providing package example.net/directnotfound: module example.net/directnotfound: reading http://.*: 404 Not Found$'
+
+stderr '^example.com/untidy imports\n\texample.net/m imports\n\texample.net/indirectnotfound: cannot find module providing package example.net/indirectnotfound: module example.net/indirectnotfound: reading http://.*: 404 Not Found$'
+
+stderr '^example.com/untidy tested by\n\texample.com/untidy.test imports\n\texample.net/directtestnotfound: cannot find module providing package example.net/directtestnotfound: module example.net/directtestnotfound: reading http://.*: 404 Not Found$'
+
+stderr '^example.com/untidy imports\n\texample.net/m tested by\n\texample.net/m.test imports\n\texample.net/indirecttestnotfound: cannot find module providing package example.net/indirecttestnotfound: module example.net/indirecttestnotfound: reading http://.*: 404 Not Found$'
+
+cmp go.mod.orig go.mod
+
+
+# If a dependency cannot be resolved, 'go mod vendor' fails with an error message
+# explaining the problem, does not update the go.mod file, and does not create
+# the vendor directory.
+
+! go mod vendor
+
+stderr '^example.com/untidy imports\n\texample.net/directnotfound: cannot find module providing package example.net/directnotfound: module example.net/directnotfound: reading http://.*: 404 Not Found$'
+
+stderr '^example.com/untidy imports\n\texample.net/m imports\n\texample.net/indirectnotfound: cannot find module providing package example.net/indirectnotfound: module example.net/indirectnotfound: reading http://.*: 404 Not Found$'
+
+stderr '^example.com/untidy tested by\n\texample.com/untidy.test imports\n\texample.net/directtestnotfound: cannot find module providing package example.net/directtestnotfound: module example.net/directtestnotfound: reading http://.*: 404 Not Found$'
+
+! stderr 'indirecttestnotfound'  # Vendor prunes test dependencies.
+
+cmp go.mod.orig go.mod
+! exists vendor
+
+
+# 'go mod tidy' still logs the errors, but succeeds and updates go.mod.
+
+go mod tidy -e
+stderr -count=4 'cannot find module providing package'
+cmp go.mod.final go.mod
+
+
+# 'go mod vendor -e' still logs the errors, but succeeds and updates go.mod.
+
+cp go.mod.orig go.mod
+go mod vendor -e
+stderr -count=3 'cannot find module providing package'
+cmp go.mod.final go.mod
+exists vendor/modules.txt
+exists vendor/example.net/m/m.go
+
+
+-- go.mod --
+module example.com/untidy
+go 1.16
+replace example.net/m v0.1.0 => ./m
+-- go.mod.final --
+module example.com/untidy
+
+go 1.16
+
+replace example.net/m v0.1.0 => ./m
+
+require example.net/m v0.1.0
+-- untidy.go --
+package untidy
+
+import (
+       _ "example.net/m"
+       _ "example.net/directnotfound"
+)
+-- untidy_test.go --
+package untidy_test
+
+import _ "example.net/directtestnotfound"
+-- m/go.mod --
+module example.net/m
+go 1.16
+-- m/m.go --
+package m
+
+import _ "example.net/indirectnotfound"
+-- m/m_test.go --
+package m_test
+
+import _ "example.net/indirecttestnotfound"
index 9da69306dacc4032e73c7610770c252732d7178b..5aa5ca1ffc02c520d79eefa46e4d24f3b980dba4 100644 (file)
@@ -46,6 +46,10 @@ cmpenv stdout $WORK/go.mod.json
 go mod edit -json $WORK/go.mod.retractrationale
 cmp stdout $WORK/go.mod.retractrationale.json
 
+# go mod edit -json (deprecation)
+go mod edit -json $WORK/go.mod.deprecation
+cmp stdout $WORK/go.mod.deprecation.json
+
 # go mod edit -json (empty mod file)
 go mod edit -json $WORK/go.mod.empty
 cmp stdout $WORK/go.mod.empty.json
@@ -290,6 +294,20 @@ retract (
                }
        ]
 }
+-- $WORK/go.mod.deprecation --
+// Deprecated: and the new one is not ready yet
+module m
+-- $WORK/go.mod.deprecation.json --
+{
+       "Module": {
+               "Path": "m",
+               "Deprecated": "and the new one is not ready yet"
+       },
+       "Require": null,
+       "Exclude": null,
+       "Replace": null,
+       "Retract": null
+}
 -- $WORK/go.mod.empty --
 -- $WORK/go.mod.empty.json --
 {
diff --git a/libgo/go/cmd/go/testdata/script/mod_edit_no_modcache.txt b/libgo/go/cmd/go/testdata/script/mod_edit_no_modcache.txt
new file mode 100644 (file)
index 0000000..ced15bb
--- /dev/null
@@ -0,0 +1,15 @@
+# 'go mod edit' opportunistically locks the side-lock file in the module cache,
+# for compatibility with older versions of the 'go' command.
+# It does not otherwise depend on the module cache, so it should not
+# fail if the module cache directory cannot be created.
+
+[root] skip
+
+mkdir $WORK/readonly
+chmod 0555 $WORK/readonly
+env GOPATH=$WORK/readonly/nonexist
+
+go mod edit -go=1.17
+
+-- go.mod --
+module example.com/m
index 982e6b2e518d9670fff09fb896f02acdc065dce5..c4359bccccf49cffd05862ee3dc3b41b60c26222 100644 (file)
@@ -1,4 +1,4 @@
-# This test checks error messages for non-existant packages in module mode.
+# This test checks error messages for non-existent packages in module mode.
 # Veries golang.org/issue/35414
 env GO111MODULE=on
 cd $WORK
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_ambiguous_arg.txt b/libgo/go/cmd/go/testdata/script/mod_get_ambiguous_arg.txt
new file mode 100644 (file)
index 0000000..daed03b
--- /dev/null
@@ -0,0 +1,107 @@
+go mod tidy
+cp go.mod go.mod.orig
+
+# If there is no sensible *package* meaning for 'm/p', it should refer
+# to *module* m/p.
+
+go get -d m/p  # @latest
+go list -m all
+stdout '^m/p v0.3.0 '
+! stdout '^m '
+
+cp go.mod.orig go.mod
+
+go get -d m/p@v0.1.0
+go list -m all
+stdout '^m/p v0.1.0 '
+! stdout '^m '
+
+# When feasible, the argument 'm/p' in 'go get m/p' refers to *package* m/p,
+# which is in module m.
+#
+# (It only refers to *module* m/p if there is no such package at the
+# requested version.)
+
+go get -d m/p@v0.2.0
+go list -m all
+stdout '^m v0.2.0 '
+stdout '^m/p v0.1.0 '  # unchanged from the previous case
+
+# Repeating the above with module m/p already in the module graph does not
+# change its meaning.
+
+go get -d m/p@v0.2.0
+go list -m all
+stdout '^m v0.2.0 '
+stdout '^m/p v0.1.0 '
+
+-- go.mod --
+module example.com
+
+go 1.16
+
+replace (
+       m v0.1.0 => ./m01
+       m v0.2.0 => ./m02
+       m v0.3.0 => ./m03
+       m/p v0.1.0 => ./mp01
+       m/p v0.2.0 => ./mp02
+       m/p v0.3.0 => ./mp03
+)
+-- m01/go.mod --
+module m
+
+go 1.16
+-- m01/README.txt --
+Module m at v0.1.0 does not yet contain package p.
+
+-- m02/go.mod --
+module m
+
+go 1.16
+
+require m/p v0.1.0
+-- m02/p/p.go --
+// Package p is present in module m, but not module m/p.
+package p
+
+-- m03/go.mod --
+module m
+
+go 1.16
+
+require m/p v0.1.0
+-- m03/README.txt --
+Module m at v0.3.0 no longer contains package p.
+
+-- mv2/go.mod --
+module m/v2
+
+go 1.16
+-- mv2/README.txt --
+This module is m/v2. It doesn't actually need to exist,
+but it explains how module m could plausibly exist
+and still contain package p at 'latest' even when module
+m/p also exists.
+
+-- mp01/go.mod --
+module m/p
+
+go 1.16
+-- mp01/README.txt --
+This module is m/p.
+Package m/p does not exist in this module.
+-- mp02/go.mod --
+module m/p
+
+go 1.16
+-- mp02/README.txt --
+This module is m/p.
+Package m/p does not exist in this module.
+-- mp03/go.mod --
+module m/p
+
+go 1.16
+-- mp03/README.txt --
+This module is m/p.
+Package m/p does not exist in this module.
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_ambiguous_import.txt b/libgo/go/cmd/go/testdata/script/mod_get_ambiguous_import.txt
new file mode 100644 (file)
index 0000000..33605f5
--- /dev/null
@@ -0,0 +1,60 @@
+go list -m all
+stdout '^example.net/m v0.1.0 '
+! stdout '^example.net/m/p '
+cp go.mod go.mod.orig
+
+# Upgrading example.net/m/p without also upgrading example.net/m
+# causes the import of package example.net/m/p to be ambiguous.
+#
+# TODO(#27899): Should we automatically upgrade example.net/m to v0.2.0
+# to resolve the conflict?
+! go get -d example.net/m/p@v1.0.0
+stderr '^example.net/m/p: ambiguous import: found package example.net/m/p in multiple modules:\n\texample.net/m v0.1.0 \(.*[/\\]m1[/\\]p\)\n\texample.net/m/p v1.0.0 \(.*[/\\]p0\)\n\z'
+cmp go.mod go.mod.orig
+
+# Upgrading both modules simultaneously resolves the ambiguous upgrade.
+# Note that this command line mixes a module path (example.net/m)
+# and a package path (example.net/m/p) in the same command.
+go get -d example.net/m@v0.2.0 example.net/m/p@v1.0.0
+
+go list -m all
+stdout '^example.net/m v0.2.0 '
+stdout '^example.net/m/p v1.0.0 '
+
+-- go.mod --
+module example.net/importer
+
+go 1.16
+
+require (
+       example.net/m v0.1.0
+)
+
+replace (
+       example.net/m v0.1.0 => ./m1
+       example.net/m v0.2.0 => ./m2
+       example.net/m/p v1.0.0 => ./p0
+)
+-- importer.go --
+package importer
+import _ "example.net/m/p"
+-- m1/go.mod --
+module example.net/m
+
+go 1.16
+-- m1/p/p.go --
+package p
+-- m2/go.mod --
+module example.net/m
+
+go 1.16
+-- m2/README.txt --
+Package p has been moved to module …/m/p.
+Module …/m/p does not require any version of module …/m.
+
+-- p0/go.mod --
+module example.net/m/p
+
+go 1.16
+-- p0/p.go --
+package p
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_ambiguous_pkg.txt b/libgo/go/cmd/go/testdata/script/mod_get_ambiguous_pkg.txt
new file mode 100644 (file)
index 0000000..0e7f93b
--- /dev/null
@@ -0,0 +1,87 @@
+# Both example.net/ambiguous v0.1.0 and example.net/ambiguous/pkg v0.1.0 exist.
+# 'go mod tidy' would arbitrarily choose the one with the longer path,
+# but 'go mod tidy' also arbitrarily chooses the latest version.
+
+cp go.mod go.mod.orig
+
+
+# From a clean slate, 'go get' currently does the same thing as 'go mod tidy':
+# it resolves the package from the module with the longest matching prefix.
+
+go get -d example.net/ambiguous/nested/pkg@v0.1.0
+go list -m all
+stdout '^example.net/ambiguous/nested v0.1.0$'
+! stdout '^example.net/ambiguous '
+
+
+# From an initial state that already depends on the shorter path,
+# the same 'go get' command should (somewhat arbitrarily) keep the
+# existing path, since it is a valid interpretation of the command.
+
+cp go.mod.orig go.mod
+go mod edit -require=example.net/ambiguous@v0.1.0
+
+go get -d example.net/ambiguous/nested/pkg@v0.1.0
+go list -m all
+stdout '^example.net/ambiguous v0.1.0$'
+! stdout '^example.net/ambiguous/nested '
+
+
+# The user should be able to make the command unambiguous by explicitly
+# upgrading the conflicting module...
+
+go get -d example.net/ambiguous@v0.2.0 example.net/ambiguous/nested/pkg@v0.1.0
+go list -m all
+stdout '^example.net/ambiguous/nested v0.1.0$'
+stdout '^example.net/ambiguous v0.2.0$'
+
+
+# ...or by explicitly NOT adding the conflicting module.
+
+cp go.mod.orig go.mod
+go mod edit -require=example.net/ambiguous@v0.1.0
+
+go get -d example.net/ambiguous/nested/pkg@v0.1.0 example.net/ambiguous/nested@none
+go list -m all
+! stdout '^example.net/ambiguous/nested '
+stdout '^example.net/ambiguous v0.1.0$'
+
+
+# The user should also be able to fix it by *downgrading* the conflicting module
+# away.
+
+cp go.mod.orig go.mod
+go mod edit -require=example.net/ambiguous@v0.1.0
+
+go get -d example.net/ambiguous@none example.net/ambiguous/nested/pkg@v0.1.0
+go list -m all
+stdout '^example.net/ambiguous/nested v0.1.0$'
+! stdout '^example.net/ambiguous '
+
+
+# In contrast, if we do the same thing tacking a wildcard pattern ('/...') on
+# the end of the package path, we get different behaviors depending on the
+# initial state, and no error. (This seems to contradict the “same meaning
+# regardless of the initial state” point above, but maybe that's ok?)
+
+cp go.mod.orig go.mod
+
+go get -d example.net/ambiguous/nested/pkg/...@v0.1.0
+go list -m all
+stdout '^example.net/ambiguous/nested v0.1.0$'
+! stdout '^example.net/ambiguous '
+
+
+cp go.mod.orig go.mod
+go mod edit -require=example.net/ambiguous@v0.1.0
+
+go get -d example.net/ambiguous/nested/pkg/...@v0.1.0
+go list -m all
+! stdout '^example.net/ambiguous/nested '
+stdout '^example.net/ambiguous v0.1.0$'
+
+
+-- go.mod --
+module test
+
+go 1.16
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_changes.txt b/libgo/go/cmd/go/testdata/script/mod_get_changes.txt
new file mode 100644 (file)
index 0000000..3287b2a
--- /dev/null
@@ -0,0 +1,70 @@
+# When adding a requirement, 'go get' prints a message for the requirement
+# and for changed explicit dependencies. 'go get' does not print messages
+# for changed indirect dependencies.
+go list -m all
+! stdout golang.org/x/text
+go get -d rsc.io/quote@v1.5.2
+stderr '^go get: added rsc.io/quote v1.5.2$'
+stderr '^go get: upgraded rsc.io/sampler v1.0.0 => v1.3.0$'
+! stderr '^go get.*golang.org/x/text'
+go list -m all
+stdout golang.org/x/text
+cmp go.mod go.mod.upgrade
+
+# When removing a requirement, 'go get' prints a message for the requiremnent
+# and for changed explicit dependencies. 'go get' does not print messages
+# for changed indirect dependencies.
+go get -d rsc.io/sampler@none
+stderr '^go get: downgraded rsc.io/quote v1.5.2 => v1.3.0$'
+stderr '^go get: removed rsc.io/sampler v1.3.0$'
+! stderr '^go get.*golang.org/x/text'
+cmp go.mod go.mod.downgrade
+
+# When removing or downgrading a requirement, 'go get' also prints a message
+# for explicit dependencies removed as a consequence.
+cp go.mod.usequote go.mod
+go get -d rsc.io/quote@v1.5.1
+stderr '^go get: downgraded rsc.io/quote v1.5.2 => v1.5.1$'
+stderr '^go get: removed usequote v0.0.0$'
+
+-- go.mod --
+module m
+
+go 1.16
+
+require rsc.io/sampler v1.0.0
+-- go.sum --
+rsc.io/sampler v1.0.0 h1:SRJnjyQ07sAtq6G4RcfJEmz8JxqLyj3PoGXG2VhbDWo=
+rsc.io/sampler v1.0.0/go.mod h1:cqxpM3ZVz9VtirqxZPmrWzkQ+UkiNiGtkrN+B+i8kx8=
+-- go.mod.upgrade --
+module m
+
+go 1.16
+
+require (
+       rsc.io/quote v1.5.2 // indirect
+       rsc.io/sampler v1.3.0
+)
+-- go.mod.downgrade --
+module m
+
+go 1.16
+
+require (
+       golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
+       rsc.io/quote v1.3.0 // indirect
+)
+-- go.mod.usequote --
+module m
+
+go 1.16
+
+require usequote v0.0.0
+
+replace usequote => ./usequote
+-- usequote/go.mod --
+module usequote
+
+go 1.16
+
+require rsc.io/quote v1.5.2
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_deprecate_install.txt b/libgo/go/cmd/go/testdata/script/mod_get_deprecate_install.txt
new file mode 100644 (file)
index 0000000..63cd27a
--- /dev/null
@@ -0,0 +1,39 @@
+[short] skip
+
+env GO111MODULE=on
+
+# 'go get' outside a module with an executable prints a deprecation message.
+go get example.com/cmd/a
+stderr '^go get: installing executables with ''go get'' in module mode is deprecated.$'
+stderr 'Use ''go install pkg@version'' instead.'
+
+cp go.mod.orig go.mod
+
+# 'go get' inside a module with a non-main package does not print a message.
+# This will stop building in the future, but it's the command we want to use.
+go get rsc.io/quote
+! stderr deprecated
+cp go.mod.orig go.mod
+
+# 'go get' inside a module with an executable prints a different
+# deprecation message.
+go get example.com/cmd/a
+stderr '^go get: installing executables with ''go get'' in module mode is deprecated.$'
+stderr 'To adjust and download dependencies of the current module, use ''go get -d'''
+cp go.mod.orig go.mod
+
+# 'go get' should not print a warning for a main package inside the main module.
+# The intent is most likely to update the dependencies of that package.
+# 'go install' would be used otherwise.
+go get m
+! stderr .
+cp go.mod.orig go.mod
+
+-- go.mod.orig --
+module m
+
+go 1.17
+-- main.go --
+package main
+
+func main() {}
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_deprecated.txt b/libgo/go/cmd/go/testdata/script/mod_get_deprecated.txt
new file mode 100644 (file)
index 0000000..7bdd7a5
--- /dev/null
@@ -0,0 +1,66 @@
+# 'go get pkg' should not show a deprecation message for an unrelated module.
+go get -d ./use/nothing
+! stderr 'module.*is deprecated'
+
+# 'go get pkg' should show a deprecation message for the module providing pkg.
+go get -d example.com/deprecated/a
+stderr '^go: module example.com/deprecated/a is deprecated: in example.com/deprecated/a@v1.9.0$'
+go get -d example.com/deprecated/a@v1.0.0
+stderr '^go: module example.com/deprecated/a is deprecated: in example.com/deprecated/a@v1.9.0$'
+
+# 'go get pkg' should show a deprecation message for a module providing
+# packages directly imported by pkg.
+go get -d ./use/a
+stderr '^go: module example.com/deprecated/a is deprecated: in example.com/deprecated/a@v1.9.0$'
+
+# 'go get pkg' may show a deprecation message for an indirectly required module
+# if it provides a package named on the command line.
+go get -d ./use/b
+! stderr 'module.*is deprecated'
+go get -d local/use
+! stderr 'module.*is deprecated'
+go get -d example.com/deprecated/b
+stderr '^go: module example.com/deprecated/b is deprecated: in example.com/deprecated/b@v1.9.0$'
+
+# 'go get pkg' does not show a deprecation message for a module providing a
+# directly imported package if the module is no longer deprecated in its
+# latest version, even if the module is deprecated in its current version.
+go get -d ./use/undeprecated
+! stderr 'module.*is deprecated'
+
+-- go.mod --
+module m
+
+go 1.17
+
+require (
+       example.com/deprecated/a v1.0.0
+       example.com/undeprecated v1.0.0
+       local v0.0.0
+)
+
+replace local v0.0.0 => ./local
+-- use/nothing/nothing.go --
+package nothing
+-- use/a/a.go --
+package a
+
+import _ "example.com/deprecated/a"
+-- use/b/b.go --
+package b
+
+import _ "local/use"
+-- use/undeprecated/undeprecated.go --
+package undeprecated
+
+import _ "example.com/undeprecated"
+-- local/go.mod --
+module local
+
+go 1.17
+
+require example.com/deprecated/b v1.0.0
+-- local/use/use.go --
+package use
+
+import _ "example.com/deprecated/b"
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_downadd_indirect.txt b/libgo/go/cmd/go/testdata/script/mod_get_downadd_indirect.txt
new file mode 100644 (file)
index 0000000..efc38f7
--- /dev/null
@@ -0,0 +1,81 @@
+# This test illustrates a case where downgrading one module may upgrade another.
+# Compare to the downcross2 test case in cmd/go/internal/mvs/mvs_test.go.
+
+# The initial package import graph used in this test looks like:
+#
+# a ---- b ---- d
+#
+# The module dependency graph originally looks like:
+#
+# a ---- b.2 ---- d.2
+#
+# b.1 ---- c.1
+#
+# If we downgrade module d to version 1, we must downgrade b as well.
+# If that downgrade selects b version 1, we will add a new dependency on module c.
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod.orig go.mod
+
+go get -d example.com/d@v0.1.0
+go list -m all
+stdout '^example.com/b v0.1.0 '
+stdout '^example.com/c v0.1.0 '
+stdout '^example.com/d v0.1.0 '
+
+-- go.mod --
+module example.com/a
+
+go 1.15
+
+require example.com/b v0.2.0
+
+replace (
+       example.com/b v0.1.0 => ./b1
+       example.com/b v0.2.0 => ./b2
+       example.com/c v0.1.0 => ./c
+       example.com/d v0.1.0 => ./d
+       example.com/d v0.2.0 => ./d
+)
+-- a.go --
+package a
+
+import _ "example.com/b"
+
+-- b1/go.mod --
+module example.com/b
+
+go 1.15
+
+require example.com/c v0.1.0
+-- b1/b.go --
+package b
+
+import _ "example.com/c"
+
+-- b2/go.mod --
+module example.com/b
+
+go 1.15
+
+require example.com/d v0.2.0
+-- b2/b.go --
+package b
+
+import _ "example.com/d"
+
+-- c/go.mod --
+module example.com/c
+
+go 1.15
+
+-- c/c.go --
+package c
+
+-- d/go.mod --
+module example.com/d
+
+go 1.15
+-- d/d.go --
+package d
index a954c10344bbafd33266e59c8efb4bb0a2115db3..c26c5e1c21013ada363965a4b768d36d921c6552 100644 (file)
@@ -20,8 +20,8 @@ stdout 'rsc.io/quote v1.5.1'
 stdout 'rsc.io/sampler v1.3.0'
 
 ! go get -d rsc.io/sampler@v1.0.0 rsc.io/quote@v1.5.2 golang.org/x/text@none
+stderr -count=1 '^go get:'
 stderr '^go get: rsc.io/quote@v1.5.2 requires rsc.io/sampler@v1.3.0, not rsc.io/sampler@v1.0.0$'
-stderr '^go get: rsc.io/quote@v1.5.2 requires golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c, not golang.org/x/text@none$'
 
 go list -m all
 stdout 'rsc.io/quote v1.5.1'
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_downgrade_missing.txt b/libgo/go/cmd/go/testdata/script/mod_get_downgrade_missing.txt
new file mode 100644 (file)
index 0000000..5b768fa
--- /dev/null
@@ -0,0 +1,43 @@
+cp go.mod go.mod.orig
+
+# getting a specific version of a module along with a pattern
+# not yet present in that module should report the version mismatch
+# rather than a "matched no packages" warning.
+
+! go get -d example.net/pkgadded@v1.1.0 example.net/pkgadded/subpkg/...
+stderr '^go get: example.net/pkgadded@v1.1.0 conflicts with example.net/pkgadded/subpkg/...@upgrade \(v1.2.0\)$'
+! stderr 'matched no packages'
+cmp go.mod.orig go.mod
+
+
+# A wildcard pattern should match the pattern with that path.
+
+go get -d example.net/pkgadded/...@v1.0.0
+go list -m all
+stdout '^example.net/pkgadded v1.0.0'
+cp go.mod.orig go.mod
+
+
+# If we need to resolve a transitive dependency of a package,
+# and another argument constrains away the version that provides that
+# package, then 'go get' should fail with a useful error message.
+
+! go get -d example.net/pkgadded@v1.0.0 .
+stderr '^example.com/m imports\n\texample.net/pkgadded/subpkg: cannot find module providing package example.net/pkgadded/subpkg$'
+! stderr 'example.net/pkgadded v1\.2\.0'
+cmp go.mod.orig go.mod
+
+go get -d example.net/pkgadded@v1.0.0
+! go list -deps -mod=readonly .
+stderr '^m.go:3:8: cannot find module providing package example\.net/pkgadded/subpkg: '
+
+-- go.mod --
+module example.com/m
+
+go 1.16
+
+require example.net/pkgadded v1.2.0
+-- m.go --
+package m
+
+import _ "example.net/pkgadded/subpkg"
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_downup_artifact.txt b/libgo/go/cmd/go/testdata/script/mod_get_downup_artifact.txt
new file mode 100644 (file)
index 0000000..c20583b
--- /dev/null
@@ -0,0 +1,159 @@
+# This test illustrates a case where an upgrade–downgrade–upgrade cycle can
+# result in upgrades of otherwise-irrelevant dependencies.
+#
+# This case has no corresponding test in the mvs package, because it is an
+# artifact that results from the composition of *multiple* MVS operations.
+
+# The initial package import graph used in the test looks like:
+#
+# m ---- a
+# |      |
+# +----- b
+# |      |
+# +----- c
+# |
+# +----- d
+#
+# b version 2 adds its own import of package d.
+#
+# The module dependency graph initially looks like:
+#
+# m ---- a.1
+# |       |
+# +----- b.1
+# |       |
+# +----- c.1
+# |
+# +----- d.1
+#
+# b.2 ---- c.2
+#  |
+#  +------ d.2
+#  |
+#  +------ e.1
+#
+# If we upgrade module b to version 2, we will upgrade c and d and add a new
+# dependency on e. If b version 2 is disallowed because of any of those
+# dependencies, the other dependencies should not be upgraded as a side-effect.
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod go.mod.orig
+
+go list -m all
+stdout '^example.com/a v0.1.0 '
+stdout '^example.com/b v0.1.0 '
+stdout '^example.com/c v0.1.0 '
+stdout '^example.com/d v0.1.0 '
+! stdout '^example.com/e '
+
+# b is imported by a, so the -u flag would normally upgrade it to v0.2.0.
+# However, that would conflict with the explicit c@v0.1.0 constraint,
+# so b must remain at v0.1.0.
+#
+# If we're not careful, we might temporarily add b@v0.2.0 and pull in its
+# upgrades of module d and addition of module e, which are not relevant to
+# b@v0.1.0 and should not be added to the main module's dependencies.
+
+go get -u -d example.com/a@latest example.com/c@v0.1.0
+
+go list -m all
+stdout '^example.com/a v0.1.0 '
+stdout '^example.com/b v0.1.0 '
+stdout '^example.com/c v0.1.0 '
+stdout '^example.com/d v0.1.0 '
+! stdout '^example.com/e '
+
+-- go.mod --
+module example.com/m
+
+go 1.16
+
+require (
+       example.com/a v0.1.0
+       example.com/b v0.1.0
+       example.com/c v0.1.0
+       example.com/d v0.1.0
+)
+
+replace (
+       example.com/a v0.1.0 => ./a1
+       example.com/b v0.1.0 => ./b1
+       example.com/b v0.2.0 => ./b2
+       example.com/c v0.1.0 => ./c
+       example.com/c v0.2.0 => ./c
+       example.com/d v0.1.0 => ./d
+       example.com/d v0.2.0 => ./d
+       example.com/e v0.1.0 => ./e
+)
+-- m.go --
+package m
+
+import (
+       _ "example.com/a"
+       _ "example.com/b"
+       _ "example.com/c"
+       _ "example.com/d"
+)
+
+-- a1/go.mod --
+module example.com/a
+
+go 1.16
+
+require example.com/b v0.1.0
+-- a1/a.go --
+package a
+
+import _ "example.com/b"
+
+-- b1/go.mod --
+module example.com/b
+
+go 1.16
+
+require example.com/c v0.1.0
+-- b1/b.go --
+package b
+
+import _ "example.com/c"
+
+-- b2/go.mod --
+module example.com/b
+
+go 1.16
+
+require (
+       example.com/c v0.2.0
+       example.com/d v0.2.0
+       example.com/e v0.1.0
+)
+-- b2/b.go --
+package b
+
+import (
+       "example.com/c"
+       "example.com/d"
+       "example.com/e"
+)
+
+-- c/go.mod --
+module example.com/c
+
+go 1.16
+-- c/c.go --
+package c
+
+-- d/go.mod --
+module example.com/d
+
+go 1.16
+-- d/d.go --
+package d
+
+-- e/go.mod --
+module example.com/e
+
+go 1.16
+-- e/e.go --
+package e
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_downup_indirect.txt b/libgo/go/cmd/go/testdata/script/mod_get_downup_indirect.txt
new file mode 100644 (file)
index 0000000..ced1dcd
--- /dev/null
@@ -0,0 +1,101 @@
+# This test illustrates a case where downgrading one module may upgrade another.
+# Compare to the downcross1 test case in cmd/go/internal/mvs/mvs_test.go.
+
+# The package import graph used in this test looks like:
+#
+# a ---- b
+#   \     \
+#    \     \
+#     ----- c ---- d
+#
+# The module dependency graph originally looks like:
+#
+# a ---- b.2
+#   \      \
+#    \      \
+#     ----- c.1 ---- d.2
+#
+# b.1 ---- c.2
+#
+# If we downgrade module d to version 1, we must downgrade b as well.
+# If that downgrade selects b version 1, we will upgrade module c to version 2.
+# So 'go get d@1' should instead downgrade both b and c to "none".
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod.orig go.mod
+
+go get -d example.com/d@v0.1.0
+go list -m all
+! stdout '^example.com/b '
+! stdout '^example.com/c '
+stdout '^example.com/d v0.1.0 '
+
+-- go.mod --
+module example.com/a
+
+go 1.15
+
+require (
+       example.com/b v0.2.0
+       example.com/c v0.1.0
+)
+
+replace (
+       example.com/b v0.1.0 => ./b1
+       example.com/b v0.2.0 => ./b2
+       example.com/c v0.1.0 => ./c1
+       example.com/c v0.2.0 => ./c2
+       example.com/d v0.1.0 => ./d
+       example.com/d v0.2.0 => ./d
+)
+-- a.go --
+package a
+
+import (
+       _ "example.com/b"
+       _ "example.com/c"
+)
+
+-- b1/go.mod --
+module example.com/b
+
+go 1.15
+
+require example.com/c v0.2.0
+-- b1/b.go --
+package b
+
+import _ "example.com/c"
+
+-- b2/go.mod --
+module example.com/b
+
+go 1.15
+
+require example.com/c v0.1.0
+-- b2/b.go --
+package b
+
+import _ "example.com/c"
+
+-- c1/go.mod --
+module example.com/c
+
+go 1.15
+
+require example.com/d v0.2.0
+-- c1/c.go --
+package c
+
+-- c2/go.mod --
+module example.com/c
+
+go 1.15
+-- c2/c.go --
+package c
+
+-- d/go.mod --
+module example.com/d
+
+go 1.15
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_downup_pseudo_artifact.txt b/libgo/go/cmd/go/testdata/script/mod_get_downup_pseudo_artifact.txt
new file mode 100644 (file)
index 0000000..c49615c
--- /dev/null
@@ -0,0 +1,129 @@
+# This test illustrates a case where an upgrade–downgrade–upgrade cycle could
+# add extraneous dependencies due to another module depending on an
+# otherwise-unlisted version (such as a pseudo-version).
+#
+# This case corresponds to the "downhiddenartifact" test in the mvs package.
+
+# The initial package import graph used in the test looks like:
+#
+# a --- b
+#  \     \
+#   \     \
+#    c --- d
+#
+# The module dependency graph initially looks like:
+#
+# a --- b.3
+#  \      \
+#   \      \
+#   c.2 --- d.2
+#
+# c.1 --- b.2 (pseudo)
+#
+# b.1 --- e.1
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod.orig go.mod
+
+# When we downgrade d.2 to d.1, no dependency on e should be added
+# because nothing else in the module or import graph requires it.
+go get -d example.net/d@v0.1.0
+
+go list -m all
+stdout '^example.net/b v0.2.1-0.20210219000000-000000000000 '
+stdout '^example.net/c v0.1.0 '
+stdout '^example.net/d v0.1.0 '
+! stdout '^example.net/e '
+
+-- go.mod --
+module example.net/a
+
+go 1.16
+
+require (
+       example.net/b v0.3.0
+       example.net/c v0.2.0
+)
+
+replace (
+       example.net/b v0.1.0 => ./b1
+       example.net/b v0.2.1-0.20210219000000-000000000000 => ./b2
+       example.net/b v0.3.0 => ./b3
+       example.net/c v0.1.0 => ./c1
+       example.net/c v0.2.0 => ./c2
+       example.net/d v0.1.0 => ./d
+       example.net/d v0.2.0 => ./d
+       example.net/e v0.1.0 => ./e
+)
+-- a.go --
+package a
+
+import (
+       _ "example.net/b"
+       _ "example.net/c"
+)
+
+-- b1/go.mod --
+module example.net/b
+
+go 1.16
+
+require example.net/e v0.1.0
+-- b1/b.go --
+package b
+
+import _ "example.net/e"
+
+-- b2/go.mod --
+module example.net/b
+
+go 1.16
+-- b2/b.go --
+package b
+
+-- b3/go.mod --
+module example.net/b
+
+go 1.16
+
+require example.net/d v0.2.0
+-- b3/b.go --
+package b
+
+import _ "example.net/d"
+-- c1/go.mod --
+module example.net/c
+
+go 1.16
+
+require example.net/b v0.2.1-0.20210219000000-000000000000
+-- c1/c.go --
+package c
+
+import _ "example.net/b"
+
+-- c2/go.mod --
+module example.net/c
+
+go 1.16
+
+require example.net/d v0.2.0
+-- c2/c.go --
+package c
+
+import _ "example.net/d"
+
+-- d/go.mod --
+module example.net/d
+
+go 1.16
+-- d/d.go --
+package d
+
+-- e/go.mod --
+module example.net/e
+
+go 1.16
+-- e/e.go --
+package e
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_errors.txt b/libgo/go/cmd/go/testdata/script/mod_get_errors.txt
new file mode 100644 (file)
index 0000000..5c37058
--- /dev/null
@@ -0,0 +1,69 @@
+cp go.mod go.mod.orig
+
+
+# Both 'go get' and 'go get -d' should fail, without updating go.mod,
+# if the transitive dependencies of the requested package (by default,
+# the package in the current directory) cannot be resolved.
+
+! go get
+stderr '^example.com/m imports\n\texample.com/badimport imports\n\texample.net/oops: cannot find module providing package example.net/oops$'
+cmp go.mod.orig go.mod
+
+! go get -d
+stderr '^example.com/m imports\n\texample.com/badimport imports\n\texample.net/oops: cannot find module providing package example.net/oops$'
+cmp go.mod.orig go.mod
+
+cd importsyntax
+
+
+# If 'go get' fails due to a compile error (such as a syntax error),
+# it should not update the go.mod file.
+
+! go get
+stderr '^..[/\\]badimport[/\\]syntaxerror[/\\]syntaxerror.go:1:1: expected ''package'', found pack$'  # TODO: An import stack would be nice.
+cmp ../go.mod.orig ../go.mod
+
+
+# A syntax error in a dependency prevents the compiler from needing that
+# dependency's imports, so 'go get -d' should not report an error when those
+# imports cannot be resolved: it has all of the dependencies that the compiler
+# needs, and the user did not request to run the compiler.
+
+go get -d
+cmp ../go.mod.syntax-d ../go.mod
+
+
+-- go.mod --
+module example.com/m
+
+go 1.16
+
+replace example.com/badimport v0.1.0 => ./badimport
+-- go.mod.syntax-d --
+module example.com/m
+
+go 1.16
+
+replace example.com/badimport v0.1.0 => ./badimport
+
+require example.com/badimport v0.1.0
+-- m.go --
+package m
+
+import _ "example.com/badimport"
+-- importsyntax/importsyntax.go --
+package importsyntax
+
+import _ "example.com/badimport/syntaxerror"
+-- badimport/go.mod --
+module example.com/badimport
+
+go 1.16
+-- badimport/badimport.go --
+package badimport
+
+import "example.net/oops"
+-- badimport/syntaxerror/syntaxerror.go --
+pack-age syntaxerror // sic
+
+import "example.net/oops"
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_extra.txt b/libgo/go/cmd/go/testdata/script/mod_get_extra.txt
new file mode 100644 (file)
index 0000000..7efa24e
--- /dev/null
@@ -0,0 +1,69 @@
+cp go.mod go.mod.orig
+
+# The -u flag should not (even temporarily) upgrade modules whose versions are
+# determined by explicit queries to any version other than the explicit one.
+# Otherwise, 'go get -u' could introduce spurious dependencies.
+
+go get -d -u example.net/a@v0.1.0 example.net/b@v0.1.0
+go list -m all
+stdout '^example.net/a v0.1.0 '
+stdout '^example.net/b v0.1.0 '
+! stdout '^example.net/c '
+
+
+# TODO(bcmills): This property does not yet hold for modules added for
+# missing packages when the newly-added module matches a wildcard.
+
+cp go.mod.orig go.mod
+
+go get -d -u example.net/a@v0.1.0 example.net/b/...@v0.1.0
+go list -m all
+stdout '^example.net/a v0.1.0 '
+stdout '^example.net/b v0.1.0 '
+stdout '^example.net/c '  # BUG, but a minor and rare one
+
+
+-- go.mod --
+module example
+
+go 1.15
+
+replace (
+       example.net/a v0.1.0 => ./a1
+       example.net/b v0.1.0 => ./b1
+       example.net/b v0.2.0 => ./b2
+       example.net/c v0.1.0 => ./c1
+       example.net/c v0.2.0 => ./c1
+)
+
+-- a1/go.mod --
+module example.net/a
+
+go 1.15
+
+// example.net/a needs a dependency on example.net/b, but lacks a requirement
+// on it (perhaps due to a missed file in a VCS commit).
+-- a1/a.go --
+package a
+import _ "example.net/b"
+
+-- b1/go.mod --
+module example.net/b
+
+go 1.15
+-- b1/b.go --
+package b
+
+-- b2/go.mod --
+module example.net/b
+
+go 1.15
+
+require example.net/c v0.1.0
+-- b2/b.go --
+package b
+
+-- c1/go.mod --
+module example.net/c
+
+go 1.15
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_fossil.txt b/libgo/go/cmd/go/testdata/script/mod_get_fossil.txt
new file mode 100644 (file)
index 0000000..baad544
--- /dev/null
@@ -0,0 +1,29 @@
+[!net] skip
+[!exec:fossil] skip
+
+# Regression test for 'go get' to ensure repositories
+# provided by fossil v2.12 and up are able to be fetched
+# and parsed correctly.
+# Verifies golang.org/issue/42323.
+
+
+env GO111MODULE=on
+env GOPROXY=direct
+env GOSUMDB=off
+
+# 'go get' for the fossil repo will fail if fossil
+# is unable to determine your fossil user. Easiest
+# way to set it for use by 'go get' is specifying
+# a any non-empty $USER; the value doesn't otherwise matter.
+env USER=fossiluser
+env FOSSIL_HOME=$WORK/home
+
+# Attempting to get the latest version of a fossil repo.
+go get vcs-test.golang.org/fossil/hello.fossil
+! stderr 'unexpected response from fossil info'
+grep 'vcs-test.golang.org/fossil/hello.fossil' go.mod
+exists $GOPATH/bin/hello.fossil$GOEXE
+
+-- go.mod --
+module x
+-- $WORK/home/.fossil --
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_go_file.txt b/libgo/go/cmd/go/testdata/script/mod_get_go_file.txt
new file mode 100644 (file)
index 0000000..0c7b5dc
--- /dev/null
@@ -0,0 +1,68 @@
+# Tests Issue #38478
+# Tests that go get in GOMOD mode returns a specific error if the argument
+# ends with '.go', has no version, and either has no slash or refers to an
+# existing file.
+
+env GO111MODULE=on
+
+# argument doesn't have .go suffix and has no version
+! go get test
+! stderr 'arguments must be package or module paths'
+! stderr 'exists as a file, but ''go get'' requires package arguments'
+
+# argument has .go suffix and has version
+! go get test.go@v1.0.0
+! stderr 'arguments must be package or module paths'
+! stderr 'exists as a file, but ''go get'' requires package arguments'
+
+# argument has .go suffix, is a file and exists
+! go get test.go
+stderr 'go get test.go: arguments must be package or module paths'
+
+# argument has .go suffix, doesn't exist and has no slashes
+! go get test_missing.go
+stderr 'arguments must be package or module paths'
+
+# argument has .go suffix, is a file and exists in sub-directory
+! go get test/test.go
+stderr 'go get: test/test.go exists as a file, but ''go get'' requires package arguments'
+
+# argument has .go suffix, doesn't exist and has slashes
+! go get test/test_missing.go
+! stderr 'arguments must be package or module paths'
+! stderr 'exists as a file, but ''go get'' requires package arguments'
+
+# argument has .go suffix, is a symlink and exists
+[symlink] symlink test_sym.go -> test.go
+[symlink] ! go get test_sym.go
+[symlink] stderr 'go get test_sym.go: arguments must be package or module paths'
+[symlink] rm test_sym.go
+
+# argument has .go suffix, is a symlink and exists in sub-directory
+[symlink] symlink test/test_sym.go -> test.go
+[symlink] ! go get test/test_sym.go
+[symlink] stderr 'go get: test/test_sym.go exists as a file, but ''go get'' requires package arguments'
+[symlink] rm test_sym.go
+
+# argument has .go suffix, is a directory and exists
+mkdir test_dir.go
+! go get test_dir.go
+stderr 'go get test_dir.go: arguments must be package or module paths'
+rm test_dir.go
+
+# argument has .go suffix, is a directory and exists in sub-directory
+mkdir test/test_dir.go
+! go get test/test_dir.go
+! stderr 'arguments must be package or module paths'
+! stderr 'exists as a file, but ''go get'' requires package arguments'
+rm test/test_dir.go
+
+
+-- test.go --
+package main
+func main() {println("test")}
+
+
+-- test/test.go --
+package main
+func main() {println("test")}
index 3755f1763321e66a41cc0b04dcc6b66296404dd7..2e1283449554072c43509f293f8e64c11221e30d 100644 (file)
@@ -1,4 +1,4 @@
-# golang.org/issue/29591: 'go get' was following plain-HTTP redirects even without -insecure.
+# golang.org/issue/29591: 'go get' was following plain-HTTP redirects even without -insecure (now replaced by GOINSECURE).
 
 [!net] skip
 [!exec:git] skip
@@ -10,8 +10,6 @@ env GOSUMDB=off
 ! go get -d vcs-test.golang.org/insecure/go/insecure
 stderr 'redirected .* to insecure URL'
 
-go get -d -insecure vcs-test.golang.org/insecure/go/insecure
-
 # insecure host
 env GOINSECURE=vcs-test.golang.org
 go clean -modcache
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_issue37438.txt b/libgo/go/cmd/go/testdata/script/mod_get_issue37438.txt
new file mode 100644 (file)
index 0000000..38b2031
--- /dev/null
@@ -0,0 +1,37 @@
+# Regression test for https://golang.org/issue/37438.
+#
+# If a path exists at the requested version, but does not exist at the
+# version of the module that is already required and does not exist at
+# the version that would be selected by 'go mod tidy', then
+# 'go get foo@requested' should resolve the requested version,
+# not error out on the (unrelated) latest one.
+
+go get -d example.net/a/p@v0.2.0
+
+-- go.mod --
+module example
+
+go 1.15
+
+require example.net/a v0.1.0
+
+replace (
+       example.net/a v0.1.0 => ./a1
+       example.net/a v0.2.0 => ./a2
+       example.net/a v0.3.0 => ./a1
+)
+
+-- a1/go.mod --
+module example.net/a
+
+go 1.15
+-- a1/README --
+package example.net/a/p does not exist at this version.
+
+-- a2/go.mod --
+module example.net/a
+
+go 1.15
+-- a2/p/p.go --
+// Package p exists only at v0.2.0.
+package p
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_lazy_indirect.txt b/libgo/go/cmd/go/testdata/script/mod_get_lazy_indirect.txt
new file mode 100644 (file)
index 0000000..1cef9d1
--- /dev/null
@@ -0,0 +1,44 @@
+# https://golang.org/issue/45979: after 'go get' on a package,
+# that package should be importable without error.
+
+
+# We start out with an unresolved dependency.
+# 'go list' suggests that we run 'go get' on that dependency.
+
+! go list -deps .
+stderr '^m.go:3:8: no required module provides package rsc\.io/quote; to add it:\n\tgo get rsc.io/quote$'
+
+
+# When we run the suggested 'go get' command, the new dependency can be used
+# immediately.
+#
+# 'go get' marks the new dependency as 'indirect', because it doesn't scan
+# enough source code to know whether it is direct, and it is easier and less
+# invasive to remove an incorrect indirect mark (e.g. using 'go get') than to
+# add one that is missing ('go mod tidy' or 'go mod vendor').
+
+go get rsc.io/quote
+grep 'rsc.io/quote v\d+\.\d+\.\d+ // indirect$' go.mod
+! grep 'rsc.io/quote v\d+\.\d+\.\d+$' go.mod
+
+go list -deps .
+! stderr .
+[!short] go build .
+[!short] ! stderr .
+
+
+# 'go get .' (or 'go mod tidy') removes the indirect mark.
+
+go get .
+grep 'rsc.io/quote v\d+\.\d+\.\d+$' go.mod
+! grep 'rsc.io/quote v\d+\.\d+\.\d+ // indirect$' go.mod
+
+
+-- go.mod --
+module example.com/m
+
+go 1.17
+-- m.go --
+package m
+
+import _ "rsc.io/quote"
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_missing_ziphash.txt b/libgo/go/cmd/go/testdata/script/mod_get_missing_ziphash.txt
new file mode 100644 (file)
index 0000000..789d42d
--- /dev/null
@@ -0,0 +1,55 @@
+# Test that if the module cache contains an extracted source directory but not
+# a ziphash, 'go build' complains about a missing sum, and 'go get' adds
+# the sum. Verifies #44749.
+
+# With a tidy go.sum, go build succeeds. This also populates the module cache.
+cp go.sum.tidy go.sum
+go build -n use
+env GOPROXY=off
+env GOSUMDB=off
+
+# Control case: if we delete the hash for rsc.io/quote v1.5.2,
+# 'go build' reports an error. 'go get' adds the sum.
+cp go.sum.bug go.sum
+! go build -n use
+stderr '^use.go:3:8: missing go.sum entry for module providing package rsc.io/quote \(imported by use\); to add:\n\tgo get use$'
+go get -d use
+cmp go.sum go.sum.tidy
+go build -n use
+
+# If we delete the hash *and* the ziphash file, we should see the same behavior.
+cp go.sum.bug go.sum
+rm $WORK/gopath/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.ziphash
+! go build -n use
+stderr '^use.go:3:8: missing go.sum entry for module providing package rsc.io/quote \(imported by use\); to add:\n\tgo get use$'
+go get -d use
+cmp go.sum go.sum.tidy
+go build -n use
+
+-- go.mod --
+module use
+
+go 1.16
+
+require rsc.io/quote v1.5.2
+-- go.sum.tidy --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64=
+rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY=
+-- go.sum.bug --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64=
+rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY=
+-- use.go --
+package use
+
+import _ "rsc.io/quote"
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_nopkgs.txt b/libgo/go/cmd/go/testdata/script/mod_get_nopkgs.txt
new file mode 100644 (file)
index 0000000..078e71a
--- /dev/null
@@ -0,0 +1,40 @@
+cd subdir
+
+# 'go get' on empty patterns that are necessarily local to the module
+# should warn that the patterns are empty, exactly once.
+
+go get ./...
+stderr -count=1 'matched no packages'
+
+go get -d ./...
+stderr -count=1 'matched no packages'
+
+# 'go get' on patterns that could conceivably match nested modules
+# should report a module resolution error.
+
+go get -d example.net/emptysubdir/... # control case
+
+! go get -d example.net/emptysubdir/subdir/...
+! stderr 'matched no packages'
+stderr '^go get example\.net/emptysubdir/subdir/\.\.\.: module example\.net/emptysubdir/subdir: reading http://.*: 404 Not Found\n\tserver response: 404 page not found\n\z'
+
+# It doesn't make sense to 'go get' a path in the standard library,
+# since the standard library necessarily can't have unresolved imports.
+#
+# TODO(#30241): Maybe that won't always be the case?
+#
+# For that case, we emit a "malformed module path" error message,
+# which isn't ideal either.
+
+! go get -d builtin/...  # in GOROOT/src, but contains no packages
+stderr '^go get builtin/...: malformed module path "builtin": missing dot in first path element$'
+
+-- go.mod --
+module example.net/emptysubdir
+
+go 1.16
+-- emptysubdir.go --
+// Package emptysubdir has a subdirectory containing no packages.
+package emptysubdir
+-- subdir/README.txt --
+This module intentionally does not contain any p
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_patch.txt b/libgo/go/cmd/go/testdata/script/mod_get_patch.txt
new file mode 100644 (file)
index 0000000..053ef62
--- /dev/null
@@ -0,0 +1,130 @@
+# This test examines the behavior of 'go get …@patch'
+# See also mod_upgrade_patch.txt (focused on "-u=patch" specifically)
+# and mod_get_patchmod.txt (focused on module/package ambiguities).
+
+cp go.mod go.mod.orig
+
+# example.net/b@patch refers to the patch for the version of b that was selected
+# at the start of 'go get', not the version after applying other changes.
+
+! go get -d example.net/a@v0.2.0 example.net/b@patch
+stderr '^go get: example.net/a@v0.2.0 requires example.net/b@v0.2.0, not example.net/b@patch \(v0.1.1\)$'
+cmp go.mod go.mod.orig
+
+
+# -u=patch changes the default version for other arguments to '@patch',
+# but they continue to be resolved against the originally-selected version,
+# not the updated one.
+#
+# TODO(#42360): Reconsider the change in defaults.
+
+! go get -d -u=patch example.net/a@v0.2.0 example.net/b
+stderr '^go get: example.net/a@v0.2.0 requires example.net/b@v0.2.0, not example.net/b@patch \(v0.1.1\)$'
+cmp go.mod go.mod.orig
+
+
+# -u=patch refers to the patches for the selected versions of dependencies *after*
+# applying other version changes, not the versions that were selected at the start.
+# However, it should not patch versions determined by explicit arguments.
+
+go get -d -u=patch example.net/a@v0.2.0
+go list -m all
+stdout '^example.net/a v0.2.0 '
+stdout '^example.net/b v0.2.1 '
+
+
+# "-u=patch all" should be equivalent to "all@patch", and should fail if the
+# patched versions result in a higher-than-patch upgrade.
+
+cp go.mod.orig go.mod
+! go get -u=patch all
+stderr '^go get: example.net/a@v0.1.1 \(matching all@patch\) requires example.net/b@v0.2.0, not example.net/b@v0.1.1 \(matching all@patch\)$'
+cmp go.mod go.mod.orig
+
+
+# On the other hand, "-u=patch ./..." should patch-upgrade dependencies until
+# they reach a fixed point, even if that results in higher-than-patch upgrades.
+
+go get -u=patch ./...
+go list -m all
+stdout '^example.net/a v0.1.1 '
+stdout '^example.net/b v0.2.1 '
+
+
+-- go.mod --
+module example
+
+go 1.16
+
+require (
+       example.net/a v0.1.0
+       example.net/b v0.1.0  // indirect
+)
+
+replace (
+       example.net/a v0.1.0 => ./a10
+       example.net/a v0.1.1 => ./a11
+       example.net/a v0.2.0 => ./a20
+       example.net/a v0.2.1 => ./a21
+       example.net/b v0.1.0 => ./b
+       example.net/b v0.1.1 => ./b
+       example.net/b v0.2.0 => ./b
+       example.net/b v0.2.1 => ./b
+       example.net/b v0.3.0 => ./b
+       example.net/b v0.3.1 => ./b
+)
+-- example.go --
+package example
+
+import _ "example.net/a"
+
+-- a10/go.mod --
+module example.net/a
+
+go 1.16
+
+require example.net/b v0.1.0
+-- a10/a.go --
+package a
+
+import _ "example.net/b"
+
+-- a11/go.mod --
+module example.net/a
+
+go 1.16
+
+require example.net/b v0.2.0  // upgraded
+-- a11/a.go --
+package a
+
+import _ "example.net/b"
+
+-- a20/go.mod --
+module example.net/a
+
+go 1.16
+
+require example.net/b v0.2.0
+-- a20/a.go --
+package a
+
+import _ "example.net/b"
+
+-- a21/go.mod --
+module example.net/a
+
+go 1.16
+
+require example.net/b v0.2.0  // not upgraded
+-- a21/a.go --
+package a
+
+import _ "example.net/b"
+
+-- b/go.mod --
+module example.net/b
+
+go 1.16
+-- b/b.go --
+package b
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_patchbound.txt b/libgo/go/cmd/go/testdata/script/mod_get_patchbound.txt
new file mode 100644 (file)
index 0000000..4fd1ec5
--- /dev/null
@@ -0,0 +1,84 @@
+# -u=patch will patch dependencies as far as possible, but not so far that they
+# conflict with other command-line arguments.
+
+go list -m all
+stdout '^example.net/a v0.1.0 '
+stdout '^example.net/b v0.1.0 '
+
+go get -d -u=patch example.net/a@v0.2.0
+go list -m all
+stdout '^example.net/a v0.2.0 '
+stdout '^example.net/b v0.1.1 '  # not v0.1.2, which requires …/a v0.3.0.
+
+-- go.mod --
+module example
+
+go 1.16
+
+require (
+       example.net/a v0.1.0
+       example.net/b v0.1.0 // indirect
+)
+
+replace (
+       example.net/a v0.1.0 => ./a
+       example.net/a v0.2.0 => ./a
+       example.net/a v0.3.0 => ./a
+       example.net/b v0.1.0 => ./b10
+       example.net/b v0.1.1 => ./b11
+       example.net/b v0.1.2 => ./b12
+)
+-- example.go --
+package example
+
+import _ "example.net/a"
+
+-- a/go.mod --
+module example.net/a
+
+go 1.16
+
+require example.net/b v0.1.0
+-- a/a.go --
+package a
+
+import _ "example.net/b"
+
+-- b10/go.mod --
+module example.net/b
+
+go 1.16
+
+require example.net/a v0.1.0
+-- b10/b.go --
+package b
+-- b10/b_test.go --
+package b_test
+
+import _ "example.net/a"
+
+-- b11/go.mod --
+module example.net/b
+
+go 1.16
+
+require example.net/a v0.2.0
+-- b11/b.go --
+package b
+-- b11/b_test.go --
+package b_test
+
+import _ "example.net/a"
+
+-- b12/go.mod --
+module example.net/b
+
+go 1.16
+
+require example.net/a v0.3.0
+-- b12/b.go --
+package b
+-- b12/b_test.go --
+package b_test
+
+import _ "example.net/a"
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_patchcycle.txt b/libgo/go/cmd/go/testdata/script/mod_get_patchcycle.txt
new file mode 100644 (file)
index 0000000..d1db56f
--- /dev/null
@@ -0,0 +1,64 @@
+# If a patch of a module requires a higher version of itself,
+# it should be reported as its own conflict.
+#
+# This case is weird and unlikely to occur often at all, but it should not
+# spuriously succeed.
+# (It used to print v0.1.1 but then silently upgrade to v0.2.0.)
+
+! go get example.net/a@patch
+stderr '^go get: example.net/a@patch \(v0.1.1\) requires example.net/a@v0.2.0, not example.net/a@patch \(v0.1.1\)$'  # TODO: A mention of b v0.1.0 would be nice.
+
+-- go.mod --
+module example
+
+go 1.16
+
+require example.net/a v0.1.0
+
+replace (
+       example.net/a v0.1.0 => ./a10
+       example.net/a v0.1.1 => ./a11
+       example.net/a v0.2.0 => ./a20
+       example.net/b v0.1.0 => ./b10
+)
+-- example.go --
+package example
+
+import _ "example.net/a"
+
+-- a10/go.mod --
+module example.net/a
+
+go 1.16
+-- a10/a.go --
+package a
+
+-- a11/go.mod --
+module example.net/a
+
+go 1.16
+
+require example.net/b v0.1.0
+-- a11/a.go --
+package a
+
+import _ "example.net/b"
+
+-- a20/go.mod --
+module example.net/a
+
+go 1.16
+-- a20/a.go --
+package a
+
+
+-- b10/go.mod --
+module example.net/b
+
+go 1.16
+
+require example.net/a v0.2.0
+-- b10/b.go --
+package b
+
+import _ "example.net/a"
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_patchmod.txt b/libgo/go/cmd/go/testdata/script/mod_get_patchmod.txt
new file mode 100644 (file)
index 0000000..e39d13a
--- /dev/null
@@ -0,0 +1,82 @@
+# example.net/pkgremoved@v0.1.0 refers to a package.
+go get -d example.net/pkgremoved@v0.1.0
+
+go list example.net/pkgremoved
+stdout '^example.net/pkgremoved'
+
+cp go.mod go.mod.orig
+
+
+# When we resolve a new dependency on example.net/other,
+# it will change the meaning of the path "example.net/pkgremoved"
+# from a package (at v0.1.0) to only a module (at v0.2.0).
+#
+# If we simultaneously 'get' that module at the query "patch", the module should
+# be constrained to the latest patch of its originally-selected version (v0.1.0),
+# not upgraded to the latest patch of the new transitive dependency.
+
+! go get -d example.net/pkgremoved@patch example.net/other@v0.1.0
+stderr '^go get: example.net/other@v0.1.0 requires example.net/pkgremoved@v0.2.0, not example.net/pkgremoved@patch \(v0.1.1\)$'
+cmp go.mod.orig go.mod
+
+
+# However, we should be able to patch from a package to a module and vice-versa.
+
+# Package to module ...
+
+go get -d example.net/pkgremoved@v0.3.0
+go list example.net/pkgremoved
+stdout 'example.net/pkgremoved'
+
+go get -d example.net/pkgremoved@patch
+! go list example.net/pkgremoved
+
+# ... and module to package.
+
+go get -d example.net/pkgremoved@v0.4.0
+! go list example.net/pkgremoved
+
+go get -d example.net/pkgremoved@patch
+go list example.net/pkgremoved
+stdout 'example.net/pkgremoved'
+
+
+-- go.mod --
+module example
+
+go 1.16
+
+replace (
+       example.net/other v0.1.0 => ./other
+
+       example.net/pkgremoved v0.1.0 => ./prpkg
+       example.net/pkgremoved v0.1.1 => ./prpkg
+
+       example.net/pkgremoved v0.2.0 => ./prmod
+       example.net/pkgremoved v0.2.1 => ./prmod
+
+       example.net/pkgremoved v0.3.0 => ./prpkg
+       example.net/pkgremoved v0.3.1 => ./prmod
+
+       example.net/pkgremoved v0.4.0 => ./prmod
+       example.net/pkgremoved v0.4.1 => ./prpkg
+)
+-- other/go.mod --
+module example.net/other
+
+go 1.16
+
+require example.net/pkgremoved v0.2.0
+-- other/other.go --
+package other
+-- prpkg/go.mod --
+module example.net/pkgremoved
+
+go 1.16
+-- prpkg/pkgremoved.go --
+package pkgremoved
+-- prmod/go.mod --
+module example.net/pkgremoved
+-- prmod/README.txt --
+Package pkgremoved was removed in v0.2.0 and v0.3.1,
+and added in v0.1.0 and v0.4.1.
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_pkgtags.txt b/libgo/go/cmd/go/testdata/script/mod_get_pkgtags.txt
new file mode 100644 (file)
index 0000000..0c79ec7
--- /dev/null
@@ -0,0 +1,130 @@
+# https://golang.org/issue/44106
+# 'go get' should fetch the transitive dependencies of packages regardless of
+# tags, but shouldn't error out if the package is missing tag-guarded
+# dependencies.
+
+# Control case: just adding the top-level module to the go.mod file does not
+# fetch its dependencies.
+
+go mod edit -require example.net/tools@v0.1.0
+! go list -deps example.net/cmd/tool
+stderr '^module example\.net/cmd provides package example\.net/cmd/tool and is replaced but not required; to add it:\n\tgo get example\.net/cmd@v0\.1\.0$'
+go mod edit -droprequire example.net/tools
+
+
+# 'go get -d' makes a best effort to fetch those dependencies, but shouldn't
+# error out if dependencies of tag-guarded files are missing.
+
+go get -d example.net/tools@v0.1.0
+! stderr 'no Go source files'
+
+! go list example.net/tools
+stderr '^package example.net/tools: build constraints exclude all Go files in .*[/\\]tools$'
+
+go list -tags=tools -e -deps example.net/tools
+stdout '^example.net/cmd/tool$'
+stdout '^example.net/missing$'
+
+go list -deps example.net/cmd/tool
+
+! go list example.net/missing
+stderr '^no required module provides package example.net/missing; to add it:\n\tgo get example.net/missing$'
+
+
+# https://golang.org/issue/33526: 'go get' without '-d' should succeed
+# for a module whose root is a constrained-out package.
+#
+# Ideally it should silently succeed, but today it logs the "no Go source files"
+# error and succeeds anyway.
+
+go get example.net/tools@v0.1.0
+! stderr .
+
+! go build example.net/tools
+stderr '^package example.net/tools: build constraints exclude all Go files in .*[/\\]tools$'
+
+
+# https://golang.org/issue/29268
+# 'go get' should fetch modules whose roots contain test-only packages, but
+# without the -t flag shouldn't error out if the test has missing dependencies.
+
+go get -d example.net/testonly@v0.1.0
+
+# With the -t flag, the test dependencies must resolve successfully.
+! go get -d -t example.net/testonly@v0.1.0
+stderr '^example.net/testonly tested by\n\texample.net/testonly\.test imports\n\texample.net/missing: cannot find module providing package example.net/missing$'
+
+
+# 'go get -d' should succeed for a module path that does not contain a package,
+# but fail for a non-package subdirectory of a module.
+
+! go get -d example.net/missing/subdir@v0.1.0
+stderr '^go get: module example.net/missing@v0.1.0 found \(replaced by ./missing\), but does not contain package example.net/missing/subdir$'
+
+go get -d example.net/missing@v0.1.0
+
+
+# Getting the subdirectory should continue to fail even if the corresponding
+# module is already present in the build list.
+
+! go get -d example.net/missing/subdir@v0.1.0
+stderr '^go get: module example.net/missing@v0.1.0 found \(replaced by ./missing\), but does not contain package example.net/missing/subdir$'
+
+
+-- go.mod --
+module example.net/m
+
+go 1.15
+
+replace (
+       example.net/tools v0.1.0 => ./tools
+       example.net/cmd v0.1.0 => ./cmd
+       example.net/testonly v0.1.0 => ./testonly
+       example.net/missing v0.1.0 => ./missing
+)
+
+-- tools/go.mod --
+module example.net/tools
+
+go 1.15
+
+// Requirements intentionally omitted.
+
+-- tools/tools.go --
+// +build tools
+
+package tools
+
+import (
+       _ "example.net/cmd/tool"
+       _ "example.net/missing"
+)
+
+-- cmd/go.mod --
+module example.net/cmd
+
+go 1.16
+-- cmd/tool/tool.go --
+package main
+
+func main() {}
+
+-- testonly/go.mod --
+module example.net/testonly
+
+go 1.15
+-- testonly/testonly_test.go --
+package testonly_test
+
+import _ "example.net/missing"
+
+func Test(t *testing.T) {}
+
+-- missing/go.mod --
+module example.net/missing
+
+go 1.15
+-- missing/README.txt --
+There are no Go source files here.
+-- missing/subdir/README.txt --
+There are no Go source files here either.
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_prefer_incompatible.txt b/libgo/go/cmd/go/testdata/script/mod_get_prefer_incompatible.txt
new file mode 100644 (file)
index 0000000..be3db42
--- /dev/null
@@ -0,0 +1,29 @@
+# Verifies golang.org/issue/37574.
+
+# If we are already using an +incompatible version, we shouldn't look up
+# a lower compatible version when upgrading.
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod.orig go.mod
+grep '^example.com/incompatiblewithsub v2\.0\.0\+incompatible' go.sum
+! grep '^example.com/incompatiblewithsub v1.0.0' go.sum
+
+go get -d example.com/incompatiblewithsub/sub
+cmp go.mod.orig go.mod
+! grep '^example.com/incompatiblewithsub v1.0.0' go.sum
+
+# TODO(golang.org/issue/31580): the 'go get' command above should not change
+# go.sum. However, as part of the query above, we download example.com@v1.0.0,
+# an unrelated module, since it's a possible prefix. The sum for that module
+# should not be written to go.sum.
+
+-- go.mod --
+module m
+
+go 1.15
+
+require example.com/incompatiblewithsub v2.0.0+incompatible
+-- use.go --
+package use
+
+import _ "example.com/incompatiblewithsub/sub"
index 514b0a7a5314df19b2b8d0d25610858a1d40f0c2..75c776a7fa29c78d1856d381fa2a938b15348034 100644 (file)
@@ -9,3 +9,35 @@ env GOPROXY=direct
 stderr 'Confirm the import path was entered correctly.'
 stderr 'If this is a private repository, see https://golang.org/doc/faq#git_https for additional information.'
 ! stdout .
+
+# Fetching a nonexistent commit should return an "unknown revision"
+# error message.
+! go get github.com/golang/term@86186f3aba07ed0212cfb944f3398997d2d07c6b
+stderr '^go get: github.com/golang/term@86186f3aba07ed0212cfb944f3398997d2d07c6b: invalid version: unknown revision 86186f3aba07ed0212cfb944f3398997d2d07c6b$'
+! stdout .
+
+! go get github.com/golang/nonexist@master
+stderr '^Confirm the import path was entered correctly.$'
+stderr '^If this is a private repository, see https://golang.org/doc/faq#git_https for additional information.$'
+! stderr 'unknown revision'
+! stdout .
+
+[!linux] stop  # Needs XDG_CONFIG_HOME.
+[!exec:false] stop
+
+# Test that Git clone errors will be shown to the user instead of a generic
+# "unknown revision" error. To do this we want to force git ls-remote to return
+# an error we don't already have special handling for. See golang/go#42751.
+#
+# Set XDG_CONFIG_HOME to tell Git where to look for the git config file listed
+# below, which turns on ssh.
+env XDG_CONFIG_HOME=$TMPDIR
+env GIT_SSH_COMMAND=false
+! go install github.com/golang/nonexist@master
+stderr 'fatal: Could not read from remote repository.'
+! stderr 'unknown revision'
+! stdout .
+
+-- $TMPDIR/git/config --
+[url "git@github.com:"]
+    insteadOf = https://github.com/
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_promote_implicit.txt b/libgo/go/cmd/go/testdata/script/mod_get_promote_implicit.txt
new file mode 100644 (file)
index 0000000..9eec201
--- /dev/null
@@ -0,0 +1,92 @@
+cp go.mod.orig go.mod
+
+# If we list a package in an implicit dependency imported from the main module,
+# we should get an error because the dependency should have an explicit
+# requirement.
+go list -m indirect-with-pkg
+stdout '^indirect-with-pkg v1.0.0 => ./indirect-with-pkg$'
+! go list ./use-indirect
+stderr '^package m/use-indirect imports indirect-with-pkg from implicitly required module; to add missing requirements, run:\n\tgo get indirect-with-pkg@v1.0.0$'
+
+# We can promote the implicit requirement by getting the importing package.
+# NOTE: the hint recommends getting the imported package (tested below) since
+# it's more obvious and doesn't require -d. However, that adds an '// indirect'
+# comment on the requirement.
+go get -d m/use-indirect
+cmp go.mod go.mod.use
+cp go.mod.orig go.mod
+
+# We can also promote implicit requirements using 'go get' on them, or their
+# packages. This gives us "// indirect" requirements, since 'go get' doesn't
+# know they're needed by the main module. See #43131 for the rationale.
+# The hint above recommends this because it's more obvious usage and doesn't
+# require the -d flag.
+go get -d indirect-with-pkg indirect-without-pkg
+cmp go.mod go.mod.indirect
+
+-- go.mod.orig --
+module m
+
+go 1.16
+
+require direct v1.0.0
+
+replace (
+       direct v1.0.0 => ./direct
+       indirect-with-pkg v1.0.0 => ./indirect-with-pkg
+       indirect-without-pkg v1.0.0 => ./indirect-without-pkg
+)
+-- go.mod.use --
+module m
+
+go 1.16
+
+require (
+       direct v1.0.0
+       indirect-with-pkg v1.0.0
+)
+
+replace (
+       direct v1.0.0 => ./direct
+       indirect-with-pkg v1.0.0 => ./indirect-with-pkg
+       indirect-without-pkg v1.0.0 => ./indirect-without-pkg
+)
+-- go.mod.indirect --
+module m
+
+go 1.16
+
+require (
+       direct v1.0.0
+       indirect-with-pkg v1.0.0 // indirect
+       indirect-without-pkg v1.0.0 // indirect
+)
+
+replace (
+       direct v1.0.0 => ./direct
+       indirect-with-pkg v1.0.0 => ./indirect-with-pkg
+       indirect-without-pkg v1.0.0 => ./indirect-without-pkg
+)
+-- use-indirect/use-indirect.go --
+package use
+
+import _ "indirect-with-pkg"
+-- direct/go.mod --
+module direct
+
+go 1.16
+
+require (
+       indirect-with-pkg v1.0.0
+       indirect-without-pkg v1.0.0
+)
+-- indirect-with-pkg/go.mod --
+module indirect-with-pkg
+
+go 1.16
+-- indirect-with-pkg/p.go --
+package p
+-- indirect-without-pkg/go.mod --
+module indirect-without-pkg
+
+go 1.16
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_replaced.txt b/libgo/go/cmd/go/testdata/script/mod_get_replaced.txt
new file mode 100644 (file)
index 0000000..d97f3f1
--- /dev/null
@@ -0,0 +1,111 @@
+cp go.mod go.mod.orig
+
+env oldGOPROXY=$GOPROXY
+
+# If a wildcard replacement exists for an otherwise-nonexistent module,
+# 'go get' should resolve it to the minimum valid pseudo-version.
+
+go mod edit -replace=example.com/x=./x
+go get -d example.com/x
+
+go list -m example.com/x
+stdout '^example.com/x v0.0.0-00010101000000-000000000000 '
+
+# If specific-version replacements exist, the highest matching version should be used.
+go mod edit -replace=example.com/x@v0.1.0=./x
+go mod edit -replace=example.com/x@v0.2.0=./x
+
+go get -d example.com/x
+go list -m example.com/x
+stdout '^example.com/x v0.2.0 '
+
+go get -d example.com/x@<v0.2.0
+go list -m example.com/x
+stdout '^example.com/x v0.1.0 '
+
+
+# The same should work with GOPROXY=off.
+
+env GOPROXY=off
+cp go.mod.orig go.mod
+
+go mod edit -replace=example.com/x=./x
+go get -d example.com/x
+
+go list -m example.com/x
+stdout '^example.com/x v0.0.0-00010101000000-000000000000 '
+
+# If specific-version replacements exist, the highest matching version should be used.
+go mod edit -replace=example.com/x@v0.1.0=./x
+go mod edit -replace=example.com/x@v0.2.0=./x
+
+go get -d example.com/x
+go list -m example.com/x
+stdout '^example.com/x v0.2.0 '
+
+go get -d example.com/x@<v0.2.0
+go list -m example.com/x
+stdout '^example.com/x v0.1.0 '
+
+
+# Replacements should also be listed as known versions, and 'go get' should sort
+# them in with ordinary versions.
+
+env GOPROXY=$oldGOPROXY
+
+cp go.mod.orig go.mod
+go list -versions -m rsc.io/quote
+stdout 'v1.3.0 v1.4.0'
+
+go get -d rsc.io/quote@v1.3
+go list -m rsc.io/quote
+stdout '^rsc.io/quote v1.3.0'
+
+go mod edit -replace rsc.io/quote@v1.3.1=rsc.io/quote@v1.4.0
+
+go list -versions -m rsc.io/quote
+stdout 'v1.3.0 v1.3.1 v1.4.0'
+
+go get -d rsc.io/quote@v1.3
+go list -m rsc.io/quote
+stdout '^rsc.io/quote v1.3.1 '
+
+go get -d rsc.io/quote@>v1.3.1
+go list -m rsc.io/quote
+stdout '^rsc.io/quote v1.4.0'
+
+
+# Replacements should allow 'go get' to work even with dotless module paths.
+
+cp go.mod.orig go.mod
+
+! go list example
+stderr '^package example is not in GOROOT \(.*\)$'
+! go get -d example
+stderr '^go get: malformed module path "example": missing dot in first path element$'
+
+go mod edit -replace example@v0.1.0=./example
+
+! go list example
+stderr '^module example provides package example and is replaced but not required; to add it:\n\tgo get example@v0.1.0$'
+
+go get -d example
+go list -m example
+stdout '^example v0.1.0 '
+
+
+-- go.mod --
+module example.com
+
+go 1.16
+-- x/go.mod --
+module example.com/x
+
+go 1.16
+-- x/x.go --
+package x
+-- example/go.mod --
+module example
+go 1.16
+-- example/example.go --
+package example
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_retract.txt b/libgo/go/cmd/go/testdata/script/mod_get_retract.txt
new file mode 100644 (file)
index 0000000..560fa7b
--- /dev/null
@@ -0,0 +1,59 @@
+# 'go get pkg' should not upgrade to a retracted version.
+cp go.mod.orig go.mod
+go mod edit -require example.com/retract/self/prev@v1.1.0
+go get -d example.com/retract/self/prev
+go list -m example.com/retract/self/prev
+stdout '^example.com/retract/self/prev v1.1.0$'
+
+# 'go get pkg' should not downgrade from a retracted version when no higher
+# version is available.
+cp go.mod.orig go.mod
+go mod edit -require example.com/retract/self/prev@v1.9.0
+go get -d example.com/retract/self/prev
+stderr '^go: warning: example.com/retract/self/prev@v1.9.0: retracted by module author: self$'
+stderr '^go: to switch to the latest unretracted version, run:\n\tgo get example.com/retract/self/prev@latest\n$'
+go list -m example.com/retract/self/prev
+stdout '^example.com/retract/self/prev v1.9.0$'
+
+# 'go get pkg@latest' should downgrade from a retracted version.
+cp go.mod.orig go.mod
+go mod edit -require example.com/retract/self/prev@v1.9.0
+go get -d example.com/retract/self/prev@latest
+go list -m example.com/retract/self/prev
+stdout '^example.com/retract/self/prev v1.1.0$'
+
+# 'go get pkg@version' should update to a specific version, even if that
+# version is retracted.
+cp go.mod.orig go.mod
+go get -d example.com/retract@v1.0.0-bad
+stderr '^go: warning: example.com/retract@v1.0.0-bad: retracted by module author: bad$'
+go list -m example.com/retract
+stdout '^example.com/retract v1.0.0-bad$'
+
+# 'go get -u' should not downgrade from a retracted version when no higher
+# version is available.
+cp go.mod.orig go.mod
+go mod edit -require example.com/retract/self/prev@v1.9.0
+go get -d -u ./use
+stderr '^go: warning: example.com/retract/self/prev@v1.9.0: retracted by module author: self$'
+go list -m example.com/retract/self/prev
+stdout '^example.com/retract/self/prev v1.9.0$'
+
+# 'go get' should warn if a module needed to build named packages is retracted.
+# 'go get' should not warn about unrelated modules.
+go get -d ./empty
+! stderr retracted
+go get -d ./use
+stderr '^go: warning: example.com/retract/self/prev@v1.9.0: retracted by module author: self$'
+
+-- go.mod.orig --
+module example.com/use
+
+go 1.15
+
+-- use/use.go --
+package use
+
+import _ "example.com/retract/self/prev"
+-- empty/empty.go --
+package empty
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_retract_ambiguous.txt b/libgo/go/cmd/go/testdata/script/mod_get_retract_ambiguous.txt
new file mode 100644 (file)
index 0000000..b49ba54
--- /dev/null
@@ -0,0 +1,10 @@
+! go get -d example.com/retract/ambiguous/other
+stderr 'ambiguous import: found package example.com/retract/ambiguous/nested in multiple modules:'
+stderr '^go: warning: example.com/retract/ambiguous/nested@v1.9.0-bad: retracted by module author: nested modules are bad$'
+
+-- go.mod --
+module example.com/use
+
+go 1.16
+
+require example.com/retract/ambiguous/nested v1.9.0-bad
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_split.txt b/libgo/go/cmd/go/testdata/script/mod_get_split.txt
new file mode 100644 (file)
index 0000000..f4e7661
--- /dev/null
@@ -0,0 +1,157 @@
+cp go.mod go.mod.orig
+
+
+# 'go get' on a package already provided by the build list should update
+# the module already in the build list, not fail with an ambiguous import error.
+
+go get -d example.net/split/nested@patch
+go list -m all
+stdout '^example.net/split v0.2.1 '
+! stdout '^example.net/split/nested'
+
+# We should get the same behavior if we use a pattern that matches only that package.
+
+cp go.mod.orig go.mod
+
+go get -d example.net/split/nested/...@patch
+go list -m all
+stdout '^example.net/split v0.2.1 '
+! stdout '^example.net/split/nested'
+
+
+# If we request a version for which the package only exists in one particular module,
+# we should add that one particular module but not resolve import ambiguities.
+#
+# In particular, if the module that previously provided the package has a
+# matching version, but does not itself match the pattern and contains no
+# matching packages, we should not change its version. (We should *not* downgrade
+# module example.net/split to v0.1.0, despite the fact that
+# example.net/split v0.2.0 currently provides the package with the requested path.)
+#
+# TODO(#27899): Maybe we should resolve the ambiguities by upgrading.
+
+cp go.mod.orig go.mod
+
+! go get -d example.net/split/nested@v0.1.0
+stderr '^example.net/split/nested: ambiguous import: found package example.net/split/nested in multiple modules:\n\texample.net/split v0.2.0 \(.*split.2[/\\]nested\)\n\texample.net/split/nested v0.1.0 \(.*nested.1\)$'
+
+# A wildcard that matches packages in some module at its selected version
+# but not at the requested version should fail.
+#
+# We can't set the module to the selected version, because that version doesn't
+# even match the query: if we ran the same query twice, we wouldn't consider the
+# module to match the wildcard during the second call, so why should we consider
+# it to match during the first one?  ('go get' should be idempotent, and if we
+# did that then it would not be.)
+#
+# But we also can't leave it where it is: the user requested that we set everything
+# matching the pattern to the given version, and right now we have packages
+# that match the pattern but *not* the version.
+#
+# That only leaves two options: we can set the module to an arbitrary version
+# (perhaps 'latest' or 'none'), or we can report an error and the let the user
+# disambiguate. We would rather not choose arbitrarily, so we do the latter.
+#
+# TODO(#27899): Should we instead upgrade or downgrade to an arbirary version?
+
+! go get -d example.net/split/nested/...@v0.1.0
+stderr '^go get: example.net/split/nested/\.\.\.@v0.1.0 matches packages in example.net/split@v0.2.0 but not example.net/split@v0.1.0: specify a different version for module example.net/split$'
+
+cmp go.mod go.mod.orig
+
+
+# If another argument resolves the ambiguity, we should be ok again.
+
+go get -d example.net/split@none example.net/split/nested@v0.1.0
+go list -m all
+! stdout '^example.net/split '
+stdout '^example.net/split/nested v0.1.0 '
+
+cp go.mod.orig go.mod
+
+go get -d example.net/split@v0.3.0 example.net/split/nested@v0.1.0
+go list -m all
+stdout '^example.net/split v0.3.0 '
+stdout '^example.net/split/nested v0.1.0 '
+
+
+# If a pattern applies to modules and to packages, we should set all matching
+# modules to the version indicated by the pattern, and also resolve packages
+# to match the pattern if possible.
+
+cp go.mod.orig go.mod
+go get -d example.net/split/nested@v0.0.0
+
+go get -d example.net/...@v0.1.0
+go list -m all
+stdout '^example.net/split v0.1.0 '
+stdout '^example.net/split/nested v0.1.0 '
+
+go get -d example.net/...
+go list -m all
+stdout '^example.net/split v0.3.0 '
+stdout '^example.net/split/nested v0.2.0 '
+
+
+# @none applies to all matching module paths,
+# regardless of whether they contain any packages.
+
+go get -d example.net/...@none
+go list -m all
+! stdout '^example.net'
+
+# Starting from no dependencies, a wildcard can resolve to an empty module with
+# the same prefix even if it contains no packages.
+
+go get -d example.net/...@none
+go get -d example.net/split/...@v0.1.0
+go list -m all
+stdout '^example.net/split v0.1.0 '
+
+
+-- go.mod --
+module m
+
+go 1.16
+
+require example.net/split v0.2.0
+
+replace (
+       example.net/split v0.1.0 => ./split.1
+       example.net/split v0.2.0 => ./split.2
+       example.net/split v0.2.1 => ./split.2
+       example.net/split v0.3.0 => ./split.3
+       example.net/split/nested v0.0.0 => ./nested.0
+       example.net/split/nested v0.1.0 => ./nested.1
+       example.net/split/nested v0.2.0 => ./nested.2
+)
+-- split.1/go.mod --
+module example.net/split
+
+go 1.16
+-- split.2/go.mod --
+module example.net/split
+
+go 1.16
+-- split.2/nested/nested.go --
+package nested
+-- split.3/go.mod --
+module example.net/split
+
+go 1.16
+-- nested.0/go.mod --
+module example.net/split/nested
+
+go 1.16
+-- nested.1/go.mod --
+module example.net/split/nested
+
+go 1.16
+-- nested.1/nested.go --
+package nested
+-- nested.2/go.mod --
+module example.net/split/nested
+
+go 1.16
+-- nested.2/nested.go --
+package nested
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_sum_noroot.txt b/libgo/go/cmd/go/testdata/script/mod_get_sum_noroot.txt
new file mode 100644 (file)
index 0000000..4f1cf03
--- /dev/null
@@ -0,0 +1,11 @@
+# When 'go get' is invoked on a module without a package in the root directory,
+# it should add sums for the module's go.mod file and its content to go.sum.
+# Verifies golang.org/issue/41103.
+go mod init m
+go get -d rsc.io/QUOTE
+grep '^rsc.io/QUOTE v1.5.2/go.mod ' go.sum
+grep '^rsc.io/QUOTE v1.5.2 ' go.sum
+
+# Double-check rsc.io/QUOTE does not have a root package.
+! go list -mod=readonly rsc.io/QUOTE
+stderr '^cannot find module providing package rsc.io/QUOTE: import lookup disabled by -mod=readonly$'
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_too_many_redirects.txt b/libgo/go/cmd/go/testdata/script/mod_get_too_many_redirects.txt
new file mode 100644 (file)
index 0000000..9cbe0d2
--- /dev/null
@@ -0,0 +1,10 @@
+env GO111MODULE=on
+env GOPROXYBASE=$GOPROXY
+env GOPROXY=$GOPROXYBASE/redirect/11
+env GOSUMDB=off
+
+! go get -d rsc.io/quote@v1.2.0
+stderr 'stopped after 10 redirects'
+
+env GOPROXY=$GOPROXYBASE/redirect/9
+go get -d rsc.io/quote@v1.2.0
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_update_unrelated_sum.txt b/libgo/go/cmd/go/testdata/script/mod_get_update_unrelated_sum.txt
new file mode 100644 (file)
index 0000000..0093c0e
--- /dev/null
@@ -0,0 +1,120 @@
+# Check that 'go get' adds sums for updated modules if we had sums before,
+# even if we didn't load packages from them.
+# Verifies #44129.
+
+env fmt='{{.ImportPath}}: {{if .Error}}{{.Error.Err}}{{else}}ok{{end}}'
+
+# Control case: before upgrading, we have the sums we need.
+# go list -deps -e -f $fmt .
+# stdout '^rsc.io/quote: ok$'
+# ! stdout rsc.io/sampler  # not imported by quote in this version
+cp go.mod.orig go.mod
+cp go.sum.orig go.sum
+go mod tidy
+cmp go.mod.orig go.mod
+cmp go.sum.orig go.sum
+
+
+# Upgrade a module. This also upgrades rsc.io/quote, and though we didn't load
+# a package from it, we had the sum for its old version, so we need the
+# sum for the new version, too.
+go get -d example.com/upgrade@v0.0.2
+grep '^rsc.io/quote v1.5.2 ' go.sum
+
+# The upgrade still breaks the build because the new version of quote imports
+# rsc.io/sampler, and we don't have its zip sum.
+go list -deps -e -f $fmt
+stdout 'rsc.io/quote: ok'
+stdout 'rsc.io/sampler: missing go.sum entry for module providing package rsc.io/sampler'
+cp go.mod.orig go.mod
+cp go.sum.orig go.sum
+
+
+# Replace the old version with a directory before upgrading.
+# We didn't need a sum for it before (even though we had one), so we won't
+# fetch a new sum.
+go mod edit -replace rsc.io/quote@v1.0.0=./dummy
+go get -d example.com/upgrade@v0.0.2
+! grep '^rsc.io/quote v1.5.2 ' go.sum
+cp go.mod.orig go.mod
+cp go.sum.orig go.sum
+
+
+# Replace the new version with a directory before upgrading.
+# We can't get a sum for a directory.
+go mod edit -replace rsc.io/quote@v1.5.2=./dummy
+go get -d example.com/upgrade@v0.0.2
+! grep '^rsc.io/quote v1.5.2 ' go.sum
+cp go.mod.orig go.mod
+cp go.sum.orig go.sum
+
+
+# Replace the new version with a different version.
+# We should get a sum for that version.
+go mod edit -replace rsc.io/quote@v1.5.2=rsc.io/quote@v1.5.1
+go get -d example.com/upgrade@v0.0.2
+! grep '^rsc.io/quote v1.5.2 ' go.sum
+grep '^rsc.io/quote v1.5.1 ' go.sum
+cp go.mod.orig go.mod
+cp go.sum.orig go.sum
+
+
+# Delete the new version's zip (but not mod) from the cache and go offline.
+# 'go get' should fail when fetching the zip.
+rm $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
+env GOPROXY=off
+! go get -d example.com/upgrade@v0.0.2
+stderr '^go: upgraded rsc.io/quote v1.0.0 => v1.5.2: error finding sum for rsc.io/quote@v1.5.2: module lookup disabled by GOPROXY=off$'
+
+-- go.mod.orig --
+module m
+
+go 1.16
+
+require (
+       example.com/upgrade v0.0.1
+       rsc.io/quote v1.0.0
+)
+
+replace (
+       example.com/upgrade v0.0.1 => ./upgrade1
+       example.com/upgrade v0.0.2 => ./upgrade2
+)
+-- go.sum.orig --
+rsc.io/quote v1.0.0 h1:kQ3IZQzPTiDJxSZI98YaWgxFEhlNdYASHvh+MplbViw=
+rsc.io/quote v1.0.0/go.mod h1:v83Ri/njykPcgJltBc/gEkJTmjTsNgtO1Y7vyIK1CQA=
+-- go.sum.want --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.0.0 h1:kQ3IZQzPTiDJxSZI98YaWgxFEhlNdYASHvh+MplbViw=
+rsc.io/quote v1.0.0/go.mod h1:v83Ri/njykPcgJltBc/gEkJTmjTsNgtO1Y7vyIK1CQA=
+rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+-- use.go --
+package use
+
+import (
+       _ "example.com/upgrade"
+       _ "rsc.io/quote"
+)
+-- upgrade1/go.mod --
+module example.com/upgrade
+
+go 1.16
+-- upgrade1/upgrade.go --
+package upgrade
+-- upgrade2/go.mod --
+module example.com/upgrade
+
+go 1.16
+
+require rsc.io/quote v1.5.2 // indirect
+-- upgrade2/upgrade.go --
+package upgrade
+-- dummy/go.mod --
+module rsc.io/quote
+
+go 1.16
+-- dummy/quote.go --
+package quote
+
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_wild.txt b/libgo/go/cmd/go/testdata/script/mod_get_wild.txt
new file mode 100644 (file)
index 0000000..78c645c
--- /dev/null
@@ -0,0 +1,95 @@
+# This test covers a crazy edge-case involving wildcards and multiple passes of
+# patch-upgrades, but if we get it right we probably get many other edge-cases
+# right too.
+
+go list -m all
+stdout '^example.net/a v0.1.0 '
+! stdout '^example.net/b '
+
+
+# Requesting pattern example.../b by itself fails: there is no such module
+# already in the build list, and the wildcard in the first element prevents us
+# from attempting to resolve a new module whose path is a prefix of the pattern.
+
+! go get -d -u=patch example.../b@upgrade
+stderr '^go get: no modules to query for example\.\.\./b@upgrade because first path element contains a wildcard$'
+
+
+# Patching . causes a patch to example.net/a, which introduces a new match
+# for example.net/b/..., which is itself patched and causes another upgrade to
+# example.net/a, which is then patched again.
+
+go get -d -u=patch . example.../b@upgrade
+go list -m all
+stdout '^example.net/a v0.2.1 '  # upgraded by dependency of b and -u=patch
+stdout '^example.net/b v0.2.0 '  # introduced by patch of a and upgraded by wildcard
+
+
+-- go.mod --
+module example
+
+go 1.16
+
+require example.net/a v0.1.0
+
+replace (
+       example.net/a v0.1.0 => ./a10
+       example.net/a v0.1.1 => ./a11
+       example.net/a v0.2.0 => ./a20
+       example.net/a v0.2.1 => ./a20
+       example.net/b v0.1.0 => ./b1
+       example.net/b v0.1.1 => ./b1
+       example.net/b v0.2.0 => ./b2
+)
+-- example.go --
+package example
+
+import _ "example.net/a"
+
+-- a10/go.mod --
+module example.net/a
+
+go 1.16
+-- a10/a.go --
+package a
+
+-- a11/go.mod --
+module example.net/a
+
+go 1.16
+
+require example.net/b v0.1.0
+-- a11/a.go --
+package a
+-- a11/unimported/unimported.go --
+package unimported
+
+import _ "example.net/b"
+
+
+-- a20/go.mod --
+module example.net/a
+
+go 1.16
+-- a20/a.go --
+package a
+
+-- b1/go.mod --
+module example.net/b
+
+go 1.16
+-- b1/b.go --
+package b
+
+-- b2/go.mod --
+module example.net/b
+
+go 1.16
+
+require example.net/a v0.2.0
+-- b2/b.go --
+package b
+-- b2/b_test.go --
+package b_test
+
+import _ "example.net/a"
diff --git a/libgo/go/cmd/go/testdata/script/mod_go_version_missing.txt b/libgo/go/cmd/go/testdata/script/mod_go_version_missing.txt
new file mode 100644 (file)
index 0000000..d704816
--- /dev/null
@@ -0,0 +1,122 @@
+cp go.mod go.mod.orig
+
+# For modules whose go.mod file does not include a 'go' directive,
+# we assume the language and dependency semantics of Go 1.16,
+# but do not trigger “automatic vendoring” mode (-mod=vendor),
+# which was added in Go 1.14 and was not triggered
+# under the same conditions in Go 1.16 (which would instead
+# default to -mod=readonly when no 'go' directive is present).
+
+# For Go 1.16 modules, 'all' should prune out dependencies of tests,
+# even if the 'go' directive is missing.
+
+go list -mod=readonly all
+stdout '^example.com/dep$'
+! stdout '^example.com/testdep$'
+cp stdout list-1.txt
+cmp go.mod go.mod.orig
+
+# We should only default to -mod=vendor if the 'go' directive is explicit in the
+# go.mod file. Otherwise, we don't actually know whether the module was written
+# against Go 1.11 or 1.16. We would have to update the go.mod file to clarify,
+# and as of Go 1.16 we don't update the go.mod file by default.
+#
+# If we set -mod=vendor explicitly, we shouldn't apply the Go 1.14
+# consistency check, because — again — we don't know whether we're in a 1.11
+# module or a bad-script-edited 1.16 module.
+
+! go list -mod=vendor all
+! stderr '^go: inconsistent vendoring'
+stderr 'cannot find package "\." in:\n\t.*[/\\]vendor[/\\]example.com[/\\]badedit$'
+
+# When we set -mod=mod, the go version should be updated immediately,
+# to the current version, converting the requirements from eager to lazy.
+#
+# Since we don't know which requirements are actually relevant to the main
+# module, all requirements are added as roots, making the requirements untidy.
+
+go list -mod=mod all
+! stdout '^example.com/testdep$'
+cmp stdout list-1.txt
+cmpenv go.mod go.mod.untidy
+
+go mod tidy
+cmpenv go.mod go.mod.tidy
+
+# On the other hand, if we jump straight to 'go mod tidy',
+# the requirements remain tidy from the start.
+
+cp go.mod.orig go.mod
+go mod tidy
+cmpenv go.mod go.mod.tidy
+
+
+# The updated version should have been written back to go.mod, so now the 'go'
+# directive is explicit. -mod=vendor should trigger by default, and the stronger
+# Go 1.14 consistency check should apply.
+! go list all
+stderr '^go: inconsistent vendoring'
+! stderr badedit
+
+
+-- go.mod --
+module example.com/m
+
+require example.com/dep v0.1.0
+
+replace (
+       example.com/dep v0.1.0 => ./dep
+       example.com/testdep v0.1.0 => ./testdep
+)
+-- go.mod.untidy --
+module example.com/m
+
+go $goversion
+
+require example.com/dep v0.1.0
+
+require example.com/testdep v0.1.0 // indirect
+
+replace (
+       example.com/dep v0.1.0 => ./dep
+       example.com/testdep v0.1.0 => ./testdep
+)
+-- go.mod.tidy --
+module example.com/m
+
+go $goversion
+
+require example.com/dep v0.1.0
+
+replace (
+       example.com/dep v0.1.0 => ./dep
+       example.com/testdep v0.1.0 => ./testdep
+)
+-- vendor/example.com/dep/dep.go --
+package dep
+import _ "example.com/badedit"
+-- vendor/modules.txt --
+HAHAHA this is broken.
+
+-- m.go --
+package m
+
+import _ "example.com/dep"
+
+const x = 1_000
+
+-- dep/go.mod --
+module example.com/dep
+
+require example.com/testdep v0.1.0
+-- dep/dep.go --
+package dep
+-- dep/dep_test.go --
+package dep_test
+
+import _ "example.com/testdep"
+
+-- testdep/go.mod --
+module example.com/testdep
+-- testdep/testdep.go --
+package testdep
diff --git a/libgo/go/cmd/go/testdata/script/mod_gomodcache.txt b/libgo/go/cmd/go/testdata/script/mod_gomodcache.txt
new file mode 100644 (file)
index 0000000..74a3c79
--- /dev/null
@@ -0,0 +1,67 @@
+# Test GOMODCACHE
+env GO111MODULE=on
+
+# Explicitly set GOMODCACHE
+env GOMODCACHE=$WORK/modcache
+go env GOMODCACHE
+stdout $WORK[/\\]modcache
+go get -d rsc.io/quote@v1.0.0
+exists $WORK/modcache/cache/download/rsc.io/quote/@v/v1.0.0.info
+grep '{"Version":"v1.0.0","Time":"2018-02-14T00:45:20Z"}' $WORK/modcache/cache/download/rsc.io/quote/@v/v1.0.0.info
+
+# Ensure GOMODCACHE doesn't affect location of sumdb, but $GOMODCACHE/cache/download/sumdb is still written
+exists $GOPATH/pkg/sumdb
+! exists $WORK/modcache/sumdb
+exists $WORK/modcache/cache/download/sumdb
+
+# Test that the default GOMODCACHE is $GOPATH[0]/pkg/mod
+env GOMODCACHE=
+go env GOMODCACHE
+stdout $GOPATH[/\\]pkg[/\\]mod
+go get -d rsc.io/quote@v1.0.0
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.0.0.info
+grep '{"Version":"v1.0.0","Time":"2018-02-14T00:45:20Z"}' $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.0.0.info
+
+# If neither GOMODCACHE or GOPATH are set, GOPATH defaults to the user's $HOME/go, so GOMODCACHE becomes $HOME/go/pkg/mod
+[windows] env USERPROFILE=$WORK/home # Ensure USERPROFILE is a valid path (rather than /no-home/ so we don't run into the logic that "uninfers" GOPATH in cmd/go/main.go
+[plan9] env home=$WORK/home
+[!windows] [!plan9] env HOME=$WORK/home
+env GOMODCACHE=
+env GOPATH=
+go env GOMODCACHE
+stdout $HOME[/\\]go[/\\]pkg[/\\]mod
+
+# If GOMODCACHE isn't set and GOPATH starts with the path list separator, it's an error.
+env GOMODCACHE=
+env GOPATH=${:}$WORK/this/is/ignored
+! go env GOMODCACHE
+stderr 'missing \$GOPATH'
+
+# If GOMODCACHE isn't set and GOPATH has multiple elements only the first is used.
+env GOMODCACHE=
+env GOPATH=$WORK/first/path${:}$WORK/this/is/ignored
+go env GOMODCACHE
+stdout $WORK[/\\]first[/\\]path[/\\]pkg[/\\]mod
+
+env GOMODCACHE=$WORK/modcache
+go mod download rsc.io/quote@v1.0.0
+exists $WORK/modcache/cache/download/rsc.io/quote/@v/v1.0.0.info
+
+# Test error when cannot create GOMODCACHE directory
+env GOMODCACHE=$WORK/modcachefile
+! go install example.com/cmd/a@v1.0.0
+stderr 'go: could not create module cache'
+
+# Test that the following work even with GO111MODULE=off
+env GO111MODULE=off
+
+# Cleaning modcache
+exists $WORK/modcache
+env GOMODCACHE=$WORK/modcache
+go clean -modcache
+! exists $WORK/modcache
+
+-- go.mod --
+module m
+
+-- $WORK/modcachefile --
diff --git a/libgo/go/cmd/go/testdata/script/mod_graph_version.txt b/libgo/go/cmd/go/testdata/script/mod_graph_version.txt
new file mode 100644 (file)
index 0000000..f9a73f4
--- /dev/null
@@ -0,0 +1,101 @@
+# For this module, Go 1.17 prunes out a (transitive and otherwise-irrelevant)
+# requirement on a retracted higher version of a dependency.
+# However, when Go 1.16 reads the same requirements from the go.mod file,
+# it does not prune out that requirement, and selects the retracted version.
+#
+# The Go 1.16 module graph looks like:
+#
+# m ---- lazy v0.1.0 ---- requireincompatible v0.1.0 ---- incompatible v2.0.0+incompatible
+# |        |
+# + -------+------------- incompatible v1.0.0
+#
+# The Go 1.17 module graph is the same except that the dependencies of
+# requireincompatible are pruned out (because the module that requires
+# it — lazy v0.1.0 — specifies 'go 1.17', and it is not otherwise relevant to
+# the main module).
+
+cp go.mod go.mod.orig
+
+go mod graph
+cp stdout graph-1.17.txt
+stdout '^example\.com/m example\.com/retract/incompatible@v1\.0\.0$'
+stdout '^example\.net/lazy@v0\.1\.0 example\.com/retract/incompatible@v1\.0\.0$'
+! stdout 'example\.com/retract/incompatible@v2\.0\.0\+incompatible'
+
+go mod graph -go=1.17
+cmp stdout graph-1.17.txt
+
+cmp go.mod go.mod.orig
+
+
+# Setting -go=1.16 should report the graph as viewed by Go 1.16,
+# but should not edit the go.mod file.
+
+go mod graph -go=1.16
+cp stdout graph-1.16.txt
+stdout '^example\.com/m example\.com/retract/incompatible@v1\.0\.0$'
+stdout '^example\.net/lazy@v0\.1\.0 example.com/retract/incompatible@v1\.0\.0$'
+stdout '^example.net/requireincompatible@v0.1.0 example.com/retract/incompatible@v2\.0\.0\+incompatible$'
+
+cmp go.mod go.mod.orig
+
+
+# If we actually update the go.mod file to the requested go version,
+# we should get the same selected versions, but the roots of the graph
+# may be updated.
+#
+# TODO(#45551): The roots should not be updated.
+
+go mod edit -go=1.16
+go mod graph
+! stdout '^example\.com/m example\.com/retract/incompatible@v1\.0\.0$'
+stdout '^example\.net/lazy@v0.1.0 example.com/retract/incompatible@v1\.0\.0$'
+stdout '^example.net/requireincompatible@v0.1.0 example.com/retract/incompatible@v2\.0\.0\+incompatible$'
+       # TODO(#45551): cmp stdout graph-1.16.txt
+
+
+# Unsupported go versions should be rejected, since we don't know
+# what versions they would report.
+! go mod graph -go=1.99999999999
+stderr '^invalid value "1\.99999999999" for flag -go: maximum supported Go version is '$goversion'\nusage: go mod graph \[-go=version\]\nRun ''go help mod graph'' for details.$'
+
+
+-- go.mod --
+// Module m indirectly imports a package from
+// example.com/retract/incompatible. Its selected version of
+// that module is lower under Go 1.17 semantics than under Go 1.16.
+module example.com/m
+
+go 1.17
+
+replace (
+       example.net/lazy v0.1.0 => ./lazy
+       example.net/requireincompatible v0.1.0 => ./requireincompatible
+)
+
+require (
+       example.com/retract/incompatible v1.0.0 // indirect
+       example.net/lazy v0.1.0
+)
+-- lazy/go.mod --
+// Module lazy requires example.com/retract/incompatible v1.0.0.
+//
+// When viewed from the outside it also has a transitive dependency
+// on v2.0.0+incompatible, but in lazy mode that transitive dependency
+// is pruned out.
+module example.net/lazy
+
+go 1.17
+
+exclude example.com/retract/incompatible v2.0.0+incompatible
+
+require (
+       example.com/retract/incompatible v1.0.0
+       example.net/requireincompatible v0.1.0
+)
+-- requireincompatible/go.mod --
+module example.net/requireincompatible
+
+go 1.15
+
+require example.com/retract/incompatible v2.0.0+incompatible
diff --git a/libgo/go/cmd/go/testdata/script/mod_import_cycle.txt b/libgo/go/cmd/go/testdata/script/mod_import_cycle.txt
new file mode 100644 (file)
index 0000000..7be0749
--- /dev/null
@@ -0,0 +1,40 @@
+env GO111MODULE=on
+
+# 'go list all' should fail with a reasonable error message
+! go list all
+stderr '^package m\n\timports m/a\n\timports m/b\n\timports m/a: import cycle not allowed'
+
+# 'go list -e' should not print to stderr, but should mark all three
+# packages (m, m/a, and m/b) as Incomplete.
+go list -e -json all
+! stderr .
+stdout -count=3 '"Incomplete": true,'
+
+-- go.mod --
+module m
+
+require (
+       m/a v0.0.0
+       m/b v0.0.0
+)
+
+replace (
+       m/a => ./a
+       m/b => ./b
+)
+-- m.go --
+package m
+import (
+       _ "m/a"
+       _ "m/b"
+)
+-- a/go.mod --
+module m/a
+-- a/a.go --
+package a
+import _ "m/b"
+-- b/go.mod --
+module m/b
+-- b/b.go --
+package b
+import _ "m/a"
diff --git a/libgo/go/cmd/go/testdata/script/mod_import_issue41113.txt b/libgo/go/cmd/go/testdata/script/mod_import_issue41113.txt
new file mode 100644 (file)
index 0000000..fed2510
--- /dev/null
@@ -0,0 +1,28 @@
+# Regression test for https://golang.org/issue/41113.
+#
+# When resolving a missing import path, the inability to add the package from
+# one module path should not interfere with adding a nested path.
+
+# Initially, our module depends on split-incompatible v2.1.0-pre+incompatible,
+# from which an imported package has been removed (and relocated to the nested
+# split-incompatible/subpkg module). modload.QueryPattern will suggest
+# split-incompatible v2.0.0+incompatible, which we cannot use (because it would
+# be an implicit downgrade), and split-incompatible/subpkg v0.1.0, which we
+# *should* use.
+
+go mod tidy
+
+go list -m all
+stdout '^example.com/split-incompatible/subpkg v0\.1\.0$'
+! stdout '^example.com/split-incompatible .*'
+
+-- go.mod --
+module golang.org/issue/41113
+
+go 1.16
+
+require example.com/split-incompatible v2.1.0-pre+incompatible
+-- x.go --
+package issue41113
+
+import _ "example.com/split-incompatible/subpkg"
diff --git a/libgo/go/cmd/go/testdata/script/mod_import_issue42891.txt b/libgo/go/cmd/go/testdata/script/mod_import_issue42891.txt
new file mode 100644 (file)
index 0000000..a78cab2
--- /dev/null
@@ -0,0 +1,14 @@
+# If an import declaration is an absolute path, most commands should report
+# an error instead of going into an infinite loop.
+# Verifies golang.org/issue/42891.
+go list .
+stdout '^m$'
+
+-- go.mod --
+module m
+
+go 1.16
+-- m.go --
+package m
+
+import "/"
diff --git a/libgo/go/cmd/go/testdata/script/mod_import_meta.txt b/libgo/go/cmd/go/testdata/script/mod_import_meta.txt
new file mode 100644 (file)
index 0000000..0e469d0
--- /dev/null
@@ -0,0 +1,45 @@
+# The loader should not attempt to resolve imports of the "all", "std", and "cmd" meta-packages.
+
+! go list -deps ./importall
+! stderr 'internal error'
+stderr '^importall[/\\]x.go:3:8: "all" is not an importable package; see ''go help packages''$'
+
+! go list -deps ./importcmd
+! stderr 'internal error'
+stderr '^importcmd[/\\]x.go:3:8: "cmd" is not an importable package; see ''go help packages''$'
+
+! go list -deps ./importstd
+! stderr 'internal error'
+stderr '^importstd[/\\]x.go:3:8: "std" is not an importable package; see ''go help packages''$'
+
+
+# Not even if such a path is theoretically provided by a (necessarily replaced) module.
+
+go mod edit -replace std@v0.1.0=./modstd
+go mod edit -require std@v0.1.0
+
+! go list -deps ./importstd
+stderr '^importstd[/\\]x.go:3:8: "std" is not an importable package; see ''go help packages''$'
+
+
+-- go.mod --
+module example.com
+go 1.16
+-- importall/x.go --
+package importall
+
+import _ "all"
+-- importcmd/x.go --
+package importcmd
+
+import _ "cmd"
+-- importstd/x.go --
+package importstd
+
+import _ "std"
+-- modstd/go.mod --
+module std
+go 1.16
+-- modstd/std.go --
+// Package std is an incredibly confusingly-named package.
+package std
diff --git a/libgo/go/cmd/go/testdata/script/mod_indirect_nospace.txt b/libgo/go/cmd/go/testdata/script/mod_indirect_nospace.txt
new file mode 100644 (file)
index 0000000..f4fb6a8
--- /dev/null
@@ -0,0 +1,32 @@
+# https://golang.org/issue/45932: "indirect" comments missing spaces
+# should not be corrupted when the comment is removed.
+
+go mod tidy
+cmp go.mod go.mod.direct
+
+-- go.mod --
+module example.net/m
+
+go 1.16
+
+require example.net/x v0.1.0 //indirect
+
+replace example.net/x v0.1.0 => ./x
+-- go.mod.direct --
+module example.net/m
+
+go 1.16
+
+require example.net/x v0.1.0
+
+replace example.net/x v0.1.0 => ./x
+-- m.go --
+package m
+import _ "example.net/x"
+
+-- x/go.mod --
+module example.net/x
+
+go 1.16
+-- x/x.go --
+package x
index f8cf1d563ab64b11bbee108653cf1b2556b400e0..76b48678604fabe57bda20fde36b770e5728435d 100644 (file)
@@ -1,10 +1,6 @@
 env GO111MODULE=on
 env GOFLAGS=-mod=mod
 
-# modconv uses git directly to examine what old 'go get' would
-[!net] skip
-[!exec:git] skip
-
 # go mod init should populate go.mod from Gopkg.lock
 go mod init x
 stderr 'copying requirements from Gopkg.lock'
index a351a6ae4bce792c59bd25f7eacb9cf9413c5d44..373810c7687275f39d91a82e2ebc739f9421d64e 100644 (file)
@@ -3,6 +3,7 @@
 
 env GO111MODULE=on
 env GOPROXY=direct
+env GOSUMDB=
 
 # Regression test for golang.org/issue/32161:
 # 'go mod init' did not locate tags when resolving a commit to a pseudo-version.
index ccdfc92317583e96a8176a91daa97c7ab650c784..e5fd4ddbcb92c7d585b1e5b239a6dfc5cfe8089d 100644 (file)
@@ -1,7 +1,7 @@
 env GO111MODULE=on
 
 ! go mod init .
-stderr '^go: invalid module path "\.": is a local import path$'
+stderr '^go: malformed module path ".": is a local import path$'
 
 cd x
 go mod init example.com/x
diff --git a/libgo/go/cmd/go/testdata/script/mod_init_tidy.txt b/libgo/go/cmd/go/testdata/script/mod_init_tidy.txt
new file mode 100644 (file)
index 0000000..4a52590
--- /dev/null
@@ -0,0 +1,30 @@
+# 'go mod init' should not recommend 'go mod tidy' in an empty directory
+# (one that contains no non-hidden .go files or subdirectories).
+cd empty
+go mod init m
+! stderr tidy
+cd ..
+
+# 'go mod init' should recommend 'go mod tidy' if the directory has a .go file.
+cd pkginroot
+go mod init m
+stderr '^go: to add module requirements and sums:\n\tgo mod tidy$'
+cd ..
+
+# 'go mod init' should recommend 'go mod tidy' if the directory has a
+# subdirectory. We don't walk the tree to see if it has .go files.
+cd subdir
+go mod init m
+stderr '^go: to add module requirements and sums:\n\tgo mod tidy$'
+cd ..
+
+-- empty/empty.txt --
+Not a .go file. Still counts as an empty project.
+-- empty/.hidden/empty.go --
+File in hidden directory. Still as an empty project.
+-- empty/_hidden/empty.go --
+File in hidden directory. Still as an empty project.
+-- pkginroot/hello.go --
+package vendorimport
+-- subdir/sub/empty.txt --
+Subdirectory doesn't need to contain a package.
diff --git a/libgo/go/cmd/go/testdata/script/mod_install_hint.txt b/libgo/go/cmd/go/testdata/script/mod_install_hint.txt
new file mode 100644 (file)
index 0000000..f2a5287
--- /dev/null
@@ -0,0 +1,5 @@
+# Module is replaced but not required. No hint appears as no module is suggested.
+go mod init m
+go mod edit -replace=github.com/notrequired@v0.5.0=github.com/doesnotexist@v0.5.0
+! go install github.com/notrequired
+! stderr 'to add it:'
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/mod_install_pkg_version.txt b/libgo/go/cmd/go/testdata/script/mod_install_pkg_version.txt
new file mode 100644 (file)
index 0000000..367d34b
--- /dev/null
@@ -0,0 +1,203 @@
+# 'go install pkg@version' works outside a module.
+env GO111MODULE=auto
+go install example.com/cmd/a@v1.0.0
+exists $GOPATH/bin/a$GOEXE
+rm $GOPATH/bin
+
+
+# 'go install pkg@version' reports an error if modules are disabled.
+env GO111MODULE=off
+! go install example.com/cmd/a@v1.0.0
+stderr '^go: modules disabled by GO111MODULE=off; see ''go help modules''$'
+env GO111MODULE=auto
+
+
+# 'go install pkg@version' ignores go.mod in current directory.
+cd m
+cp go.mod go.mod.orig
+! go list -m all
+stderr '^go list -m: example.com/cmd@v1.1.0-doesnotexist: missing go.sum entry; to add it:\n\tgo mod download example.com/cmd$'
+go install example.com/cmd/a@latest
+cmp go.mod go.mod.orig
+exists $GOPATH/bin/a$GOEXE
+[!gccgo] go version -m $GOPATH/bin/a$GOEXE
+[!gccgo] stdout '^\tmod\texample.com/cmd\tv1.0.0\t' # "latest", not from go.mod
+rm $GOPATH/bin/a
+cd ..
+
+
+# 'go install -modfile=x.mod pkg@version' reports an error, but only if
+# -modfile is specified explicitly on the command line.
+cd m
+env GOFLAGS=-modfile=go.mod
+go install example.com/cmd/a@latest  # same as above
+env GOFLAGS=
+! go install -modfile=go.mod example.com/cmd/a@latest
+stderr '^go: -modfile cannot be used with commands that ignore the current module$'
+cd ..
+
+
+# Every test case requires linking, so we only cover the most important cases
+# when -short is set.
+[short] stop
+
+
+# 'go install pkg@version' works on a module that doesn't have a go.mod file
+# and with a module whose go.mod file has missing requirements.
+# With a proxy, the two cases are indistinguishable.
+go install rsc.io/fortune@v1.0.0
+stderr '^go: found rsc.io/quote in rsc.io/quote v1.5.2$'
+exists $GOPATH/bin/fortune$GOEXE
+! exists $GOPATH/pkg/mod/rsc.io/fortune@v1.0.0/go.mod # no go.mod file
+[!gccgo] go version -m $GOPATH/bin/fortune$GOEXE
+[!gccgo] stdout '^\tdep\trsc.io/quote\tv1.5.2\t' # latest version of fortune's dependency
+rm $GOPATH/bin
+
+
+# 'go install dir@version' works like a normal 'go install' command if
+# dir is a relative or absolute path.
+env GO111MODULE=on
+go mod download rsc.io/fortune@v1.0.0
+! go install $GOPATH/pkg/mod/rsc.io/fortune@v1.0.0
+stderr '^go: go\.mod file not found in current directory or any parent directory; see ''go help modules''$'
+! go install ../pkg/mod/rsc.io/fortune@v1.0.0
+stderr '^go: go\.mod file not found in current directory or any parent directory; see ''go help modules''$'
+mkdir tmp
+cd tmp
+go mod init tmp
+go mod edit -require=rsc.io/fortune@v1.0.0
+! go install -mod=readonly $GOPATH/pkg/mod/rsc.io/fortune@v1.0.0
+stderr '^missing go\.sum entry for module providing package rsc\.io/fortune; to add:\n\tgo mod download rsc\.io/fortune$'
+! go install -mod=readonly ../../pkg/mod/rsc.io/fortune@v1.0.0
+stderr '^missing go\.sum entry for module providing package rsc\.io/fortune; to add:\n\tgo mod download rsc\.io/fortune$'
+go get -d rsc.io/fortune@v1.0.0
+go install -mod=readonly $GOPATH/pkg/mod/rsc.io/fortune@v1.0.0
+exists $GOPATH/bin/fortune$GOEXE
+cd ..
+rm tmp
+rm $GOPATH/bin
+env GO111MODULE=auto
+
+# 'go install pkg@version' reports errors for meta packages, std packages,
+# and directories.
+! go install std@v1.0.0
+stderr '^go install: std@v1.0.0: argument must be a package path, not a meta-package$'
+! go install fmt@v1.0.0
+stderr '^go install: fmt@v1.0.0: argument must not be a package in the standard library$'
+! go install example.com//cmd/a@v1.0.0
+stderr '^go install: example.com//cmd/a@v1.0.0: argument must be a clean package path$'
+! go install example.com/cmd/a@v1.0.0 ./x@v1.0.0
+stderr '^go install: ./x@v1.0.0: argument must be a package path, not a relative path$'
+! go install example.com/cmd/a@v1.0.0 $GOPATH/src/x@v1.0.0
+stderr '^go install: '$WORK'[/\\]gopath/src/x@v1.0.0: argument must be a package path, not an absolute path$'
+! go install example.com/cmd/a@v1.0.0 cmd/...@v1.0.0
+stderr '^package cmd/go not provided by module example.com/cmd@v1.0.0$'
+
+# 'go install pkg@version' should accept multiple arguments but report an error
+# if the version suffixes are different, even if they refer to the same version.
+go install example.com/cmd/a@v1.0.0 example.com/cmd/b@v1.0.0
+exists $GOPATH/bin/a$GOEXE
+exists $GOPATH/bin/b$GOEXE
+rm $GOPATH/bin
+
+env GO111MODULE=on
+go list -m example.com/cmd@latest
+stdout '^example.com/cmd v1.0.0$'
+env GO111MODULE=auto
+
+! go install example.com/cmd/a@v1.0.0 example.com/cmd/b@latest
+stderr '^go install: example.com/cmd/b@latest: all arguments must have the same version \(@v1.0.0\)$'
+
+
+# 'go install pkg@version' should report an error if the arguments are in
+# different modules.
+! go install example.com/cmd/a@v1.0.0 rsc.io/fortune@v1.0.0
+stderr '^package rsc.io/fortune provided by module rsc.io/fortune@v1.0.0\n\tAll packages must be provided by the same module \(example.com/cmd@v1.0.0\).$'
+
+
+# 'go install pkg@version' should report an error if an argument is not
+# a main package.
+! go install example.com/cmd/a@v1.0.0 example.com/cmd/err@v1.0.0
+stderr '^package example.com/cmd/err is not a main package$'
+
+# Wildcards should match only main packages. This module has a non-main package
+# with an error, so we'll know if that gets built.
+mkdir tmp
+cd tmp
+go mod init m
+go get -d example.com/cmd@v1.0.0
+! go build example.com/cmd/...
+stderr 'err[/\\]err.go:3:9: undefined: DoesNotCompile$'
+cd ..
+
+go install example.com/cmd/...@v1.0.0
+exists $GOPATH/bin/a$GOEXE
+exists $GOPATH/bin/b$GOEXE
+rm $GOPATH/bin
+
+# If a wildcard matches no packages, we should see a warning.
+! go install example.com/cmd/nomatch...@v1.0.0
+stderr '^go install: example.com/cmd/nomatch\.\.\.@v1.0.0: module example.com/cmd@v1.0.0 found, but does not contain packages matching example.com/cmd/nomatch\.\.\.$'
+go install example.com/cmd/a@v1.0.0 example.com/cmd/nomatch...@v1.0.0
+stderr '^go: warning: "example.com/cmd/nomatch\.\.\." matched no packages$'
+
+# If a wildcard matches only non-main packges, we should see a different warning.
+go install example.com/cmd/err...@v1.0.0
+stderr '^go: warning: "example.com/cmd/err\.\.\." matched only non-main packages$'
+
+
+# 'go install pkg@version' should report errors if the module contains
+# replace or exclude directives.
+go mod download example.com/cmd@v1.0.0-replace
+! go install example.com/cmd/a@v1.0.0-replace
+cmp stderr replace-err
+
+go mod download example.com/cmd@v1.0.0-exclude
+! go install example.com/cmd/a@v1.0.0-exclude
+cmp stderr exclude-err
+
+# 'go install pkg@version' should report an error if the module requires a
+# higher version of itself.
+! go install example.com/cmd/a@v1.0.0-newerself
+stderr '^go install: example.com/cmd/a@v1.0.0-newerself: version constraints conflict:\n\texample.com/cmd@v1.0.0-newerself requires example.com/cmd@v1.0.0, but example.com/cmd@v1.0.0-newerself is requested$'
+
+
+# 'go install pkg@version' will only match a retracted version if it's
+# explicitly requested.
+env GO111MODULE=on
+go list -m -versions example.com/cmd
+! stdout v1.9.0
+go list -m -versions -retracted example.com/cmd
+stdout v1.9.0
+go install example.com/cmd/a@latest
+[!gccgo] go version -m $GOPATH/bin/a$GOEXE
+[!gccgo] stdout '^\tmod\texample.com/cmd\tv1.0.0\t'
+go install example.com/cmd/a@v1.9.0
+[!gccgo] go version -m $GOPATH/bin/a$GOEXE
+[!gccgo] stdout '^\tmod\texample.com/cmd\tv1.9.0\t'
+env GO111MODULE=
+
+# 'go install pkg@version' succeeds when -mod=readonly is set explicitly.
+# Verifies #43278.
+go install -mod=readonly example.com/cmd/a@v1.0.0
+
+-- m/go.mod --
+module m
+
+go 1.16
+
+require example.com/cmd v1.1.0-doesnotexist
+-- x/x.go --
+package main
+
+func main() {}
+-- replace-err --
+go install: example.com/cmd/a@v1.0.0-replace (in example.com/cmd@v1.0.0-replace):
+       The go.mod file for the module providing named packages contains one or
+       more replace directives. It must not contain directives that would cause
+       it to be interpreted differently than if it were the main module.
+-- exclude-err --
+go install: example.com/cmd/a@v1.0.0-exclude (in example.com/cmd@v1.0.0-exclude):
+       The go.mod file for the module providing named packages contains one or
+       more exclude directives. It must not contain directives that would cause
+       it to be interpreted differently than if it were the main module.
diff --git a/libgo/go/cmd/go/testdata/script/mod_invalid_path.txt b/libgo/go/cmd/go/testdata/script/mod_invalid_path.txt
new file mode 100644 (file)
index 0000000..333a3ff
--- /dev/null
@@ -0,0 +1,61 @@
+# Test that mod files with invalid or missing paths produce an error.
+
+# Test that go list fails on a go.mod with no module declaration.
+cd $WORK/gopath/src/mod
+! go list .
+stderr '^go: no module declaration in go.mod. To specify the module path:\n\tgo mod edit -module=example.com/mod$'
+
+# Test that go mod init in GOPATH doesn't add a module declaration
+# with a path that can't possibly be a module path, because
+# it isn't even a valid import path.
+# The single quote and backtick are the only characters which are not allowed
+# but are a valid Windows file name.
+cd $WORK/'gopath/src/m''d'
+! go mod init
+stderr 'cannot determine module path'
+
+# Test that a go.mod file is rejected when its module declaration has a path that can't
+# possibly be a module path, because it isn't even a valid import path
+cd $WORK/gopath/src/badname
+! go list .
+stderr 'malformed module path'
+
+# Test that an import path containing an element with a leading dot is valid,
+# but such a module path is not.
+# Verifies #43985.
+cd $WORK/gopath/src/dotname
+go list ./.dot
+stdout '^example.com/dotname/.dot$'
+go list ./use
+stdout '^example.com/dotname/use$'
+! go list -m example.com/dotname/.dot@latest
+stderr '^go list -m: example.com/dotname/.dot@latest: malformed module path "example.com/dotname/.dot": leading dot in path element$'
+go get -d example.com/dotname/.dot
+go get -d example.com/dotname/use
+go mod tidy
+
+-- mod/go.mod --
+
+-- mod/foo.go --
+package foo
+
+-- m'd/foo.go --
+package mad
+
+-- badname/go.mod --
+
+module .\.
+
+-- badname/foo.go --
+package badname
+
+-- dotname/go.mod --
+module example.com/dotname
+
+go 1.16
+-- dotname/.dot/dot.go --
+package dot
+-- dotname/use/use.go --
+package use
+
+import _ "example.com/dotname/.dot"
diff --git a/libgo/go/cmd/go/testdata/script/mod_invalid_path_dotname.txt b/libgo/go/cmd/go/testdata/script/mod_invalid_path_dotname.txt
new file mode 100644 (file)
index 0000000..8593433
--- /dev/null
@@ -0,0 +1,46 @@
+# Test that an import path containing an element with a leading dot
+# in another module is valid.
+
+# 'go get' works with no version query.
+cp go.mod.empty go.mod
+go get -d example.com/dotname/.dot
+go list -m example.com/dotname
+stdout '^example.com/dotname v1.0.0$'
+
+# 'go get' works with a version query.
+cp go.mod.empty go.mod
+go get -d example.com/dotname/.dot@latest
+go list -m example.com/dotname
+stdout '^example.com/dotname v1.0.0$'
+
+# 'go get' works on an importing package.
+cp go.mod.empty go.mod
+go get -d .
+go list -m example.com/dotname
+stdout '^example.com/dotname v1.0.0$'
+
+# 'go list' works on the dotted package.
+go list example.com/dotname/.dot
+stdout '^example.com/dotname/.dot$'
+
+# 'go list' works on an importing package.
+go list .
+stdout '^m$'
+
+# 'go mod tidy' works.
+cp go.mod.empty go.mod
+go mod tidy
+go list -m example.com/dotname
+stdout '^example.com/dotname v1.0.0$'
+
+-- go.mod.empty --
+module m
+
+go 1.16
+-- go.sum --
+example.com/dotname v1.0.0 h1:Q0JMAn464CnwFVCshs1n4+f5EFiW/eRhnx/fTWjw2Ag=
+example.com/dotname v1.0.0/go.mod h1:7K4VLT7QylRI8H7yZwUkeDH2s19wQnyfp/3oBlItWJ0=
+-- use.go --
+package use
+
+import _ "example.com/dotname/.dot"
diff --git a/libgo/go/cmd/go/testdata/script/mod_invalid_path_plus.txt b/libgo/go/cmd/go/testdata/script/mod_invalid_path_plus.txt
new file mode 100644 (file)
index 0000000..51dbf93
--- /dev/null
@@ -0,0 +1,36 @@
+# https://golang.org/issue/44776
+# The '+' character should be disallowed in module paths, but allowed in package
+# paths within valid modules.
+
+# 'go list' accepts package paths with pluses.
+cp go.mod.orig go.mod
+go get -d example.net/cmd
+go list example.net/cmd/x++
+
+# 'go list -m' rejects module paths with pluses.
+! go list -versions -m 'example.net/bad++'
+stderr '^go list -m: malformed module path "example.net/bad\+\+": invalid char ''\+''$'
+
+# 'go get' accepts package paths with pluses.
+cp go.mod.orig go.mod
+go get -d example.net/cmd/x++
+go list -m example.net/cmd
+stdout '^example.net/cmd v0.0.0-00010101000000-000000000000 => ./cmd$'
+
+-- go.mod.orig --
+module example.com/m
+
+go 1.16
+
+replace (
+       example.net/cmd => ./cmd
+)
+
+-- cmd/go.mod --
+module example.net/cmd
+
+go 1.16
+-- cmd/x++/main.go --
+package main
+
+func main() {}
index 43b9564356100a02cea4f9c00ae394930748db37..6846a792a5df587e00b2ce7d497333413d4f0dd5 100644 (file)
@@ -19,7 +19,7 @@ cp go.mod.orig go.mod
 go mod edit -require golang.org/x/text@14c0d48ead0c
 cd outside
 ! go list -m golang.org/x/text
-stderr 'go: example.com@v0.0.0 \(replaced by \./\..\): parsing ../go.mod: '$WORK'/gopath/src/go.mod:5: require golang.org/x/text: version "14c0d48ead0c" invalid: must be of the form v1.2.3'
+stderr 'go list -m: example.com@v0.0.0 \(replaced by \./\.\.\): parsing ..[/\\]go.mod: '$WORK'[/\\]gopath[/\\]src[/\\]go.mod:5: require golang.org/x/text: version "14c0d48ead0c" invalid: must be of the form v1.2.3'
 cd ..
 go list -m golang.org/x/text
 stdout 'golang.org/x/text v0.1.1-0.20170915032832-14c0d48ead0c'
@@ -30,7 +30,7 @@ cp go.mod.orig go.mod
 go mod edit -require golang.org/x/text/unicode@v0.0.0-20170915032832-14c0d48ead0c
 cd outside
 ! go list -m golang.org/x/text
-stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text/unicode@v0.0.0-20170915032832-14c0d48ead0c: invalid version: missing golang.org/x/text/unicode/go.mod at revision 14c0d48ead0c'
+stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text/unicode@v0.0.0-20170915032832-14c0d48ead0c: invalid version: missing golang.org/x/text/unicode/go.mod at revision 14c0d48ead0c'
 cd ..
 ! go list -m golang.org/x/text
 stderr 'golang.org/x/text/unicode@v0.0.0-20170915032832-14c0d48ead0c: invalid version: missing golang.org/x/text/unicode/go.mod at revision 14c0d48ead0c'
@@ -47,17 +47,17 @@ cp go.mod.orig go.mod
 go mod edit -require golang.org/x/text@v2.1.1-0.20170915032832-14c0d48ead0c
 cd outside
 ! go list -m golang.org/x/text
-stderr 'go: example.com@v0.0.0 \(replaced by \./\.\.\): parsing ../go.mod: '$WORK'/gopath/src/go.mod:5: require golang.org/x/text: version "v2.1.1-0.20170915032832-14c0d48ead0c" invalid: should be v0 or v1, not v2'
+stderr 'go list -m: example.com@v0.0.0 \(replaced by \./\.\.\): parsing ..[/\\]go.mod: '$WORK'[/\\]gopath[/\\]src[/\\]go.mod:5: require golang.org/x/text: version "v2.1.1-0.20170915032832-14c0d48ead0c" invalid: should be v0 or v1, not v2'
 cd ..
 ! go list -m golang.org/x/text
-stderr $WORK'/gopath/src/go.mod:5: require golang.org/x/text: version "v2.1.1-0.20170915032832-14c0d48ead0c" invalid: should be v0 or v1, not v2'
+stderr $WORK'[/\\]gopath[/\\]src[/\\]go.mod:5: require golang.org/x/text: version "v2.1.1-0.20170915032832-14c0d48ead0c" invalid: should be v0 or v1, not v2'
 
 # A pseudo-version with fewer than 12 digits of SHA-1 prefix is invalid.
 cp go.mod.orig go.mod
 go mod edit -require golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0
 cd outside
 ! go list -m golang.org/x/text
-stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0: invalid pseudo-version: revision is shorter than canonical \(14c0d48ead0c\)'
+stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0: invalid pseudo-version: revision is shorter than canonical \(14c0d48ead0c\)'
 cd ..
 ! go list -m golang.org/x/text
 stderr 'golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0: invalid pseudo-version: revision is shorter than canonical \(14c0d48ead0c\)'
@@ -67,7 +67,7 @@ cp go.mod.orig go.mod
 go mod edit -require golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a
 cd outside
 ! go list -m golang.org/x/text
-stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a: invalid pseudo-version: revision is longer than canonical \(14c0d48ead0c\)'
+stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a: invalid pseudo-version: revision is longer than canonical \(14c0d48ead0c\)'
 cd ..
 ! go list -m golang.org/x/text
 stderr 'golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a: invalid pseudo-version: revision is longer than canonical \(14c0d48ead0c\)'
@@ -77,7 +77,7 @@ cp go.mod.orig go.mod
 go mod edit -require golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c
 cd outside
 ! go list -m golang.org/x/text
-stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)'
+stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)'
 cd ..
 ! go list -m golang.org/x/text
 stderr 'golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)'
@@ -87,7 +87,7 @@ stderr 'golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-v
 go mod edit -replace golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c=golang.org/x/text@14c0d48ead0c
 cd outside
 ! go list -m golang.org/x/text
-stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)'
+stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)'
 cd ..
 go list -m golang.org/x/text
 stdout 'golang.org/x/text v0.1.1-0.20190915032832-14c0d48ead0c => golang.org/x/text v0.1.1-0.20170915032832-14c0d48ead0c'
@@ -97,7 +97,7 @@ cp go.mod.orig go.mod
 go mod edit -require golang.org/x/text@v1.999.999-0.20170915032832-14c0d48ead0c
 cd outside
 ! go list -m golang.org/x/text
-stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v1.999.999-0.20170915032832-14c0d48ead0c: invalid pseudo-version: preceding tag \(v1.999.998\) not found'
+stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v1.999.999-0.20170915032832-14c0d48ead0c: invalid pseudo-version: preceding tag \(v1.999.998\) not found'
 cd ..
 ! go list -m golang.org/x/text
 stderr 'golang.org/x/text@v1.999.999-0.20170915032832-14c0d48ead0c: invalid pseudo-version: preceding tag \(v1.999.998\) not found'
@@ -109,7 +109,7 @@ cp go.mod.orig go.mod
 go mod edit -require golang.org/x/text@v1.0.0-20170915032832-14c0d48ead0c
 cd outside
 ! go list -m golang.org/x/text
-stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v1.0.0-20170915032832-14c0d48ead0c: invalid pseudo-version: major version without preceding tag must be v0, not v1'
+stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v1.0.0-20170915032832-14c0d48ead0c: invalid pseudo-version: major version without preceding tag must be v0, not v1'
 cd ..
 ! go list -m golang.org/x/text
 stderr 'golang.org/x/text@v1.0.0-20170915032832-14c0d48ead0c: invalid pseudo-version: major version without preceding tag must be v0, not v1'
@@ -120,7 +120,7 @@ cp go.mod.orig go.mod
 go mod edit -require golang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c
 cd outside
 ! go list -m golang.org/x/text
-stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c: invalid pseudo-version: version before v0.0.0 would have negative patch number'
+stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c: invalid pseudo-version: version before v0.0.0 would have negative patch number'
 cd ..
 ! go list -m golang.org/x/text
 stderr 'golang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c: invalid pseudo-version: version before v0.0.0 would have negative patch number'
@@ -130,7 +130,7 @@ stderr 'golang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c: invalid pseudo-v
 go mod edit -replace golang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c=golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c
 cd outside
 ! go list -m golang.org/x/text
-stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c: invalid pseudo-version: version before v0.0.0 would have negative patch number'
+stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c: invalid pseudo-version: version before v0.0.0 would have negative patch number'
 cd ..
 go list -m golang.org/x/text
 stdout 'golang.org/x/text v0.0.0-0.20170915032832-14c0d48ead0c => golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c'
@@ -153,7 +153,7 @@ cp go.mod.orig go.mod
 go mod edit -require golang.org/x/text@v0.2.1-0.20170915032832-14c0d48ead0c
 cd outside
 ! go list -m golang.org/x/text
-stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.2.1-0.20170915032832-14c0d48ead0c: invalid pseudo-version: revision 14c0d48ead0c is not a descendent of preceding tag \(v0.2.0\)'
+stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.2.1-0.20170915032832-14c0d48ead0c: invalid pseudo-version: revision 14c0d48ead0c is not a descendent of preceding tag \(v0.2.0\)'
 cd ..
 ! go list -m golang.org/x/text
 stderr 'golang.org/x/text@v0.2.1-0.20170915032832-14c0d48ead0c: invalid pseudo-version: revision 14c0d48ead0c is not a descendent of preceding tag \(v0.2.0\)'
@@ -163,7 +163,7 @@ cp go.mod.orig go.mod
 go mod edit -require golang.org/x/text@v0.2.1-0.20171213102548-c4d099d611ac
 cd outside
 ! go list -m golang.org/x/text
-stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.2.1-0.20171213102548-c4d099d611ac: invalid pseudo-version: tag \(v0.2.0\) found on revision c4d099d611ac is already canonical, so should not be replaced with a pseudo-version derived from that tag'
+stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.2.1-0.20171213102548-c4d099d611ac: invalid pseudo-version: tag \(v0.2.0\) found on revision c4d099d611ac is already canonical, so should not be replaced with a pseudo-version derived from that tag'
 cd ..
 ! go list -m golang.org/x/text
 stderr 'golang.org/x/text@v0.2.1-0.20171213102548-c4d099d611ac: invalid pseudo-version: tag \(v0.2.0\) found on revision c4d099d611ac is already canonical, so should not be replaced with a pseudo-version derived from that tag'
@@ -173,7 +173,7 @@ cp go.mod.orig go.mod
 go mod edit -require golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0c+incompatible
 cd outside
 ! go list -m golang.org/x/text
-stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0c\+incompatible: invalid version: \+incompatible suffix not allowed: major version v0 is compatible'
+stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0c\+incompatible: invalid version: \+incompatible suffix not allowed: major version v0 is compatible'
 cd ..
 ! go list -m golang.org/x/text
 stderr 'golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0c\+incompatible: invalid version: \+incompatible suffix not allowed: major version v0 is compatible'
@@ -194,7 +194,7 @@ cp go.mod.orig go.mod
 go mod edit -require github.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d+incompatible
 cd outside
 ! go list -m github.com/pierrec/lz4
-stderr 'go: example.com@v0.0.0 requires\n\tgithub.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required'
+stderr 'go list -m: example.com@v0.0.0 requires\n\tgithub.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required'
 cd ..
 ! go list -m github.com/pierrec/lz4
 stderr 'github.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required'
diff --git a/libgo/go/cmd/go/testdata/script/mod_lazy_consistency.txt b/libgo/go/cmd/go/testdata/script/mod_lazy_consistency.txt
new file mode 100644 (file)
index 0000000..1bf3e31
--- /dev/null
@@ -0,0 +1,95 @@
+# If the root requirements in a lazy module are inconsistent
+# (for example, due to a bad hand-edit or git merge),
+# they can go unnoticed as long as the module with the violated
+# requirement is not used.
+# When we load a package from that module, we should spot-check its
+# requirements and either emit an error or update the go.mod file.
+
+cp go.mod go.mod.orig
+
+
+# If we load package x from x.1, we only check the requirements of x,
+# which are fine: loading succeeds.
+
+go list -deps ./usex
+stdout '^example.net/x$'
+cmp go.mod go.mod.orig
+
+
+# However, if we load needx2, we should load the requirements of needx2.
+# Those requirements indicate x.2, not x.1, so the module graph is
+# inconsistent and needs to be fixed.
+
+! go list -deps ./useneedx2
+stderr '^go: updates to go.mod needed; to update it:\n\tgo mod tidy$'
+
+! go list -deps example.net/needx2
+stderr '^go: updates to go.mod needed; to update it:\n\tgo mod tidy$'
+
+
+# The command printed in the error message should fix the problem.
+
+go mod tidy
+go list -deps ./useneedx2
+stdout '^example.net/m/useneedx2$'
+stdout '^example.net/needx2$'
+stdout '^example.net/x$'
+
+go list -m all
+stdout '^example.net/needx2 v0\.1\.0 '
+stdout '^example.net/x v0\.2\.0 '
+
+
+-- go.mod --
+module example.net/m
+
+go 1.17
+
+require (
+       example.net/needx2 v0.1.0
+       example.net/x v0.1.0
+)
+
+replace (
+       example.net/needx2 v0.1.0 => ./needx2.1
+       example.net/x v0.1.0 => ./x.1
+       example.net/x v0.2.0 => ./x.2
+)
+-- useneedx2/useneedx2.go --
+package useneedx2
+
+import _ "example.net/needx2"
+-- usex/usex.go --
+package usex
+
+import _ "example.net/x"
+
+-- x.1/go.mod --
+module example.com/x
+
+go 1.17
+-- x.1/x.go --
+package x
+
+-- x.2/go.mod --
+module example.com/x
+
+go 1.17
+-- x.2/x.go --
+package x
+
+const AddedInV2 = true
+
+-- needx2.1/go.mod --
+module example.com/x
+
+go 1.17
+
+require example.net/x v0.2.0
+-- needx2.1/needx2.go --
+// Package needx2 needs x v0.2.0 or higher.
+package needx2
+
+import "example.net/x"
+
+var _ = x.AddedInV2
diff --git a/libgo/go/cmd/go/testdata/script/mod_lazy_downgrade.txt b/libgo/go/cmd/go/testdata/script/mod_lazy_downgrade.txt
new file mode 100644 (file)
index 0000000..2f815fe
--- /dev/null
@@ -0,0 +1,183 @@
+# This test illustrates the interaction between lazy loading and downgrading in
+# 'go get'.
+
+# The package import graph used in this test looks like:
+#
+# lazy ---- a
+#           |
+#           a_test ---- b
+#                       b_test ---- c
+#
+# The module dependency graph initially looks like:
+#
+# lazy ---- a.1 ---- b.1 ---- c.1
+#      \                     /
+#        b.3 ---- c.2    b.2
+#
+# (Note that lazy loading will prune out the dependency from b.1 on c.1.)
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod.orig go.mod
+
+go list -m all
+stdout '^example.com/a v0.1.0 '
+stdout '^example.com/b v0.3.0 '
+stdout '^example.com/c v0.2.0 '
+
+# Downgrading c should also downgrade the b that requires it.
+
+go get -d example.com/c@v0.1.0
+go list -m all
+stdout '^example.com/a v0.1.0 '
+stdout '^example.com/b v0.2.0 '
+stdout '^example.com/c v0.1.0 '
+
+# Removing c entirely should also remove the a and b that require it.
+
+go get -d example.com/c@none
+go list -m all
+! stdout '^example.com/a '
+! stdout '^example.com/b '
+! stdout '^example.com/c '
+
+
+# With lazy loading, downgrading c should work the same way, but dependencies
+# outside of the deepening scan should not affect the downgrade.
+
+cp go.mod.orig go.mod
+go mod edit -go=1.17
+
+go list -m all
+stdout '^example.com/a v0.1.0 '
+stdout '^example.com/b v0.3.0 '
+stdout '^example.com/c v0.2.0 '
+
+go get -d example.com/c@v0.1.0
+go list -m all
+stdout '^example.com/a v0.1.0 '
+stdout '^example.com/b v0.2.0 '
+stdout '^example.com/c v0.1.0 '
+
+# At this point, b.2 is still an explicit root, so its dependency on c
+# is still tracked, and it will still be downgraded away if we remove c.
+# ('go get' never makes a root into a non-root. Only 'go mod tidy' does that.)
+
+go get -d example.com/c@none
+go list -m all
+! stdout '^example.com/a '
+! stdout '^example.com/b '
+! stdout '^example.com/c '
+
+
+# This time, we drop the explicit 'b' root by downgrading it to v0.1.0
+# (the version required by a.1) and running 'go mod tidy'.
+# It is still selected at v0.1.0 (as a dependency of a),
+# but its dependency on c is now pruned from the module graph, so it doesn't
+# result in any downgrades to b or a if we run 'go get c@none'.
+
+cp go.mod.orig go.mod
+go mod edit -go=1.17
+
+go list -m all
+stdout '^example.com/a v0.1.0 '
+stdout '^example.com/b v0.3.0 '
+stdout '^example.com/c v0.2.0 '
+
+go get -d example.com/c@v0.1.0 example.com/b@v0.1.0
+go list -m all
+stdout '^example.com/a v0.1.0 '
+stdout '^example.com/b v0.1.0 '
+stdout '^example.com/c v0.1.0 '
+
+go mod tidy
+go list -m all
+stdout '^example.com/a v0.1.0 '
+stdout '^example.com/b v0.1.0 '
+! stdout '^example.com/c '
+
+go get -d example.com/c@none
+go list -m all
+stdout '^example.com/a v0.1.0'
+stdout '^example.com/b v0.1.0'
+! stdout '^example.com/c '
+
+
+-- go.mod --
+module example.com/lazy
+
+go 1.15
+
+require (
+       example.com/a v0.1.0
+       example.com/b v0.3.0 // indirect
+)
+
+replace (
+       example.com/a v0.1.0 => ./a
+       example.com/b v0.1.0 => ./b1
+       example.com/b v0.2.0 => ./b2
+       example.com/b v0.3.0 => ./b3
+       example.com/c v0.1.0 => ./c
+       example.com/c v0.2.0 => ./c
+)
+-- lazy.go --
+package lazy
+
+import _ "example.com/a"
+
+-- a/go.mod --
+module example.com/a
+
+go 1.17
+
+require example.com/b v0.1.0
+-- a/a.go --
+package a
+-- a/a_test.go --
+package a_test
+
+import _ "example.com/b"
+
+-- b1/go.mod --
+module example.com/b
+
+go 1.17
+
+require example.com/c v0.1.0
+-- b1/b.go --
+package b
+-- b1/b_test.go --
+package b_test
+import _ "example.com/c"
+
+-- b2/go.mod --
+module example.com/b
+
+go 1.17
+
+require example.com/c v0.1.0
+-- b2/b.go --
+package b
+-- b2/b_test.go --
+package b_test
+import _ "example.com/c"
+
+-- b3/go.mod --
+module example.com/b
+
+go 1.17
+
+require example.com/c v0.2.0
+-- b3/b.go --
+package b
+-- b3/b_test.go --
+package b_test
+import _ "example.com/c"
+
+-- c/go.mod --
+module example.com/c
+
+go 1.17
+-- c/c.go --
+package c
diff --git a/libgo/go/cmd/go/testdata/script/mod_lazy_import_allmod.txt b/libgo/go/cmd/go/testdata/script/mod_lazy_import_allmod.txt
new file mode 100644 (file)
index 0000000..97718c4
--- /dev/null
@@ -0,0 +1,191 @@
+# This test demonstrates dependency resolution when the main module imports a
+# new package from a previously-test-only dependency.
+#
+# When lazy loading is active, the loader will not load dependencies of any
+# module whose packages are *only* imported by tests outside the main module. If
+# the main module is changed to import a package from such a module, the
+# dependencies of that module will need to be reloaded.
+
+# The import graph used in this test looks like:
+#
+# m ---- a
+#  \     |
+#   \    a_test ---- b/x
+#    \
+#      --------------b/y (new) ---- c
+#
+# Where b/x and b/y are disjoint packages, but both contained in module b.
+#
+# The module dependency graph initially looks like:
+#
+# m ---- a.1 ---- b.1 ---- c.1
+#
+# This configuration is similar to that used in mod_lazy_new_import,
+# but the new import is from what is initially a test-only dependency.
+
+# Control case: in Go 1.14, the original go.mod is tidy,
+# and the dependency on c is eagerly loaded.
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod.orig go.mod
+
+go list -m all
+stdout '^a v0.1.0 '
+stdout '^b v0.1.0 '
+stdout '^c v0.1.0 '
+
+# After adding a new import of b/y,
+# the import of c from b/y should resolve to the version required by b.
+
+cp m.go m.go.orig
+cp m.go.new m.go
+go mod tidy
+cmp go.mod.new go.mod
+
+go list -m all
+stdout '^a v0.1.0 '
+stdout '^b v0.1.0 '
+stdout '^c v0.1.0 '
+
+# With lazy loading, the go.mod requirements are the same,
+# but the dependency on c is initially pruned out.
+
+cp m.go.orig m.go
+cp go.mod.orig go.mod
+go mod edit -go=1.17
+go mod edit -go=1.17 go.mod.new
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod.orig go.mod
+
+go list -m all
+stdout '^a v0.1.0 '
+stdout '^b v0.1.0 '
+! stdout '^c '
+
+# After adding a new direct import of b/y,
+# the existing verison of b should be promoted to a root,
+# bringing the version of c required by b into the build list.
+
+cp m.go.new m.go
+go mod tidy
+cmp go.mod.lazy go.mod
+
+go list -m all
+stdout '^a v0.1.0 '
+stdout '^b v0.1.0 '
+stdout '^c v0.1.0 '
+
+-- m.go --
+package main
+
+import (
+       "fmt"
+
+       _ "a"  // a_test imports b/x.
+)
+
+func main() {
+}
+-- m.go.new --
+package main
+
+import (
+       "fmt"
+
+       _ "a"  // a_test imports b/x.
+       "b/y"  // This is a new import, not yet reflected in the go.mod file.
+)
+
+func main() {
+       fmt.Println(b.CVersion())
+}
+-- go.mod --
+module m
+
+go 1.14
+
+require a v0.1.0
+
+replace (
+       a v0.1.0 => ./a1
+       b v0.1.0 => ./b1
+       c v0.1.0 => ./c1
+       c v0.2.0 => ./c2
+)
+-- go.mod.new --
+module m
+
+go 1.14
+
+require (
+       a v0.1.0
+       b v0.1.0
+)
+
+replace (
+       a v0.1.0 => ./a1
+       b v0.1.0 => ./b1
+       c v0.1.0 => ./c1
+       c v0.2.0 => ./c2
+)
+-- go.mod.lazy --
+module m
+
+go 1.17
+
+require (
+       a v0.1.0
+       b v0.1.0
+)
+
+require c v0.1.0 // indirect
+
+replace (
+       a v0.1.0 => ./a1
+       b v0.1.0 => ./b1
+       c v0.1.0 => ./c1
+       c v0.2.0 => ./c2
+)
+-- a1/go.mod --
+module a
+
+go 1.17
+
+require b v0.1.0
+-- a1/a.go --
+package a
+-- a1/a_test.go --
+package a_test
+
+import _ "b/x"
+-- b1/go.mod --
+module b
+
+go 1.17
+
+require c v0.1.0
+-- b1/x/x.go --
+package x
+-- b1/y/y.go --
+package y
+
+import "c"
+
+func CVersion() string {
+       return c.Version
+}
+-- c1/go.mod --
+module c
+
+go 1.17
+-- c1/c.go --
+package c
+
+const Version = "v0.1.0"
+-- c2/go.mod --
+This file should be unused.
+-- c2/c.go --
+This file should be unused.
diff --git a/libgo/go/cmd/go/testdata/script/mod_lazy_new_import.txt b/libgo/go/cmd/go/testdata/script/mod_lazy_new_import.txt
new file mode 100644 (file)
index 0000000..4272a52
--- /dev/null
@@ -0,0 +1,155 @@
+# This test illustrates the use of a deepening scan to resolve transitive
+# imports of imports of new packages from within existing dependencies.
+
+# The package import graph used in this test looks like:
+#
+# lazy ---- a/x ---- b
+#     \
+#      ---- a/y (new) ---- c
+#
+# Where a/x and x/y are disjoint packages, but both contained in module a.
+#
+# The module dependency graph initially looks like:
+#
+# lazy ---- a.1 ---- b.1
+#              \
+#               c.1
+
+
+cp go.mod go.mod.old
+cp lazy.go lazy.go.old
+go mod tidy
+cmp go.mod go.mod.old
+
+# Before adding a new import, the go.mod file should
+# enumerate modules for all packages already imported.
+go list all
+cmp go.mod go.mod.old
+
+# When we add a new import of a package in an existing dependency,
+# and that dependency is already tidy, its transitive dependencies
+# should already be present.
+cp lazy.go.new lazy.go
+go list all
+go list -m all
+stdout '^example.com/c v0.1.0' # not v0.2.0 as would be resolved by 'latest'
+cmp go.mod go.mod.old
+
+# Now, we repeat the test with a lazy main module.
+cp lazy.go.old lazy.go
+cp go.mod.117 go.mod
+
+# Before adding a new import, the go.mod file should
+# enumerate modules for all packages already imported.
+go list all
+cmp go.mod go.mod.117
+
+# When a new import is found, we should perform a deepening scan of the existing
+# dependencies and add a requirement on the version required by those
+# dependencies — not re-resolve 'latest'.
+cp lazy.go.new lazy.go
+
+! go list all
+stderr '^go: updates to go.mod needed; to update it:\n\tgo mod tidy$'
+
+go mod tidy
+go list all
+go list -m all
+stdout '^example.com/c v0.1.0' # not v0.2.0 as would be resolved by 'latest'
+
+cmp go.mod go.mod.new
+
+
+-- go.mod --
+module example.com/lazy
+
+go 1.15
+
+require example.com/a v0.1.0
+
+replace (
+       example.com/a v0.1.0 => ./a
+       example.com/b v0.1.0 => ./b
+       example.com/c v0.1.0 => ./c1
+       example.com/c v0.2.0 => ./c2
+)
+-- go.mod.117 --
+module example.com/lazy
+
+go 1.17
+
+require example.com/a v0.1.0
+
+require example.com/b v0.1.0 // indirect
+
+replace (
+       example.com/a v0.1.0 => ./a
+       example.com/b v0.1.0 => ./b
+       example.com/c v0.1.0 => ./c1
+       example.com/c v0.2.0 => ./c2
+)
+-- go.mod.new --
+module example.com/lazy
+
+go 1.17
+
+require example.com/a v0.1.0
+
+require (
+       example.com/b v0.1.0 // indirect
+       example.com/c v0.1.0 // indirect
+)
+
+replace (
+       example.com/a v0.1.0 => ./a
+       example.com/b v0.1.0 => ./b
+       example.com/c v0.1.0 => ./c1
+       example.com/c v0.2.0 => ./c2
+)
+-- lazy.go --
+package lazy
+
+import (
+       _ "example.com/a/x"
+)
+-- lazy.go.new --
+package lazy
+
+import (
+       _ "example.com/a/x"
+       _ "example.com/a/y"
+)
+-- a/go.mod --
+module example.com/a
+
+go 1.15
+
+require (
+       example.com/b v0.1.0
+       example.com/c v0.1.0
+)
+-- a/x/x.go --
+package x
+import _ "example.com/b"
+-- a/y/y.go --
+package y
+import _ "example.com/c"
+-- b/go.mod --
+module example.com/b
+
+go 1.15
+-- b/b.go --
+package b
+-- c1/go.mod --
+module example.com/c
+
+go 1.15
+-- c1/c.go --
+package c
+-- c2/go.mod --
+module example.com/c
+
+go 1.15
+-- c2/c.go --
+package c
+This file should not be used, so this syntax error should be ignored.
diff --git a/libgo/go/cmd/go/testdata/script/mod_lazy_test_horizon.txt b/libgo/go/cmd/go/testdata/script/mod_lazy_test_horizon.txt
new file mode 100644 (file)
index 0000000..7d07eb6
--- /dev/null
@@ -0,0 +1,131 @@
+# This file demonstrates the effect of lazy loading on the selected
+# versions of test dependencies.
+
+# The package import graph used in this test looks like:
+#
+# m ---- a
+#  \     |
+#   \    a_test ---- b
+#    \               |
+#     x              b_test
+#     |                    \
+#     x_test -------------- c
+#
+# And the module dependency graph looks like:
+#
+# m -- a.1 -- b.1 -- c.2
+#  \
+#   x.1 ------------ c.1
+
+# Control case: in Go 1.15, the version of c imported by 'go test x' is the
+# version required by module b, even though b_test is not relevant to the main
+# module. (The main module imports a, and a_test imports b, but all of the
+# packages and tests in the main module can be built without b.)
+
+go list -m c
+stdout '^c v0.2.0 '
+
+[!short] go test -v x
+[!short] stdout ' c v0.2.0$'
+
+# With lazy loading, the go.mod requirements are the same,
+# but the irrelevant dependency on c v0.2.0 should be pruned out,
+# leaving only the relevant dependency on c v0.1.0.
+
+go mod edit -go=1.17
+go list -m c
+stdout '^c v0.1.0'
+
+[!short] go test -v x
+[!short] stdout ' c v0.1.0$'
+
+-- m.go --
+package m
+
+import (
+       _ "a"
+       _ "x"
+)
+-- go.mod --
+module m
+
+go 1.15
+
+require (
+       a v0.1.0
+       x v0.1.0
+)
+
+replace (
+       a v0.1.0 => ./a1
+       b v0.1.0 => ./b1
+       c v0.1.0 => ./c1
+       c v0.2.0 => ./c2
+       x v0.1.0 => ./x1
+)
+-- a1/go.mod --
+module a
+
+go 1.17
+
+require b v0.1.0
+-- a1/a.go --
+package a
+-- a1/a_test.go --
+package a_test
+
+import _ "b"
+-- b1/go.mod --
+module b
+
+go 1.17
+
+require c v0.2.0
+-- b1/b.go --
+package b
+-- b1/b_test.go --
+package b_test
+
+import (
+       "c"
+       "testing"
+)
+
+func TestCVersion(t *testing.T) {
+       t.Log(c.Version)
+}
+-- c1/go.mod --
+module c
+
+go 1.17
+-- c1/c.go --
+package c
+
+const Version = "v0.1.0"
+-- c2/go.mod --
+module c
+
+go 1.17
+-- c2/c.go --
+package c
+
+const Version = "v0.2.0"
+-- x1/go.mod --
+module x
+
+go 1.17
+
+require c v0.1.0
+-- x1/x.go --
+package x
+-- x1/x_test.go --
+package x_test
+
+import (
+       "c"
+       "testing"
+)
+
+func TestCVersion(t *testing.T) {
+       t.Log("c", c.Version)
+}
diff --git a/libgo/go/cmd/go/testdata/script/mod_lazy_test_of_test_dep.txt b/libgo/go/cmd/go/testdata/script/mod_lazy_test_of_test_dep.txt
new file mode 100644 (file)
index 0000000..68a5b6d
--- /dev/null
@@ -0,0 +1,224 @@
+# This file demonstrates the effect of lazy loading on the reproducibility of
+# tests (and tests of test dependencies) outside the main module.
+#
+# It is similar to the cases in mod_all.txt and mod_lazy_test_horizon.txt, but
+# focuses on the effect of "go test" on specific packages instead of the "all"
+# pattern.
+
+# The package import graph used in this test looks like:
+#
+# lazy ---- a
+#           |
+#           a_test ---- b
+#                       |
+#                       b_test ---- c
+#
+# And the non-lazy module dependency graph looks like:
+#
+# lazy ---- a.1 ---- b.1 ---- c.1
+
+cp go.mod go.mod.old
+go mod tidy
+cmp go.mod go.mod.old
+
+
+# In Go 1.15 mode, 'go list -m all' includes modules needed by the
+# transitive closure of tests of dependencies of tests of dependencies of ….
+
+go list -m all
+stdout '^example.com/b v0.1.0 '
+stdout '^example.com/c v0.1.0 '
+cmp go.mod go.mod.old
+
+# 'go test' (or equivalent) of any such dependency, no matter how remote, does
+# not update the go.mod file.
+
+go list -test -deps example.com/a
+stdout example.com/b
+! stdout example.com/c
+
+[!short] go test -c -o $devnull example.com/a
+[!short] cmp go.mod go.mod.old
+
+go list -test -deps example.com/b
+stdout example.com/c
+
+[!short] go test -c -o $devnull example.com/b
+[!short] cmp go.mod go.mod.old
+
+go mod edit -go=1.17 a/go.mod
+go mod edit -go=1.17 b1/go.mod
+go mod edit -go=1.17 b2/go.mod
+go mod edit -go=1.17 c1/go.mod
+go mod edit -go=1.17 c2/go.mod
+go mod edit -go=1.17
+
+
+# After changing to 'go 1.17` uniformly, 'go list -m all' should prune out
+# example.com/c, because it is not imported by any package (or test of a package)
+# transitively imported by the main module.
+#
+# example.com/a is imported,
+# and example.com/b is needed in order to run 'go test example.com/a',
+# but example.com/c is not needed because we don't expect the user to need to run
+# 'go test example.com/b'.
+
+# If we skip directly to adding a new import of c, the dependency is too far
+# away for a deepening scan to find, which is fine because the package whose
+# test imported it wasn't even it "all". It should resolve from the latest
+# version of its module.
+
+# However, if we reach c by running successive tests starting from the main
+# module, we should end up with exactly the version required by b, with an update
+# to the go.mod file as soon as we test a test dependency that is not itself in
+# "all".
+
+cp go.mod go.mod.117
+go mod tidy
+cmp go.mod go.mod.117
+
+go list -m all
+stdout '^example.com/b v0.1.0 '
+! stdout '^example.com/c '
+
+# 'go test' of a package (transitively) imported by the main module
+# should work without changes to the go.mod file.
+
+go list -test -deps example.com/a
+stdout example.com/b
+! stdout example.com/c
+
+[!short] go test -c -o $devnull example.com/a
+
+# However, 'go test' of a package that is itself a dependency should require an
+# update to the go.mod file.
+! go list -test -deps example.com/b
+
+       # TODO(#36460): The hint here is wrong. We should suggest
+       # 'go get -t example.com/b@v0.1.0' instead of 'go mod tidy'.
+stderr '^go: updates to go\.mod needed; to update it:\n\tgo mod tidy$'
+
+[!short] ! go test -c -o $devnull example.com/b
+[!short] stderr '^go: updates to go\.mod needed; to update it:\n\tgo mod tidy$'
+
+go get -t example.com/b@v0.1.0
+go list -test -deps example.com/b
+stdout example.com/c
+
+[!short] go test -c -o $devnull example.com/b
+
+# The update should bring the version required by b, not the latest version of c.
+
+go list -m example.com/c
+stdout '^example.com/c v0.1.0 '
+
+cmp go.mod go.mod.b
+
+
+# We should reach the same state if we arrive at it via `go test -mod=mod`.
+
+cp go.mod.117 go.mod
+
+[short] go list -mod=mod -test -deps example.com/a
+[!short] go test -mod=mod -c -o $devnull example.com/a
+
+[short] go list -mod=mod -test -deps example.com/b
+[!short] go test -mod=mod -c -o $devnull example.com/b
+
+cmp go.mod go.mod.b
+
+
+
+-- go.mod --
+module example.com/lazy
+
+go 1.15
+
+require example.com/a v0.1.0
+
+replace (
+       example.com/a v0.1.0 => ./a
+       example.com/b v0.1.0 => ./b1
+       example.com/b v0.2.0 => ./b2
+       example.com/c v0.1.0 => ./c1
+       example.com/c v0.2.0 => ./c2
+)
+-- go.mod.b --
+module example.com/lazy
+
+go 1.17
+
+require example.com/a v0.1.0
+
+require example.com/b v0.1.0 // indirect
+
+replace (
+       example.com/a v0.1.0 => ./a
+       example.com/b v0.1.0 => ./b1
+       example.com/b v0.2.0 => ./b2
+       example.com/c v0.1.0 => ./c1
+       example.com/c v0.2.0 => ./c2
+)
+-- lazy.go --
+package lazy
+
+import (
+       _ "example.com/a"
+)
+-- a/go.mod --
+module example.com/a
+
+go 1.15
+
+require example.com/b v0.1.0
+-- a/a.go --
+package a
+-- a/a_test.go --
+package a
+
+import (
+       "testing"
+
+       _ "example.com/b"
+)
+
+func TestUsingB(t *testing.T) {
+       // …
+}
+-- b1/go.mod --
+module example.com/b
+
+go 1.15
+
+require example.com/c v0.1.0
+-- b1/b.go --
+package b
+-- b1/b_test.go --
+package b
+
+import _ "example.com/c"
+-- b2/go.mod --
+module example.com/b
+
+go 1.15
+
+require example.com/c v0.1.0
+-- b2/b.go --
+package b
+This file should not be used, so this syntax error should be ignored.
+-- b2/b_test.go --
+package b
+This file should not be used, so this syntax error should be ignored.
+-- c1/go.mod --
+module example.com/c
+
+go 1.15
+-- c1/c.go --
+package c
+-- c2/go.mod --
+module example.com/c
+
+go 1.15
+-- c2/c.go --
+package c
+This file should not be used, so this syntax error should be ignored.
index 1ba6d7c910e8c88bbbd45ce22d2e8f6612408386..239c7caa4a2246e87eaaef22b2ace9ce6ba800dc 100644 (file)
@@ -29,7 +29,8 @@ stdout 'v1.3.0.*mod[\\/]rsc.io[\\/]sampler@v1.3.1 .*[\\/]v1.3.1.mod => v1.3.1.*s
 go list std
 stdout ^math/big
 
-# rsc.io/quote/buggy should be listable as a package
+# rsc.io/quote/buggy should be listable as a package,
+# even though it is only a test.
 go list -mod=mod rsc.io/quote/buggy
 
 # rsc.io/quote/buggy should not be listable as a module
diff --git a/libgo/go/cmd/go/testdata/script/mod_list_deprecated.txt b/libgo/go/cmd/go/testdata/script/mod_list_deprecated.txt
new file mode 100644 (file)
index 0000000..f0ecbba
--- /dev/null
@@ -0,0 +1,52 @@
+# 'go list pkg' does not show deprecation.
+go list example.com/deprecated/a
+stdout '^example.com/deprecated/a$'
+
+# 'go list -m' does not show deprecation.
+go list -m example.com/deprecated/a
+stdout '^example.com/deprecated/a v1.9.0$'
+
+# 'go list -m -versions' does not show deprecation.
+go list -m -versions example.com/deprecated/a
+stdout '^example.com/deprecated/a v1.0.0 v1.9.0$'
+
+# 'go list -m -u' shows deprecation.
+go list -m -u example.com/deprecated/a
+stdout '^example.com/deprecated/a v1.9.0 \(deprecated\)$'
+
+# 'go list -m -u -f' exposes the deprecation message.
+go list -m -u -f {{.Deprecated}} example.com/deprecated/a
+stdout '^in example.com/deprecated/a@v1.9.0$'
+
+# This works even if we use an old version that does not have the deprecation
+# message in its go.mod file.
+go get -d example.com/deprecated/a@v1.0.0
+! grep Deprecated: $WORK/gopath/pkg/mod/cache/download/example.com/deprecated/a/@v/v1.0.0.mod
+go list -m -u -f {{.Deprecated}} example.com/deprecated/a
+stdout '^in example.com/deprecated/a@v1.9.0$'
+
+# 'go list -m -u' does not show deprecation for the main module.
+go list -m -u
+! stdout deprecated
+go list -m -u -f '{{if not .Deprecated}}ok{{end}}'
+stdout ok
+
+# 'go list -m -u' does not show a deprecation message for a module that is not
+# deprecated at the latest version, even if it is deprecated at the current
+# version.
+go list -m -u example.com/undeprecated
+stdout '^example.com/undeprecated v1.0.0 \[v1.0.1\]$'
+-- go.mod --
+// Deprecated: main module is deprecated, too!
+module example.com/use
+
+go 1.17
+
+require (
+       example.com/deprecated/a v1.9.0
+       example.com/undeprecated v1.0.0
+)
+-- go.sum --
+example.com/deprecated/a v1.9.0 h1:pRyvBIZheJpQVVnNW4Fdg8QuoqDgtkCreqZZbASV3BE=
+example.com/deprecated/a v1.9.0/go.mod h1:Z1uUVshSY9kh6l/2hZ8oA9SBviX2yfaeEpcLDz6AZwY=
+example.com/undeprecated v1.0.0/go.mod h1:1qiRbdA9VzJXDqlG26Y41O5Z7YyO+jAD9do8XCZQ+Gg=
diff --git a/libgo/go/cmd/go/testdata/script/mod_list_deprecated_replace.txt b/libgo/go/cmd/go/testdata/script/mod_list_deprecated_replace.txt
new file mode 100644 (file)
index 0000000..48b991f
--- /dev/null
@@ -0,0 +1,68 @@
+# When all versions are replaced, we should not look up a deprecation message.
+# We will still look up a deprecation message for the replacement.
+cp go.mod.allreplaced go.mod
+go list -m -u -f '{{.Path}}@{{.Version}} <{{.Deprecated}}>{{with .Replace}} => {{.Path}}@{{.Version}} <{{.Deprecated}}>{{end}}' all
+stdout '^example.com/deprecated/a@v1.0.0 <> => example.com/deprecated/b@v1.0.0 <in example.com/deprecated/b@v1.9.0>$'
+
+# When one version is replaced, we should see a deprecation message.
+cp go.mod.onereplaced go.mod
+go list -m -u -f '{{.Path}}@{{.Version}} <{{.Deprecated}}>{{with .Replace}} => {{.Path}}@{{.Version}} <{{.Deprecated}}>{{end}}' all
+stdout '^example.com/deprecated/a@v1.0.0 <in example.com/deprecated/a@v1.9.0> => example.com/deprecated/b@v1.0.0 <in example.com/deprecated/b@v1.9.0>$'
+
+# If the replacement is a directory, we won't look that up.
+cp go.mod.dirreplacement go.mod
+go list -m -u -f '{{.Path}}@{{.Version}} <{{.Deprecated}}>{{with .Replace}} => {{.Path}}@{{.Version}} <{{.Deprecated}}>{{end}}' all
+stdout '^example.com/deprecated/a@v1.0.0 <> => ./a@ <>$'
+
+# If the latest version of the replacement is replaced, we'll use the content
+# from that replacement.
+cp go.mod.latestreplaced go.mod
+go list -m -u -f '{{.Path}}@{{.Version}} <{{.Deprecated}}>{{with .Replace}} => {{.Path}}@{{.Version}} <{{.Deprecated}}>{{end}}' all
+stdout '^example.com/deprecated/a@v1.0.0 <> => example.com/deprecated/b@v1.0.0 <in ./b>$'
+
+-- go.mod.allreplaced --
+module m
+
+go 1.17
+
+require example.com/deprecated/a v1.0.0
+
+replace example.com/deprecated/a => example.com/deprecated/b v1.0.0
+-- go.mod.onereplaced --
+module m
+
+go 1.17
+
+require example.com/deprecated/a v1.0.0
+
+replace example.com/deprecated/a v1.0.0 => example.com/deprecated/b v1.0.0
+-- go.mod.dirreplacement --
+module m
+
+go 1.17
+
+require example.com/deprecated/a v1.0.0
+
+replace example.com/deprecated/a => ./a
+-- go.mod.latestreplaced --
+module m
+
+go 1.17
+
+require example.com/deprecated/a v1.0.0
+
+replace (
+       example.com/deprecated/a => example.com/deprecated/b v1.0.0
+       example.com/deprecated/b v1.9.0 => ./b
+)
+-- go.sum --
+example.com/deprecated/b v1.0.0/go.mod h1:b19J9ywRGviY7Nq4aJ1WBJ+A7qUlEY9ihp22yI4/F6M=
+-- a/go.mod --
+module example.com/deprecated/a
+
+go 1.17
+-- b/go.mod --
+// Deprecated: in ./b
+module example.com/deprecated/b
+
+go 1.17
diff --git a/libgo/go/cmd/go/testdata/script/mod_list_retract.txt b/libgo/go/cmd/go/testdata/script/mod_list_retract.txt
new file mode 100644 (file)
index 0000000..4b13348
--- /dev/null
@@ -0,0 +1,108 @@
+# 'go list -mod=vendor -retracted' reports an error.
+go mod vendor
+! go list -m -retracted -mod=vendor
+stderr '^go list -retracted cannot be used when vendoring is enabled$'
+rm vendor
+
+# 'go list -retracted' reports an error in GOPATH mode.
+env GO111MODULE=off
+! go list -retracted
+stderr '^go list -retracted can only be used in module-aware mode$'
+env GO111MODULE=
+
+# 'go list pkg' does not show retraction.
+go list -f '{{with .Module}}{{with .Retracted}}retracted{{end}}{{end}}' example.com/retract
+! stdout .
+
+# 'go list -retracted pkg' shows retraction.
+go list -retracted -f '{{with .Module}}{{with .Retracted}}retracted{{end}}{{end}}' example.com/retract
+stdout retracted
+
+# 'go list -m' does not show retraction.
+go list -m -f '{{with .Retracted}}retracted{{end}}' example.com/retract
+! stdout .
+
+# 'go list -m -retracted' shows retraction.
+go list -m -retracted -f '{{with .Retracted}}retracted{{end}}' example.com/retract
+
+# 'go list -m mod@version' does not show retraction.
+go list -m -f '{{with .Retracted}}retracted{{end}}' example.com/retract@v1.0.0-unused
+! stdout .
+
+# 'go list -m -retracted mod@version' does not show an error if the module
+# that would contain the retraction is unavailable. See #45305.
+go list -m -retracted -f '{{.Path}} {{.Version}} {{.Error}}' example.com/retract/missingmod@v1.0.0
+stdout '^example.com/retract/missingmod v1.0.0 <nil>$'
+exists $GOPATH/pkg/mod/cache/download/example.com/retract/missingmod/@v/v1.9.0.info
+! exists $GOPATH/pkg/mod/cache/download/example.com/retract/missingmod/@v/v1.9.0.mod
+
+# 'go list -m -retracted mod@version' shows retractions.
+go list -m -retracted example.com/retract@v1.0.0-unused
+stdout '^example.com/retract v1.0.0-unused \(retracted\)$'
+go list -m -retracted -f '{{with .Retracted}}retracted{{end}}' example.com/retract@v1.0.0-unused
+stdout retracted
+
+# 'go list -m mod@latest' selects a previous release version, not self-retracted latest.
+go list -m -f '{{.Version}}{{with .Retracted}} retracted{{end}}' example.com/retract/self/prev@latest
+stdout '^v1.1.0$'
+
+# 'go list -m -retracted mod@latest' selects the self-retracted latest version.
+go list -m -retracted -f '{{.Version}}{{with .Retracted}} retracted{{end}}' example.com/retract/self/prev@latest
+stdout '^v1.9.0 retracted$'
+
+# 'go list -m mod@latest' selects a pre-release version if all release versions are retracted.
+go list -m -f '{{.Version}}{{with .Retracted}} retracted{{end}}' example.com/retract/self/prerelease@latest
+stdout '^v1.9.1-pre$'
+
+# 'go list -m -retracted mod@latest' selects the self-retracted latest version.
+go list -m -retracted -f '{{.Version}}{{with .Retracted}} retracted{{end}}' example.com/retract/self/prerelease@latest
+stdout '^v1.9.0 retracted$'
+
+# 'go list -m mod@latest' selects a pseudo-version if all versions are retracted.
+# TODO(golang.org/issue/24031): the proxy does not expose the pseudo-version,
+# even if all release versions are retracted.
+go list -m -e -f '{{.Error.Err}}' example.com/retract/self/pseudo@latest
+stdout '^module example.com/retract/self/pseudo: no matching versions for query "latest"$'
+
+# 'go list -m mod@latest' reports an error if all versions are retracted.
+go list -m -e -f '{{.Error.Err}}' example.com/retract/self/all@latest
+stdout '^module example.com/retract/self/all: no matching versions for query "latest"$'
+
+# 'go list -m mod@<v1.10' selects a previous release version, not self-retracted latest.
+# The @latest query is not special with respect to retractions.
+go list -m -f '{{.Version}}{{with .Retracted}} retracted{{end}}' example.com/retract/self/prev@<v1.10
+stdout '^v1.1.0$'
+
+# 'go list -m -versions' hides retracted versions.
+go list -m -versions example.com/retract
+stdout '^example.com/retract v1.0.0-good v1.1.0$'
+
+# 'go list -m -retracted -versions' shows retracted versions.
+go list -m -retracted -versions example.com/retract
+stdout '^example.com/retract v1.0.0-bad v1.0.0-good v1.0.0-unused v1.1.0$'
+
+# 'go list -m -u -versions' loads retractions and does not show retracted versions.
+go list -m -u -versions example.com/retract
+stdout '^example.com/retract v1.0.0-good v1.1.0$'
+go list -m -u -versions -f '{{with .Retracted}}retracted{{end}}' example.com/retract
+stdout retracted
+
+# 'go list -m -u' shows retraction.
+go list -m -u -f '{{with .Retracted}}retracted{{end}}' example.com/retract
+stdout retracted
+
+# 'go list -m -u' does not suggest an update to a self-retracted latest version.
+go list -m -u -f '{{with .Update}}{{.Version}}{{with .Retracted}} retracted{{end}}{{end}}' example.com/retract/self/prev@v1.0.0-bad
+stdout '^v1.1.0$'
+
+-- go.mod --
+module example.com/use
+
+go 1.15
+
+require example.com/retract v1.0.0-bad
+
+-- use.go --
+package use
+
+import _ "example.com/retract"
index baf7908ab93d2a946c5a8b4a1cb8c00ad816fdd8..f4e0433d8a0e171f585673c3664306a20fcc49b6 100644 (file)
@@ -48,18 +48,20 @@ stdout ^vendor/golang.org/x/crypto/internal/subtle
 ! stdout ^golang\.org/x
 
 # Within the std module, the dependencies of the non-vendored packages within
-# std should appear to come from modules, but they should be loaded from the
-# vendor directory (just like ordinary vendored module dependencies).
+# std should appear to be packages beginning with 'vendor/', not 'golang.org/…'
+# module dependencies.
 
 go list all
-stdout ^golang.org/x/
+stdout ^golang.org/x/
 ! stdout ^std/
 ! stdout ^cmd/
-stdout ^vendor/
+stdout ^vendor/
 
 go list -deps -f '{{if not .Standard}}{{.ImportPath}}{{end}}' std
-! stdout ^vendor/golang.org/x/net/http2/hpack
-stdout ^golang.org/x/net/http2/hpack
+! stdout .
+
+# However, the 'golang.org/…' module dependencies should resolve to those same
+# directories.
 
 go list -f '{{.Dir}}' golang.org/x/net/http2/hpack
 stdout $GOROOT[/\\]src[/\\]vendor
diff --git a/libgo/go/cmd/go/testdata/script/mod_list_sums.txt b/libgo/go/cmd/go/testdata/script/mod_list_sums.txt
new file mode 100644 (file)
index 0000000..86c528f
--- /dev/null
@@ -0,0 +1,32 @@
+# https://golang.org/issue/41297: 'go list -m' should not require go.sum with
+# -versions or when all args are version queries.
+
+go mod init m
+go mod edit -require=rsc.io/quote@v1.5.1
+
+go list -m -mod=readonly rsc.io/quote@latest
+stdout '^rsc\.io/quote v1\.5\.2$'
+! stderr .
+
+go list -m -mod=readonly -versions rsc.io/quote
+stdout 'rsc\.io/quote v1\.0\.0 .* v1\.5\.3-pre1$'
+! stderr .
+
+# Incidentally fetching the required version of a module records its checksum,
+# just because it happens to be in the build list, and recording the checksum
+# triggers an error under -mod=readonly.
+#
+# TODO(#41297): This should not be an error.
+! go list -m -mod=readonly rsc.io/quote@<v1.5.2
+stderr '^go: updates to go.sum needed, disabled by -mod=readonly$'
+! stderr 'missing go.sum entry'
+
+# Attempting to list the versions of a module that is not a root dependency
+# causes the build list to be resolved (so that the selected version can *also*
+# be identified, even though it is not relevant to this particular output).
+# That, in turn, causes us to need checksums for the go.sum files for the
+# modules in the module graph.
+#
+# TODO(#41297): This should not be an error either.
+! go list -m -mod=readonly -versions rsc.io/sampler
+stderr '^go list -m: rsc\.io/quote@v1\.5\.1: missing go\.sum entry; to add it:\n\tgo mod download rsc\.io/quote$'
diff --git a/libgo/go/cmd/go/testdata/script/mod_list_test_cycle.txt b/libgo/go/cmd/go/testdata/script/mod_list_test_cycle.txt
new file mode 100644 (file)
index 0000000..755e50b
--- /dev/null
@@ -0,0 +1,23 @@
+# https://golang.org/issue/45863: a typo in a test package leading to an
+# import cycle should be diagnosed, instead of causing an infinite loop.
+# The failure mode of this test prior to the fix was a timeout or OOM crash.
+
+go list -e -test -deps ./datastore/sql
+
+-- go.mod --
+module golang.org/issue45863
+
+go 1.17
+-- datastore/datastore_health.go --
+package datastore
+
+import (
+       "golang.org/issue45863/datastore"
+       "golang.org/issue45863/datastore/sql"
+)
+-- datastore/sql/sql.go --
+package sql
+-- datastore/sql/sql_test.go --
+package sql
+
+import _ "golang.org/issue45863/datastore"
diff --git a/libgo/go/cmd/go/testdata/script/mod_list_update_nolatest.txt b/libgo/go/cmd/go/testdata/script/mod_list_update_nolatest.txt
new file mode 100644 (file)
index 0000000..c6bbbb0
--- /dev/null
@@ -0,0 +1,55 @@
+# Check that if a proxy does not have a version of a module that could be
+# an upgrade, 'go list -m -u' still succeeds.
+# We use a local file proxy, since our test proxy doesn't have the behavior
+# we want to test, and we don't want it to be too clever.
+# Verifies #45305, where proxy.golang.org serves an empty /@v/list (200)
+# but has no /@latest (410) because the go.mod at the tip of the default
+# branch has a different major version suffix.
+env testproxy=$GOPROXY
+env GOPROXY=file:///$WORK/proxy
+env GOSUMDB=off
+
+# If the proxy does not return a list of versions (404/410)
+# or a latest version (404/410), we should see no error.
+go list -m example.com/noversion
+stdout '^example.com/noversion v0.0.0$'
+go list -m -u example.com/noversion
+stdout '^example.com/noversion v0.0.0$'
+
+# If the proxy returns an empty list of versions (200, not 404/410)
+# but does not have a latest version (404/410), we should see no error.
+go list -m example.com/nolatest
+stdout '^example.com/nolatest v0.0.0$'
+go list -m -u example.com/nolatest
+stdout '^example.com/nolatest v0.0.0$'
+
+# If proxy returns an invalid response, we should see an error.
+env GOPROXY=$testproxy/invalid
+! go list -m -u example.com/nolatest
+stderr '^go list -m: loading module retractions for example.com/nolatest@v0.0.0: invalid response from proxy "[^"]*": invalid character ''i'' looking for beginning of value$'
+
+-- go.mod --
+module m
+
+go 1.17
+
+require (
+       example.com/nolatest v0.0.0
+       example.com/noversion v0.0.0
+)
+-- go.sum --
+example.com/nolatest v0.0.0/go.mod h1:HnLrCt6SJga5tCtJ7IzG9dOOCniY3G5C0VT7jfMdS0M=
+example.com/noversion v0.0.0/go.mod h1:2RUfWiCYsygSXPM2Igxx0FD3Kq33OnVdxm34eDDhXbQ=
+-- $WORK/proxy/example.com/nolatest/@v/list --
+-- $WORK/proxy/example.com/nolatest/@v/v0.0.0.info --
+{"Version":"v0.0.0"}
+-- $WORK/proxy/example.com/nolatest/@v/v0.0.0.mod --
+module example.com/nolatest
+
+go 1.17
+-- $WORK/proxy/example.com/noversion/@v/v0.0.0.info --
+{"Version":"v0.0.0"}
+-- $WORK/proxy/example.com/noversion/@v/v0.0.0.mod --
+module example.com/noversion
+
+go 1.17
index c0c382bfa638b0fcb71473c560704179e7726795..eb464ab0d3b84ea1faec6d201ccf10eb7e476389 100644 (file)
@@ -22,7 +22,7 @@ cmp go.mod go.mod.orig
 
 # Update manually. Listing modules should produce an error.
 go mod edit -require=example.com/badchain/a@v1.1.0
-! go list -m
+! go list -m all
 cmp stderr list-expected
 
 # Try listing a package that imports a package
@@ -69,19 +69,17 @@ import (
 
 func Test(t *testing.T) {}
 -- update-main-expected --
-go get: example.com/badchain/c@v1.0.0 updating to
-       example.com/badchain/c@v1.1.0: parsing go.mod:
+go get: example.com/badchain/c@v1.1.0: parsing go.mod:
        module declares its path as: badchain.example.com/c
                but was required as: example.com/badchain/c
 -- update-a-expected --
-go get: example.com/badchain/a@v1.0.0 updating to
-       example.com/badchain/a@v1.1.0 requires
+go get: example.com/badchain/a@v1.1.0 requires
        example.com/badchain/b@v1.1.0 requires
        example.com/badchain/c@v1.1.0: parsing go.mod:
        module declares its path as: badchain.example.com/c
                but was required as: example.com/badchain/c
 -- list-expected --
-go: example.com/badchain/a@v1.1.0 requires
+go list -m: example.com/badchain/a@v1.1.0 requires
        example.com/badchain/b@v1.1.0 requires
        example.com/badchain/c@v1.1.0: parsing go.mod:
        module declares its path as: badchain.example.com/c
diff --git a/libgo/go/cmd/go/testdata/script/mod_load_replace_mismatch.txt b/libgo/go/cmd/go/testdata/script/mod_load_replace_mismatch.txt
new file mode 100644 (file)
index 0000000..2ca8b3c
--- /dev/null
@@ -0,0 +1,23 @@
+# If a replacement module declares a module path different from both
+# the original module and its location, report an error with all three paths.
+# In particular, the "required as" path should be the original.
+# Verifies golang.org/issue/38220.
+! go mod download
+cmp stderr want
+
+-- go.mod --
+module m
+
+require rsc.io/quote v1.5.2
+
+replace rsc.io/quote v1.5.2 => example.com/quote v1.5.2
+
+-- use.go --
+package use
+
+import _ "rsc.io/quote"
+
+-- want --
+go: rsc.io/quote@v1.5.2 (replaced by example.com/quote@v1.5.2): parsing go.mod:
+       module declares its path as: rsc.io/Quote
+               but was required as: rsc.io/quote
diff --git a/libgo/go/cmd/go/testdata/script/mod_notall.txt b/libgo/go/cmd/go/testdata/script/mod_notall.txt
new file mode 100644 (file)
index 0000000..1657c8d
--- /dev/null
@@ -0,0 +1,99 @@
+# This test demonstrates go commands that combine the 'all' pattern
+# with packages outside of 'all'.
+
+# With -deps, 'all' should include test dependencies of packages in the main
+# module, but not should not include test dependencies of packages imported only
+# by other root patterns.
+
+env GOFLAGS=-mod=mod
+cp go.mod go.mod.orig
+
+go list -deps all x/otherroot
+
+stdout '^x/inall$'
+stdout '^x/inall/fromtest$'
+stdout '^x/inall/fromtestinall$'
+stdout '^x/otherroot$'
+stdout '^x/otherdep$'
+
+! stdout '^x/fromotherroottest$'
+! stdout '^y/fromotherdeptest$'
+
+cmp go.mod go.mod.orig
+
+# With -deps -test, test dependencies of other roots should be included,
+# but test dependencies of non-roots should not.
+
+go list -deps -test all x/otherroot
+stdout '^x/inall$'
+stdout '^x/inall/fromtest$'
+stdout '^x/inall/fromtestinall$'
+stdout '^x/otherroot$'
+stdout '^x/otherdep$'
+
+stdout '^x/fromotherroottest$'
+! stdout '^y/fromotherdeptest$'
+
+cmp go.mod go.mod.orig
+
+-- m.go --
+package m
+
+import _ "x/inall"
+-- m_test.go --
+package m_test
+
+import _ "x/inall/fromtest"
+-- go.mod --
+module m
+
+go 1.15
+
+require x v0.1.0
+
+replace (
+       x v0.1.0 => ./x
+       y v0.1.0 => ./y
+)
+-- x/go.mod --
+module x
+
+go 1.15
+-- x/inall/inall.go --
+package inall
+-- x/inall/inall_test.go --
+package inall_test
+
+import _ "x/inall/fromtestinall"
+-- x/inall/fromtest/fromtest.go --
+package fromtest
+-- x/inall/fromtestinall/fromtestinall.go --
+package fromtestinall
+-- x/otherroot/otherroot.go --
+package otherroot
+
+import _ "x/otherdep"
+-- x/otherroot/otherroot_test.go --
+package otherroot_test
+
+import _ "x/fromotherroottest"
+-- x/fromotherroottest/fromotherroottest.go --
+package fromotherroottest
+-- x/otherdep/otherdep.go --
+package otherdep
+-- x/otherdep/otherdep_test.go --
+package otherdep_test
+
+import _ "y/fromotherdeptest"
+-- x/otherroot/testonly/testonly.go --
+package testonly
+-- y/go.mod --
+module y
+
+go 1.15
+-- y/fromotherdeptest/fromotherdeptest.go --
+// Package fromotherdeptest is a test dependency of x/otherdep that is
+// not declared in x/go.mod. If the loader resolves this package,
+// it will add this module to the main module's go.mod file,
+// and we can detect the mistake.
+package fromotherdeptest
index 565589268ee52662f472b5040454c6806c0e0527..33341f7d4b3656fbfb37132fd9e4ec72bf2354a2 100644 (file)
@@ -61,6 +61,11 @@ stderr 'go: cannot match "all": go.mod file not found in current directory or an
 stderr 'go: cannot match "all": go.mod file not found in current directory or any parent directory; see ''go help modules''$'
 ! stdout 'example.com/version'
 
+# 'go list -m <mods>' should fail if any of the mods lacks an explicit version.
+! go list -m example.com/printversion
+stderr 'go: cannot match "example.com/printversion" without -versions or an explicit version: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
+! stdout 'example.com/version'
+
 # 'go list -m' with wildcards should fail. Wildcards match modules in the
 # build list, so they aren't meaningful outside a module.
 ! go list -m ...
@@ -164,6 +169,8 @@ go build -n -o ignore ./stdonly/stdonly.go
 # 'go build' should succeed for standard-library packages.
 go build -n fmt
 
+# 'go build' should use the latest version of the Go language.
+go build ./newgo/newgo.go
 
 # 'go doc' without arguments implicitly operates on the current directory, and should fail.
 # TODO(golang.org/issue/32027): currently, it succeeds.
@@ -200,10 +207,6 @@ stderr 'needmod[/\\]needmod.go:10:2: no required module provides package example
 go install cmd/addr2line
 ! stderr .
 
-# 'go run' with a verison should fail due to syntax.
-! go run example.com/printversion@v1.0.0
-stderr 'can only use path@version syntax with'
-
 # 'go run' should fail if a package argument must be resolved to a module.
 ! go run example.com/printversion
 stderr '^no required module provides package example.com/printversion: go.mod file not found in current directory or any parent directory; see ''go help modules''$'
@@ -326,3 +329,15 @@ func Test(t *testing.T) {
        fmt.Println("stdonly was tested")
 }
 
+-- newgo/newgo.go --
+// Package newgo requires Go 1.14 or newer.
+package newgo
+
+import "io"
+
+const C = 299_792_458
+
+type ReadWriteCloser interface {
+       io.ReadCloser
+       io.WriteCloser
+}
diff --git a/libgo/go/cmd/go/testdata/script/mod_overlay.txt b/libgo/go/cmd/go/testdata/script/mod_overlay.txt
new file mode 100644 (file)
index 0000000..86ab04b
--- /dev/null
@@ -0,0 +1,254 @@
+# Test overlays that affect go.mod files
+
+# The go.mod file can exist only in the overlay.
+cd $WORK/gopath/src/no-go-mod
+go list -overlay overlay.json .
+stdout example.com/simple
+
+# Check content of overlaid go.mod is used.
+cd $WORK/gopath/src/overlay-go-mod
+go list -overlay overlay.json .
+stdout use.this/module/name
+
+# Check content of overlaid go.mod in a replacement module is used.
+# The go.mod in the replacement module is missing a requirement
+# that the overlay has, so it will fail to list without the overlay.
+cd $WORK/gopath/src/overlay-replaced-go-mod
+! go list -deps .
+go list -deps -overlay overlay.json .
+
+# Overlaid go.mod is not rewritten by 'go get'.
+cd $WORK/gopath/src/get-doesnt-add-dep
+cp $WORK/overlay/get_doesnt_add_dep_go_mod $WORK/want_go_mod
+! go get -d -overlay overlay.json .
+stderr '^go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay$'
+cmp $WORK/overlay/get_doesnt_add_dep_go_mod $WORK/want_go_mod
+
+# Content of overlaid go.sum is used.
+# The go.sum in the module directory has garbage values for its
+# hashes, but the overlaid file has the correct values. If
+# the correct go.sum is used with the overlay, 'go get .' should
+# not report a security error.
+cd $WORK/gopath/src/overlay-sum-used
+! go get -d .
+stderr 'SECURITY ERROR'
+! go mod verify
+stderr 'SECURITY ERROR'
+go get -d -overlay overlay.json .
+go mod verify -overlay overlay.json
+# Overlaid go.sum is not rewritten.
+# Copy an incomplete file to the overlay file, and expect an error
+# attempting to update the file
+cp incomplete-sum-file $WORK/overlay/overlay-sum-used-correct-sums
+! go get -d -overlay overlay.json .
+stderr '^go: updates to go.sum needed, but go.sum is part of the overlay specified with -overlay$'
+cmp incomplete-sum-file $WORK/overlay/overlay-sum-used-correct-sums
+! go mod tidy -overlay overlay.json
+stderr '^go: updates to go.sum needed, but go.sum is part of the overlay specified with -overlay$'
+cmp incomplete-sum-file $WORK/overlay/overlay-sum-used-correct-sums
+
+# -overlay works with -modfile.
+# There's an empty go.mod file in the directory, and the file alternate.mod is
+# overlaid to the true go.mod file, so the -modfile flag and the overlay
+# mechanism need to work together to determine the name of the module.
+cd $WORK/gopath/src/overlay-and-dash-modfile
+go list -modfile=alternate.mod -overlay overlay.json .
+stdout 'found.the/module'
+# Even with -modfile, overlaid files can't be opened for write.
+! go get -modfile=alternate.mod -overlay overlay.json -d rsc.io/quote
+stderr '^go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay$'
+
+# Carving out a module by adding an overlaid go.mod file
+cd $WORK/gopath/src/carve
+go list ./... # without an overlay, hasmod is carved out and nomod isn't
+stdout carve/nomod
+! stdout carve/hasmod
+go list -overlay overlay_carve_module.json ./... # The overlay carves out nomod, leaving nothing
+! stdout .
+stderr 'matched no packages'
+go list -overlay overlay_uncarve_module.json ./... # The overlay uncarves out hasmod
+stdout carve/nomod
+stdout carve/hasmod
+
+# Carving out a module by adding an overlaid go.mod file and using
+# -modfile to write to that file.
+cd $WORK/gopath/src/carve2/nomod
+go list -overlay overlay.json all
+! stdout ^carve2$
+stdout ^carve2/nomod$
+# Editing go.mod file fails because overlay is read only
+! go get -overlay overlay.json -d rsc.io/quote
+stderr '^go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay$'
+! grep rsc.io/quote $WORK/overlay/carve2-nomod-go.mod
+# Editing go.mod file succeeds because we use -modfile to redirect to same file
+go get -overlay overlay.json -modfile $WORK/overlay/carve2-nomod-go.mod -d rsc.io/quote
+grep rsc.io/quote $WORK/overlay/carve2-nomod-go.mod
+
+-- no-go-mod/file.go --
+package simple
+-- no-go-mod/overlay.json --
+{
+       "Replace": {
+               "go.mod": "../../../overlay/simple_go_mod"
+       }
+}
+-- $WORK/overlay/simple_go_mod --
+module example.com/simple
+-- overlay-go-mod/file.go --
+package name
+-- overlay-go-mod/go.mod --
+module dont.use/this/module/name
+-- overlay-go-mod/overlay.json --
+{
+       "Replace": {
+               "go.mod": "../../../overlay/use_this_go_mod"
+       }
+}
+-- $WORK/overlay/use_this_go_mod --
+module use.this/module/name
+-- overlay-replaced-go-mod/go.mod --
+module m
+
+go 1.15
+
+require replaced/mod v1.0.0
+replace replaced/mod v1.0.0 => ../replaced-mod
+replace dep/mod v1.0.0 => ../dep-mod
+-- overlay-replaced-go-mod/source.go --
+package m
+
+import "replaced/mod/foo"
+
+func main() {
+       foo.f()
+}
+-- overlay-replaced-go-mod/overlay.json --
+{
+       "Replace": {
+               "../replaced-mod/go.mod": "../../../overlay/replacement_module_go_mod"
+       }
+}
+-- replaced-mod/go.mod --
+module replaced/mod
+-- replaced-mod/foo/foo.go --
+package foo
+
+import "dep/mod/foo"
+
+func f() { foo.g() }
+-- dep-mod/go.mod --
+invalid
+-- dep-mod/foo/foo.go --
+package foo
+
+func g() { fmt.Println("hello") }
+-- $WORK/overlay/replacement_module_go_mod --
+module replaced/mod
+
+require dep/mod v1.0.0
+
+-- get-doesnt-add-dep/overlay.json --
+{
+       "Replace": {
+               "go.mod": "../../../overlay/get_doesnt_add_dep_go_mod"
+       }
+}
+-- get-doesnt-add-dep/p.go --
+package p
+
+import "dependency/mod"
+
+func f() { mod.G() }
+-- get-doesnt-add-dep-dependency/go.mod --
+module dependency/mod
+-- get-doesnt-add-dep-dependency/mod.go --
+package mod
+
+func G() {}
+-- $WORK/overlay/get_doesnt_add_dep_go_mod --
+module get.doesnt/add/dep
+
+replace dependency/mod v1.0.0 => ../get-doesnt-add-dep-dependency
+-- overlay-sum-used/go.mod --
+module overlay.sum/used
+
+require rsc.io/quote v1.5.0
+-- overlay-sum-used/p.go --
+package p
+
+import "rsc.io/quote"
+
+func f() string {
+       return quote.Hello()
+}
+-- overlay-sum-used/incomplete-sum-file --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
+rsc.io/quote v1.5.0 h1:6fJa6E+wGadANKkUMlZ0DhXFpoKlslOQDCo259XtdIE=
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+-- overlay-sum-used/overlay.json --
+{
+       "Replace": {
+               "go.sum": "../../../overlay/overlay-sum-used-correct-sums"
+       }
+}
+-- overlay-sum-used/go.sum --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:garbage+hash
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:garbage+hash
+rsc.io/quote v1.5.0 h1:garbage+hash
+rsc.io/quote v1.5.0/go.mod h1:garbage+hash
+rsc.io/sampler v1.3.0 h1:garbage+hash
+rsc.io/sampler v1.3.0/go.mod h1:garbage+hash
+-- $WORK/overlay/overlay-sum-used-correct-sums --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.0 h1:6fJa6E+wGadANKkUMlZ0DhXFpoKlslOQDCo259XtdIE=
+rsc.io/quote v1.5.0/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+-- overlay-and-dash-modfile/p.go --
+package module
+-- overlay-and-dash-modfile/go.mod --
+-- overlay-and-dash-modfile/overlay.json --
+{
+       "Replace": {
+               "alternate.mod": "../../../overlay/overlay-and-dash-modfile-alternate-mod"
+       }
+}
+-- $WORK/overlay/overlay-and-dash-modfile-alternate-mod --
+module found.the/module
+-- carve/go.mod --
+module carve
+-- carve/overlay_carve_module.json --
+{
+       "Replace": {
+               "nomod/go.mod": "../../../overlay/carve-nomod-go-mod"
+       }
+}
+-- carve/overlay_uncarve_module.json --
+{
+       "Replace": {
+               "hasmod/go.mod": ""
+       }
+}
+-- carve/hasmod/a.go --
+package hasmod
+-- carve/hasmod/go.mod --
+module carve/hasmod
+-- carve/nomod/b.go --
+package nomod
+-- $WORK/overlay/carve-nomod-go-mod --
+module carve/nomod
+-- carve2/go.mod --
+module carve2
+-- carve2/p.go --
+package p
+-- carve2/nomod/overlay.json --
+{
+       "Replace": {
+               "go.mod": "../../../../overlay/carve2-nomod-go.mod"
+       }
+}
+-- carve2/nomod/b.go --
+package nomod
+-- $WORK/overlay/carve2-nomod-go.mod --
+module carve2/nomod
index aa6260f63c82ee1b7a8d0c7e3c1c1dd3ccaa4acd..1b408c3e9e925d02cf6ea590bc721fb4880b2f7a 100644 (file)
@@ -23,8 +23,8 @@ stdout '^github.com/russross/blackfriday v1\.'
 go list -m github.com/russross/blackfriday@upgrade
 stdout '^github.com/russross/blackfriday v1\.'
 
-go list -m github.com/russross/blackfriday@patch
-stdout '^github.com/russross/blackfriday v1\.'
+go list -m github.com/russross/blackfriday@patch
+stderr '^go list -m: github.com/russross/blackfriday@patch: can''t query version "patch" of module github.com/russross/blackfriday: no existing version is required$'
 
 # If we're fetching directly from version control, ignored +incompatible
 # versions should also be omitted by 'go list'.
index a23090cd0ad04ac1d294e87e6da7c00b71ec034e..a5e28dd0b9771b04b68c7d3dc5b82fdca9934960 100644 (file)
@@ -10,6 +10,7 @@ stderr 'invalid proxy URL.*proxydir'
 # GOPROXY HTTPS paths may elide the "https://" prefix.
 # (See golang.org/issue/32191.)
 env GOPROXY=proxy.golang.org
+env GOSUMDB=
 go list -versions -m golang.org/x/text
 
 -- go.mod --
diff --git a/libgo/go/cmd/go/testdata/script/mod_proxy_invalid.txt b/libgo/go/cmd/go/testdata/script/mod_proxy_invalid.txt
new file mode 100644 (file)
index 0000000..6427cc1
--- /dev/null
@@ -0,0 +1,8 @@
+env GO111MODULE=on
+env GOPROXY=$GOPROXY/invalid
+
+! go list -m rsc.io/quote@latest
+stderr '^go list -m: module rsc.io/quote: invalid response from proxy "'$GOPROXY'": invalid character ''i'' looking for beginning of value$'
+
+! go list -m rsc.io/quote@1.5.2
+stderr '^go list -m: rsc.io/quote@1.5.2: invalid version: invalid response from proxy "'$GOPROXY'": invalid character ''i'' looking for beginning of value$'
diff --git a/libgo/go/cmd/go/testdata/script/mod_query_main.txt b/libgo/go/cmd/go/testdata/script/mod_query_main.txt
new file mode 100644 (file)
index 0000000..39e5841
--- /dev/null
@@ -0,0 +1,43 @@
+# 'go mod download' can download specific versions of the main module.
+go mod download rsc.io/quote@5d9f230b
+go mod download rsc.io/quote@v1.5.2
+go mod download rsc.io/quote@latest
+
+# 'go mod download' will not download @upgrade or @patch, since they always
+# resolve to the main module.
+go mod download rsc.io/quote@upgrade
+stderr '^go mod download: skipping argument rsc.io/quote@upgrade that resolves to the main module$'
+go mod download rsc.io/quote@patch
+stderr '^go mod download: skipping argument rsc.io/quote@patch that resolves to the main module$'
+
+# 'go list -m' can show a version of the main module.
+go list -m rsc.io/quote@5d9f230b
+stdout '^rsc.io/quote v0.0.0-20180710144737-5d9f230bcfba$'
+go list -m rsc.io/quote@v1.5.2
+stdout '^rsc.io/quote v1.5.2$'
+go list -m rsc.io/quote@latest
+stdout '^rsc.io/quote v1.5.2$'
+
+# 'go list -m -versions' shows available versions.
+go list -m -versions rsc.io/quote
+stdout '^rsc.io/quote.*v1.5.2'
+
+# 'go list -m' resolves @upgrade and @patch to the main module.
+go list -m rsc.io/quote@upgrade
+stdout '^rsc.io/quote$'
+go list -m rsc.io/quote@patch
+stdout '^rsc.io/quote$'
+
+# 'go get' will not attempt to upgrade the main module to any specific version.
+# See also: mod_get_main.txt.
+! go get rsc.io/quote@5d9f230b
+stderr '^go get: can''t request version "5d9f230b" of the main module \(rsc.io/quote\)$'
+! go get rsc.io/quote@v1.5.2
+stderr '^go get: can''t request version "v1.5.2" of the main module \(rsc.io/quote\)$'
+! go get rsc.io/quote@latest
+stderr '^go get: can''t request version "latest" of the main module \(rsc.io/quote\)$'
+
+-- go.mod --
+module rsc.io/quote
+
+go 1.16
index dc9667f1d0d84c7c37f4e29c6c003dc173fb4662..a0a367fb1db11c7765ae0f09945fe13bbe2fe622 100644 (file)
@@ -48,7 +48,7 @@ stderr 'module rsc.io/quote/v3@upgrade found \(v3.0.0, replaced by ./local/rsc.i
 # The reported Dir and GoMod for a replaced module should be accurate.
 cp go.mod.orig go.mod
 go mod edit -replace=rsc.io/quote/v3=not-rsc.io/quote@v0.1.0-nomod
-go mod download
+go mod download rsc.io/quote/v3
 go list -m -f '{{.Path}} {{.Version}} {{.Dir}} {{.GoMod}}{{with .Replace}} => {{.Path}} {{.Version}} {{.Dir}} {{.GoMod}}{{end}}' rsc.io/quote/v3
 stdout '^rsc.io/quote/v3 v3.0.0 '$GOPATH'[/\\]pkg[/\\]mod[/\\]not-rsc.io[/\\]quote@v0.1.0-nomod '$GOPATH'[/\\]pkg[/\\]mod[/\\]cache[/\\]download[/\\]not-rsc.io[/\\]quote[/\\]@v[/\\]v0.1.0-nomod.mod => not-rsc.io/quote v0.1.0-nomod '$GOPATH'[/\\]pkg[/\\]mod[/\\]not-rsc.io[/\\]quote@v0.1.0-nomod '$GOPATH'[/\\]pkg[/\\]mod[/\\]cache[/\\]download[/\\]not-rsc.io[/\\]quote[/\\]@v[/\\]v0.1.0-nomod.mod$'
 
index df752d9716e538b4bb89c73679d45df8e1b395ca..d24f37b7880920f9a3f7d949fdafabe09fd92103 100644 (file)
@@ -35,7 +35,7 @@ go list -m gopkg.in/src-d/go-git.v4
 # A mismatched gopkg.in path should not be able to replace a different major version.
 cd ../3-to-gomod-4
 ! go list -m gopkg.in/src-d/go-git.v3
-stderr '^go: gopkg\.in/src-d/go-git\.v3@v3\.2\.0 \(replaced by gopkg\.in/src-d/go-git\.v3@v3\.0\.0-20190801152248-0d1a009cbb60\): version "v3\.0\.0-20190801152248-0d1a009cbb60" invalid: go\.mod has non-\.\.\.\.v3 module path "gopkg\.in/src-d/go-git\.v4" at revision 0d1a009cbb60$'
+stderr '^go list -m: gopkg\.in/src-d/go-git\.v3@v3\.2\.0 \(replaced by gopkg\.in/src-d/go-git\.v3@v3\.0\.0-20190801152248-0d1a009cbb60\): version "v3\.0\.0-20190801152248-0d1a009cbb60" invalid: go\.mod has non-\.\.\.\.v3 module path "gopkg\.in/src-d/go-git\.v4" at revision 0d1a009cbb60$'
 
 -- 4-to-4/go.mod --
 module golang.org/issue/34254
diff --git a/libgo/go/cmd/go/testdata/script/mod_replace_readonly.txt b/libgo/go/cmd/go/testdata/script/mod_replace_readonly.txt
new file mode 100644 (file)
index 0000000..d950d78
--- /dev/null
@@ -0,0 +1,62 @@
+# Check that with -mod=readonly, when we load a package in a module that is
+# replaced but not required, we emit an error with the command to add the
+# requirement.
+# Verifies golang.org/issue/41416, golang.org/issue/41577.
+cp go.mod go.mod.orig
+
+# Replace all versions of a module without requiring it.
+# With -mod=mod, we'd add a requirement for a "zero" pseudo-version, but we
+# can't in readonly mode, since its go.mod may alter the build list.
+go mod edit -replace rsc.io/quote=./quote
+! go list rsc.io/quote
+stderr '^module rsc.io/quote provides package rsc.io/quote and is replaced but not required; to add it:\n\tgo get rsc.io/quote$'
+go get -d rsc.io/quote
+cmp go.mod go.mod.latest
+go list rsc.io/quote
+cp go.mod.orig go.mod
+
+# Same test with a specific version.
+go mod edit -replace rsc.io/quote@v1.0.0-doesnotexist=./quote
+! go list rsc.io/quote
+stderr '^module rsc.io/quote provides package rsc.io/quote and is replaced but not required; to add it:\n\tgo get rsc.io/quote@v1.0.0-doesnotexist$'
+go get -d rsc.io/quote@v1.0.0-doesnotexist
+cmp go.mod go.mod.specific
+go list rsc.io/quote
+cp go.mod.orig go.mod
+
+# If there are multiple versions, the highest is suggested.
+go mod edit -replace rsc.io/quote@v1.0.0-doesnotexist=./quote
+go mod edit -replace rsc.io/quote@v1.1.0-doesnotexist=./quote
+! go list rsc.io/quote
+stderr '^module rsc.io/quote provides package rsc.io/quote and is replaced but not required; to add it:\n\tgo get rsc.io/quote@v1.1.0-doesnotexist$'
+
+-- go.mod --
+module m
+
+go 1.16
+-- go.mod.latest --
+module m
+
+go 1.16
+
+replace rsc.io/quote => ./quote
+
+require rsc.io/quote v1.5.2 // indirect
+-- go.mod.specific --
+module m
+
+go 1.16
+
+replace rsc.io/quote v1.0.0-doesnotexist => ./quote
+
+require rsc.io/quote v1.0.0-doesnotexist // indirect
+-- use.go --
+package use
+
+import _ "rsc.io/quote"
+-- quote/go.mod --
+module rsc.io/quote
+
+go 1.16
+-- quote/quote.go --
+package quote
index 9156d4ce5d5fdfb47c93071a79ec09e8ef7dde35..0946dbf0bb39d0796b3f66c8d593c037c5ef51b9 100644 (file)
@@ -7,16 +7,27 @@ cp go.mod go.mod.orig
 
 ! go list -mod=readonly -m all
 stderr '^go: ignoring requirement on excluded version rsc.io/sampler v1\.99\.99$'
-stderr '^go: updates to go.mod needed, disabled by -mod=readonly$'
+stderr '^go: updates to go.mod needed, disabled by -mod=readonly; to update it:\n\tgo mod tidy$'
 ! stdout '^rsc.io/sampler v1.99.99'
 cmp go.mod go.mod.orig
 
 ! go list -mod=vendor -m rsc.io/sampler
 stderr '^go: ignoring requirement on excluded version rsc.io/sampler v1\.99\.99$'
-stderr '^go list -m: module rsc.io/sampler: can''t resolve module using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass\.\)$'
+stderr '^go: updates to go.mod needed, disabled by -mod=vendor; to update it:\n\tgo mod tidy$'
 ! stdout '^rsc.io/sampler v1.99.99'
 cmp go.mod go.mod.orig
 
+# The failure message should be clear when -mod=vendor is implicit.
+
+go mod edit -go=1.14
+! go list -m rsc.io/sampler
+stderr '^go: ignoring requirement on excluded version rsc.io/sampler v1\.99\.99$'
+stderr '^go: updates to go.mod needed, disabled by -mod=vendor\n\t\(Go version in go.mod is at least 1.14 and vendor directory exists\.\)\n\tto update it:\n\tgo mod tidy$'
+! stdout '^rsc.io/sampler v1.99.99'
+go mod edit -go=1.13
+cmp go.mod go.mod.orig
+
+
 # With the selected version excluded, commands that load only modules should
 # drop the excluded module.
 
@@ -58,7 +69,11 @@ module x
 go 1.13
 
 exclude rsc.io/sampler v1.99.99
+
 require rsc.io/sampler v1.99.99
+-- vendor/modules.txt --
+# rsc.io/sampler v1.99.99
+## explicit
 -- go.moddrop --
 module x
 
index a4441c4b3c7fba858b418d6d1d1571c0ec72009f..7a371b18068cd2e6619fc7ffdf14ddf03fa63898 100644 (file)
@@ -62,9 +62,10 @@ cmp go.mod go.mod.tidy
 
 # A missing "go" version directive should be added.
 # However, that should not remove other redundant requirements.
+# In fact, it may *add* redundant requirements due to activating lazy loading.
 cp go.mod.nogo go.mod
 go list -mod=mod all
-cmpenv go.mod go.mod.currentgo
+cmpenv go.mod go.mod.addedgo
 
 
 -- go.mod.tidy --
@@ -133,7 +134,7 @@ require (
        rsc.io/sampler v1.3.0 // indirect
        rsc.io/testonly v1.0.0 // indirect
 )
--- go.mod.currentgo --
+-- go.mod.addedgo --
 module m
 
 go $goversion
@@ -143,3 +144,5 @@ require (
        rsc.io/sampler v1.3.0 // indirect
        rsc.io/testonly v1.0.0 // indirect
 )
+
+require golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
diff --git a/libgo/go/cmd/go/testdata/script/mod_retract.txt b/libgo/go/cmd/go/testdata/script/mod_retract.txt
new file mode 100644 (file)
index 0000000..4f95ece
--- /dev/null
@@ -0,0 +1,45 @@
+cp go.mod go.mod.orig
+
+# 'go list pkg' does not report an error when a retracted version is used.
+go list -e -f '{{if .Error}}{{.Error}}{{end}}' ./use
+! stdout .
+cmp go.mod go.mod.orig
+
+# Nor does 'go build'.
+[!short] go build ./use
+[!short] ! stderr .
+[!short] cmp go.mod go.mod.orig
+
+# Neither 'go list' nor 'go build' should download go.mod from the version
+# that would list retractions.
+exists $GOPATH/pkg/mod/cache/download/example.com/retract/@v/v1.0.0-bad.mod
+! exists $GOPATH/pkg/mod/cache/download/example.com/retract/@v/v1.1.0.mod
+
+# Importing a package from a module with a retracted latest version will
+# select the latest non-retracted version.
+go get -d ./use_self_prev
+go list -m example.com/retract/self/prev
+stdout '^example.com/retract/self/prev v1.1.0$'
+exists $GOPATH/pkg/mod/cache/download/example.com/retract/self/prev/@v/v1.9.0.mod
+
+-- go.mod --
+module example.com/use
+
+go 1.15
+
+require example.com/retract v1.0.0-bad
+
+-- go.sum --
+example.com/retract v1.0.0-bad h1:liAW69rbtjY67x2CcNzat668L/w+YGgNX3lhJsWIJis=
+example.com/retract v1.0.0-bad/go.mod h1:0DvGGofJ9hr1q63cBrOY/jSY52OwhRGA0K47NE80I5Y=
+example.com/retract/self/prev v1.1.0 h1:0/8I/GTG+1eJTFeDQ/fUbgrMsVHHyKhh3Z8DSZp1fuA=
+example.com/retract/self/prev v1.1.0/go.mod h1:xl2EcklWuZZHVtHWcpzfSJQmnzAGpKZYpA/Wto7SZN4=
+-- use/use.go --
+package use
+
+import _ "example.com/retract"
+
+-- use_self_prev/use.go --
+package use_self_prev
+
+import _ "example.com/retract/self/prev"
diff --git a/libgo/go/cmd/go/testdata/script/mod_retract_fix_version.txt b/libgo/go/cmd/go/testdata/script/mod_retract_fix_version.txt
new file mode 100644 (file)
index 0000000..e45758b
--- /dev/null
@@ -0,0 +1,48 @@
+# retract must not be used without a module directive.
+! go list -m all
+stderr 'go.mod:3: no module directive found, so retract cannot be used$'
+
+# Commands that update go.mod should fix non-canonical versions in
+# retract directives.
+# Verifies #44494.
+go mod edit -module=rsc.io/quote/v2
+! go list -m all
+stderr '^go: updates to go.mod needed; to update it:\n\tgo mod tidy$'
+go mod tidy
+go list -m all
+cmp go.mod go.mod.want
+
+# If a retracted version doesn't match the module's major version suffx,
+# an error should be reported.
+! go mod edit -retract=v3.0.1
+stderr '^go mod: -retract=v3.0.1: version "v3.0.1" invalid: should be v2, not v3$'
+cp go.mod.mismatch-v2 go.mod
+! go list -m all
+stderr 'go.mod:3: retract rsc.io/quote/v2: version "v3.0.1" invalid: should be v2, not v3$'
+
+cp go.mod.mismatch-v1 go.mod
+! go list -m all
+stderr 'go.mod:3: retract rsc.io/quote: version "v3.0.1" invalid: should be v0 or v1, not v3$'
+
+-- go.mod --
+go 1.16
+
+retract latest
+-- go.mod.want --
+go 1.16
+
+retract v2.0.1
+
+module rsc.io/quote/v2
+-- go.mod.mismatch-v2 --
+go 1.16
+
+retract v3.0.1
+
+module rsc.io/quote/v2
+-- go.mod.mismatch-v1 --
+go 1.16
+
+retract v3.0.1
+
+module rsc.io/quote
diff --git a/libgo/go/cmd/go/testdata/script/mod_retract_incompatible.txt b/libgo/go/cmd/go/testdata/script/mod_retract_incompatible.txt
new file mode 100644 (file)
index 0000000..61538e8
--- /dev/null
@@ -0,0 +1,15 @@
+# The current version of a module should not be considered when loading
+# retractions. If the current version is +incompatible, we should not prefer
+# +incompatible versions when looking for retractions.
+# Verifies #42601.
+
+go mod init m
+
+# Request a +incompatible version retracted in v1.0.0.
+go get -d example.com/retract/incompatible@v2.0.0+incompatible
+stderr '^go: warning: example.com/retract/incompatible@v2.0.0\+incompatible: retracted by module author$'
+
+# We should still see a warning if the +incompatible was previously in the
+# build list.
+go get -d example.com/retract/incompatible@v2.0.0+incompatible
+stderr '^go: warning: example.com/retract/incompatible@v2.0.0\+incompatible: retracted by module author$'
diff --git a/libgo/go/cmd/go/testdata/script/mod_retract_pseudo_base.txt b/libgo/go/cmd/go/testdata/script/mod_retract_pseudo_base.txt
new file mode 100644 (file)
index 0000000..eb00e84
--- /dev/null
@@ -0,0 +1,62 @@
+# When converting a commit to a pseudo-version, don't use a retracted version
+# as the base.
+# Verifies golang.org/issue/41700.
+
+[!net] skip
+[!exec:git] skip
+env GOPROXY=direct
+env GOSUMDB=off
+go mod init m
+
+# Control: check that v1.0.0 is the only version and is retracted.
+go list -m -versions vcs-test.golang.org/git/retract-pseudo.git
+stdout '^vcs-test.golang.org/git/retract-pseudo.git$'
+go list -m -versions -retracted vcs-test.golang.org/git/retract-pseudo.git
+stdout '^vcs-test.golang.org/git/retract-pseudo.git v1.0.0$'
+
+# 713affd19d7b is a commit after v1.0.0. Don't use v1.0.0 as the base.
+go list -m vcs-test.golang.org/git/retract-pseudo.git@713affd19d7b
+stdout '^vcs-test.golang.org/git/retract-pseudo.git v0.0.0-20201009173747-713affd19d7b$'
+
+# 64c061ed4371 is the commit v1.0.0 refers to. Don't convert to v1.0.0.
+go list -m vcs-test.golang.org/git/retract-pseudo.git@64c061ed4371
+stdout '^vcs-test.golang.org/git/retract-pseudo.git v0.0.0-20201009173747-64c061ed4371'
+
+# A retracted version is a valid base. Retraction should not validate existing
+# pseudo-versions, nor should it turn invalid pseudo-versions valid.
+go get -d vcs-test.golang.org/git/retract-pseudo.git@v1.0.1-0.20201009173747-713affd19d7b
+go list -m vcs-test.golang.org/git/retract-pseudo.git
+stdout '^vcs-test.golang.org/git/retract-pseudo.git v1.0.1-0.20201009173747-713affd19d7b$'
+
+! go get -d vcs-test.golang.org/git/retract-pseudo.git@v1.0.1-0.20201009173747-64c061ed4371
+stderr '^go get: vcs-test.golang.org/git/retract-pseudo.git@v1.0.1-0.20201009173747-64c061ed4371: invalid pseudo-version: tag \(v1.0.0\) found on revision 64c061ed4371 is already canonical, so should not be replaced with a pseudo-version derived from that tag$'
+
+-- retract-pseudo.sh --
+#!/bin/bash
+
+# This is not part of the test.
+# Run this to generate and update the repository on vcs-test.golang.org.
+
+set -euo pipefail
+
+rm -rf retract-pseudo
+mkdir retract-pseudo
+cd retract-pseudo
+git init
+
+# Create the module.
+# Retract v1.0.0 and tag v1.0.0 at the same commit.
+# The module has no unretracted release versions.
+go mod init vcs-test.golang.org/git/retract-pseudo.git
+go mod edit -retract v1.0.0
+echo 'package p' >p.go
+git add -A
+git commit -m 'create module retract-pseudo'
+git tag v1.0.0
+
+# Commit a trivial change so the default branch does not point to v1.0.0.
+git mv p.go q.go
+git commit -m 'trivial change'
+
+zip -r ../retract-pseudo.zip .
+gsutil cp ../retract-pseudo.zip gs://vcs-test/git/retract-pseudo.zip
diff --git a/libgo/go/cmd/go/testdata/script/mod_retract_rationale.txt b/libgo/go/cmd/go/testdata/script/mod_retract_rationale.txt
new file mode 100644 (file)
index 0000000..823c384
--- /dev/null
@@ -0,0 +1,79 @@
+# When there is no rationale, 'go get' should print a hard-coded message.
+go get -d example.com/retract/rationale@v1.0.0-empty
+stderr '^go: warning: example.com/retract/rationale@v1.0.0-empty: retracted by module author$'
+
+# 'go list' should print the same hard-coded message.
+go list -m -retracted -f '{{.Retracted}}' example.com/retract/rationale
+stdout '^\[retracted by module author\]$'
+
+
+# When there is a multi-line message, 'go get' should print the first line.
+go get -d example.com/retract/rationale@v1.0.0-multiline1
+stderr '^go: warning: example.com/retract/rationale@v1.0.0-multiline1: retracted by module author: short description$'
+! stderr 'detail'
+
+# 'go list' should show the full message.
+go list -m -retracted -f '{{.Retracted}}' example.com/retract/rationale
+cmp stdout multiline
+
+# 'go get' output should be the same whether the retraction appears at top-level
+# or in a block.
+go get -d example.com/retract/rationale@v1.0.0-multiline2
+stderr '^go: warning: example.com/retract/rationale@v1.0.0-multiline2: retracted by module author: short description$'
+! stderr 'detail'
+
+# Same for 'go list'.
+go list -m -retracted -f '{{.Retracted}}' example.com/retract/rationale
+cmp stdout multiline
+
+
+# 'go get' should omit long messages.
+go get -d example.com/retract/rationale@v1.0.0-long
+stderr '^go: warning: example.com/retract/rationale@v1.0.0-long: retracted by module author: \(message omitted: too long\)'
+
+# 'go list' should show the full message.
+go list -m -retracted -f '{{.Retracted}}' example.com/retract/rationale
+stdout '^\[lo{500}ng\]$'
+
+
+# 'go get' should omit messages with unprintable characters.
+go get -d example.com/retract/rationale@v1.0.0-unprintable
+stderr '^go: warning: example.com/retract/rationale@v1.0.0-unprintable: retracted by module author: \(message omitted: contains non-printable characters\)'
+
+# 'go list' should show the full message.
+go list -m -retracted -f '{{.Retracted}}' example.com/retract/rationale
+stdout '^\[Ends with a BEL character. Beep!\x07\]$'
+
+
+# When there is a comment on a block, but not on individual retractions within
+# the block, the rationale should come from the block comment.
+go list -m -retracted -f '{{.Retracted}}' example.com/retract/rationale@v1.0.0-block
+stdout '^\[block comment\]$'
+go list -m -retracted -f '{{.Retracted}}' example.com/retract/rationale@v1.0.0-blockwithcomment
+stdout '^\[inner comment\]$'
+
+
+# When a version is covered by multiple retractions, all retractions should
+# be reported in the order they appear in the file.
+go list -m -retracted -f '{{range .Retracted}}{{.}},{{end}}' example.com/retract/rationale@v1.0.0-order
+stdout '^degenerate range,single version,$'
+go list -m -retracted -f '{{range .Retracted}}{{.}},{{end}}' example.com/retract/rationale@v1.0.1-order
+stdout '^single version,degenerate range,$'
+
+# 'go get' will only report the first retraction to avoid being too verbose.
+go get -d example.com/retract/rationale@v1.0.0-order
+stderr '^go: warning: example.com/retract/rationale@v1.0.0-order: retracted by module author: degenerate range$'
+go get -d example.com/retract/rationale@v1.0.1-order
+stderr '^go: warning: example.com/retract/rationale@v1.0.1-order: retracted by module author: single version$'
+
+-- go.mod --
+module m
+
+go 1.14
+
+-- multiline --
+[short description
+more
+
+detail
+suffix]
diff --git a/libgo/go/cmd/go/testdata/script/mod_retract_rename.txt b/libgo/go/cmd/go/testdata/script/mod_retract_rename.txt
new file mode 100644 (file)
index 0000000..f54742c
--- /dev/null
@@ -0,0 +1,28 @@
+# Populate go.sum.
+go get -d
+
+# 'go list -m -retracted' should load retractions, even if the version
+# containing retractions has a different module path.
+go list -m -retracted -f '{{with .Retracted}}retracted{{end}}' example.com/retract/rename
+
+# 'go list -m -u' should load retractions, too.
+go list -m -u -f '{{with .Retracted}}retracted{{end}}' example.com/retract/rename
+
+# 'go get' should warn about the retracted version.
+go get -d
+stderr '^go: warning: example.com/retract/rename@v1.0.0-bad: retracted by module author: bad$'
+
+# We can't upgrade, since this latest version has a different module path.
+! go get -d example.com/retract/rename
+stderr 'module declares its path as: example.com/retract/newname'
+
+-- go.mod --
+module example.com/use
+
+go 1.16
+
+require example.com/retract/rename v1.0.0-bad
+-- use.go --
+package use
+
+import _ "example.com/retract/rename"
diff --git a/libgo/go/cmd/go/testdata/script/mod_retract_replace.txt b/libgo/go/cmd/go/testdata/script/mod_retract_replace.txt
new file mode 100644 (file)
index 0000000..9cd7147
--- /dev/null
@@ -0,0 +1,63 @@
+# If the latest unretracted version of a module is replaced, 'go list' should
+# obtain retractions from the replacement.
+
+# Populate go.sum.
+go get -d
+
+# The latest version, v1.9.0, is not available on the proxy.
+go list -m -retracted example.com/retract/missingmod
+stdout '^example.com/retract/missingmod v1.0.0$'
+exists $GOPATH/pkg/mod/cache/download/example.com/retract/missingmod/@v/v1.9.0.info
+! exists $GOPATH/pkg/mod/cache/download/example.com/retract/missingmod/@v/v1.9.0.mod
+
+# If we replace that version, we should see retractions.
+go mod edit -replace=example.com/retract/missingmod@v1.9.0=./missingmod-v1.9.0
+go list -m -retracted -f '{{range .Retracted}}{{.}}{{end}}' example.com/retract/missingmod
+stdout '^bad version$'
+
+# If we replace the retracted version, we should not see a retraction.
+go mod edit -replace=example.com/retract/missingmod=./missingmod-v1.9.0
+go list -m -retracted -f '{{if not .Retracted}}good version{{end}}' example.com/retract/missingmod
+stdout '^good version$'
+
+
+# If a replacement version is retracted, we should see a retraction.
+# It should appear in both the replaced module and the replacement, as other
+# fields like GoMod do.
+go list -m -retracted -f '{{range .Retracted}}{{.}}{{end}}' example.com/retract
+! stdout .
+go list -m -retracted -f '{{if .Replace}}replaced{{end}}' example.com/retract
+! stdout .
+go mod edit -replace example.com/retract@v1.0.0-good=example.com/retract@v1.0.0-bad
+go list -m -mod=mod -retracted -f '{{range .Retracted}}{{.}}{{end}}' example.com/retract
+stdout '^bad$'
+go list -m -mod=mod -retracted -f '{{with .Replace}}{{range .Retracted}}{{.}}{{end}}{{end}}' example.com/retract
+stdout '^bad$'
+
+-- go.mod --
+module m
+
+go 1.14
+
+require (
+       example.com/retract v1.0.0-good
+       example.com/retract/missingmod v1.0.0
+)
+-- use.go --
+package use
+
+import (
+       _ "example.com/retract"
+       _ "example.com/retract/missingmod"
+)
+-- missingmod-v1.0.0/go.mod --
+module example.com/retract/missingmod
+
+go 1.14
+-- missingmod-v1.9.0/go.mod --
+module example.com/retract/missingmod
+
+go 1.14
+
+// bad version
+retract v1.0.0
diff --git a/libgo/go/cmd/go/testdata/script/mod_retract_versions.txt b/libgo/go/cmd/go/testdata/script/mod_retract_versions.txt
new file mode 100644 (file)
index 0000000..012fa15
--- /dev/null
@@ -0,0 +1,22 @@
+# https://golang.org/issue/44296: the --versions flag should not affect
+# the version reported by 'go list' in case of retractions.
+
+env FMT='{{.Path}}{{with .Error}}: {{printf "%q" .Err}}{{end}} {{printf "%q" .Version}}{{with .Versions}} {{.}}{{end}}'
+
+go list -m -e -f $FMT example.com/retract/self/pseudo
+stdout '^example.com/retract/self/pseudo: "module example.com/retract/self/pseudo: not a known dependency" ""$'
+
+go list -m -e -f $FMT example.com/retract/self/pseudo@latest
+stdout '^example.com/retract/self/pseudo: "module example.com/retract/self/pseudo: no matching versions for query \\"latest\\"" "latest"$'
+
+
+go list -m -e -f $FMT --versions example.com/retract/self/pseudo
+stdout '^example.com/retract/self/pseudo ""$'
+
+go list -m -e -f $FMT --versions example.com/retract/self/pseudo@latest
+stdout '^example.com/retract/self/pseudo: "module example.com/retract/self/pseudo: no matching versions for query \\"latest\\"" "latest"$'
+
+-- go.mod --
+module test
+
+go 1.17
diff --git a/libgo/go/cmd/go/testdata/script/mod_run_nonmain.txt b/libgo/go/cmd/go/testdata/script/mod_run_nonmain.txt
new file mode 100644 (file)
index 0000000..036755d
--- /dev/null
@@ -0,0 +1,18 @@
+! go run $PWD
+! stderr 'no packages loaded'
+stderr '^package example.net/nonmain is not a main package$'
+
+! go run .
+stderr '^package example.net/nonmain is not a main package$'
+
+! go run ./...
+stderr '^go: warning: "\./\.\.\." matched only non-main packages$'
+stderr '^go run: no packages loaded from \./\.\.\.$'
+
+-- go.mod --
+module example.net/nonmain
+
+go 1.17
+-- nonmain.go --
+// Package nonmain is not a main package.
+package nonmain
diff --git a/libgo/go/cmd/go/testdata/script/mod_run_pkg_version.txt b/libgo/go/cmd/go/testdata/script/mod_run_pkg_version.txt
new file mode 100644 (file)
index 0000000..e921fab
--- /dev/null
@@ -0,0 +1,103 @@
+# This test checks the behavior of 'go run' with a 'cmd@version' argument.
+# Most of 'go run' is covered in other tests.
+# mod_install_pkg_version covers most of the package loading functionality.
+# This test focuses on 'go run' behavior specific to this mode.
+[short] skip
+
+# 'go run pkg@version' works outside a module.
+env GO111MODULE=auto
+go run example.com/cmd/a@v1.0.0
+stdout '^a@v1.0.0$'
+
+
+# 'go run pkg@version' reports an error if modules are disabled.
+env GO111MODULE=off
+! go run example.com/cmd/a@v1.0.0
+stderr '^go: modules disabled by GO111MODULE=off; see ''go help modules''$'
+env GO111MODULE=on
+
+
+# 'go run pkg@version' ignores go.mod in the current directory.
+cd m
+cp go.mod go.mod.orig
+! go list -m all
+stderr '^go list -m: example.com/cmd@v1.1.0-doesnotexist: missing go.sum entry; to add it:\n\tgo mod download example.com/cmd$'
+go run example.com/cmd/a@v1.0.0
+stdout '^a@v1.0.0$'
+cmp go.mod go.mod.orig
+cd ..
+
+
+# 'go install pkg@version' works on a module that doesn't have a go.mod file
+# and with a module whose go.mod file has missing requirements.
+# With a proxy, the two cases are indistinguishable.
+go run rsc.io/fortune@v1.0.0
+stderr '^go: found rsc.io/quote in rsc.io/quote v1.5.2$'
+stderr '^Hello, world.$'
+
+
+# 'go run pkg@version' should report an error if pkg is not a main package.
+! go run example.com/cmd/err@v1.0.0
+stderr '^package example.com/cmd/err is not a main package$'
+
+
+# 'go run pkg@version' should report errors if the module contains
+# replace or exclude directives.
+go mod download example.com/cmd@v1.0.0-replace
+! go run example.com/cmd/a@v1.0.0-replace
+cmp stderr replace-err
+
+go mod download example.com/cmd@v1.0.0-exclude
+! go run example.com/cmd/a@v1.0.0-exclude
+cmp stderr exclude-err
+
+
+# 'go run dir@version' works like a normal 'go run' command if
+# dir is a relative or absolute path.
+go mod download rsc.io/fortune@v1.0.0
+! go run $GOPATH/pkg/mod/rsc.io/fortune@v1.0.0
+stderr '^go: go\.mod file not found in current directory or any parent directory; see ''go help modules''$'
+! go run ../pkg/mod/rsc.io/fortune@v1.0.0
+stderr '^go: go\.mod file not found in current directory or any parent directory; see ''go help modules''$'
+mkdir tmp
+cd tmp
+go mod init tmp
+go mod edit -require=rsc.io/fortune@v1.0.0
+! go run -mod=readonly $GOPATH/pkg/mod/rsc.io/fortune@v1.0.0
+stderr '^missing go\.sum entry for module providing package rsc\.io/fortune; to add:\n\tgo mod download rsc\.io/fortune$'
+! go run -mod=readonly ../../pkg/mod/rsc.io/fortune@v1.0.0
+stderr '^missing go\.sum entry for module providing package rsc\.io/fortune; to add:\n\tgo mod download rsc\.io/fortune$'
+cd ..
+rm tmp
+
+
+# 'go run' does not interpret @version arguments after the first.
+go run example.com/cmd/a@v1.0.0 example.com/doesnotexist@v1.0.0
+stdout '^a@v1.0.0$'
+
+
+# 'go run pkg@version' succeeds when -mod=readonly is set explicitly.
+# Verifies #43278.
+go run -mod=readonly example.com/cmd/a@v1.0.0
+stdout '^a@v1.0.0$'
+
+-- m/go.mod --
+module m
+
+go 1.16
+
+require example.com/cmd v1.1.0-doesnotexist
+-- x/x.go --
+package main
+
+func main() {}
+-- replace-err --
+go run: example.com/cmd/a@v1.0.0-replace (in example.com/cmd@v1.0.0-replace):
+       The go.mod file for the module providing named packages contains one or
+       more replace directives. It must not contain directives that would cause
+       it to be interpreted differently than if it were the main module.
+-- exclude-err --
+go run: example.com/cmd/a@v1.0.0-exclude (in example.com/cmd@v1.0.0-exclude):
+       The go.mod file for the module providing named packages contains one or
+       more exclude directives. It must not contain directives that would cause
+       it to be interpreted differently than if it were the main module.
diff --git a/libgo/go/cmd/go/testdata/script/mod_run_pkgerror.txt b/libgo/go/cmd/go/testdata/script/mod_run_pkgerror.txt
new file mode 100644 (file)
index 0000000..48f900d
--- /dev/null
@@ -0,0 +1,32 @@
+# https://golang.org/issue/39986: files reported as invalid by go/build should
+# be listed in InvalidGoFiles.
+
+go list -e -f '{{.Incomplete}}{{"\n"}}{{.Error}}{{"\n"}}{{.InvalidGoFiles}}{{"\n"}}' .
+stdout '^true\nfound packages m \(m\.go\) and main \(main\.go\) in '$PWD'\n\[main.go\]\n'
+
+
+# https://golang.org/issue/45827: 'go run .' should report the same package
+# errors as 'go build' and 'go list'.
+
+! go build
+stderr '^found packages m \(m\.go\) and main \(main\.go\) in '$PWD'$'
+
+! go list .
+stderr '^found packages m \(m\.go\) and main \(main\.go\) in '$PWD'$'
+
+! go run .
+! stderr 'no packages loaded'
+stderr '^found packages m \(m\.go\) and main \(main\.go\) in '$PWD'$'
+
+! go run ./...
+! stderr 'no packages loaded'
+stderr '^found packages m \(m\.go\) and main \(main\.go\) in '$PWD'$'
+
+-- go.mod --
+module m
+
+go 1.17
+-- m.go --
+package m
+-- main.go --
+package main
index fb954d74edbe9e76aa4f0a45e1eabf20a29d0adb..c3cde52953f86b023ecd1b8c854e3ec65dbf18ca 100644 (file)
@@ -36,11 +36,11 @@ stderr 'use of vendored package'
 
 
 # When run within the 'std' module, 'go list -test' should report vendored
-# transitive dependencies at their original module paths.
+# transitive dependencies at their vendored paths.
 cd $GOROOT/src
 go list -test -f '{{range .Deps}}{{.}}{{"\n"}}{{end}}' net/http
-stdout ^golang.org/x/net/http2/hpack
-stdout ^vendor/golang.org/x/net/http2/hpack
+stdout ^golang.org/x/net/http2/hpack
+stdout ^vendor/golang.org/x/net/http2/hpack
 
 -- go.mod --
 module m
diff --git a/libgo/go/cmd/go/testdata/script/mod_sum_ambiguous.txt b/libgo/go/cmd/go/testdata/script/mod_sum_ambiguous.txt
new file mode 100644 (file)
index 0000000..07c6659
--- /dev/null
@@ -0,0 +1,62 @@
+# Confirm our build list.
+cp go.sum.buildlist-only go.sum
+go list -m all
+stdout '^example.com/ambiguous/a v1.0.0$'
+stdout '^example.com/ambiguous/a/b v0.0.0-empty$'
+
+# If two modules could provide a package, but only one does,
+# 'go mod tidy' should retain sums for both zips.
+go mod tidy
+grep '^example.com/ambiguous/a v1.0.0 h1:' go.sum
+grep '^example.com/ambiguous/a/b v0.0.0-empty h1:' go.sum
+
+# 'go mod download' should also add sums.
+cp go.sum.buildlist-only go.sum
+go mod download example.com/ambiguous/a
+grep '^example.com/ambiguous/a v1.0.0 h1:' go.sum
+! grep '^example.com/ambiguous/a/b v0.0.0-empty h1:' go.sum
+go mod download example.com/ambiguous/a/b
+grep '^example.com/ambiguous/a/b v0.0.0-empty h1:' go.sum
+
+# If two modules could provide a package, and we're missing a sum for one,
+# we should see a missing sum error, even if we have a sum for a module that
+# provides the package.
+cp go.sum.a-only go.sum
+! go list example.com/ambiguous/a/b
+stderr '^missing go.sum entry needed to verify package example.com/ambiguous/a/b is provided by exactly one module; to add:\n\tgo mod download example.com/ambiguous/a/b$'
+! go list -deps .
+stderr '^use.go:3:8: missing go.sum entry needed to verify package example.com/ambiguous/a/b \(imported by m\) is provided by exactly one module; to add:\n\tgo get m$'
+
+cp go.sum.b-only go.sum
+! go list example.com/ambiguous/a/b
+stderr '^missing go.sum entry for module providing package example.com/ambiguous/a/b; to add:\n\tgo mod download example.com/ambiguous/a$'
+! go list -deps .
+stderr '^use.go:3:8: missing go.sum entry for module providing package example.com/ambiguous/a/b \(imported by m\); to add:\n\tgo get m$'
+
+cp go.sum.buildlist-only go.sum
+! go list example.com/ambiguous/a/b
+stderr '^missing go.sum entry for module providing package example.com/ambiguous/a/b; to add:\n\tgo mod download example.com/ambiguous/a example.com/ambiguous/a/b$'
+! go list -deps .
+stderr '^use.go:3:8: missing go.sum entry for module providing package example.com/ambiguous/a/b \(imported by m\); to add:\n\tgo get m$'
+
+-- go.mod --
+module m
+
+go 1.15
+
+require example.com/ambiguous/a v1.0.0
+-- go.sum.buildlist-only --
+example.com/ambiguous/a v1.0.0/go.mod h1:TrBl/3xTPFJ2gmMIYz53h2gkNtg0dokszEMuyS1QEb0=
+example.com/ambiguous/a/b v0.0.0-empty/go.mod h1:MajJq5jPEBnnXP+NTWIeXX7kwaPS1sbVEJdooTmsePQ=
+-- go.sum.a-only --
+example.com/ambiguous/a v1.0.0 h1:pGZhTXy6+titE2rNfwHwJykSjXDR4plO52PfZrBM0T8=
+example.com/ambiguous/a v1.0.0/go.mod h1:TrBl/3xTPFJ2gmMIYz53h2gkNtg0dokszEMuyS1QEb0=
+example.com/ambiguous/a/b v0.0.0-empty/go.mod h1:MajJq5jPEBnnXP+NTWIeXX7kwaPS1sbVEJdooTmsePQ=
+-- go.sum.b-only --
+example.com/ambiguous/a v1.0.0/go.mod h1:TrBl/3xTPFJ2gmMIYz53h2gkNtg0dokszEMuyS1QEb0=
+example.com/ambiguous/a/b v0.0.0-empty h1:xS29ReXXuhjT7jc79mo91h/PevaZ2oS9PciF1DucXtg=
+example.com/ambiguous/a/b v0.0.0-empty/go.mod h1:MajJq5jPEBnnXP+NTWIeXX7kwaPS1sbVEJdooTmsePQ=
+-- use.go --
+package use
+
+import _ "example.com/ambiguous/a/b"
diff --git a/libgo/go/cmd/go/testdata/script/mod_sum_lookup.txt b/libgo/go/cmd/go/testdata/script/mod_sum_lookup.txt
new file mode 100644 (file)
index 0000000..e021921
--- /dev/null
@@ -0,0 +1,34 @@
+# When we attempt to resolve an import that doesn't exist, we should not save
+# hashes for downloaded modules.
+# Verifies golang.org/issue/36260.
+# TODO(golang.org/issue/26603): use 'go mod tidy -e' when implemented.
+go list -e -mod=mod -tags=ignore ./noexist
+! exists go.sum
+
+# When an import is resolved successfully, we should only save hashes for
+# the module that provides the package, not for other modules looked up.
+# Verifies golang.org/issue/31580.
+go get -d ./exist
+grep '^example.com/join v1.1.0 h1:' go.sum
+! grep '^example.com/join/subpkg' go.sum
+cp go.sum go.list.sum
+go mod tidy
+cmp go.sum go.list.sum
+
+-- go.mod --
+module m
+
+go 1.15
+
+-- noexist/use.go --
+// ignore tags prevents errors in 'go mod tidy'
+// +build ignore
+
+package use
+
+import _ "example.com/join/subpkg/noexist"
+
+-- exist/use.go --
+package use
+
+import _ "example.com/join/subpkg"
diff --git a/libgo/go/cmd/go/testdata/script/mod_sum_readonly.txt b/libgo/go/cmd/go/testdata/script/mod_sum_readonly.txt
new file mode 100644 (file)
index 0000000..113f13e
--- /dev/null
@@ -0,0 +1,87 @@
+# Test that go.sum does not get updated when -mod=readonly flag is set
+env GO111MODULE=on
+
+# When a sum is needed to load the build list, we get an error for the
+# specific module. The .mod file is not downloaded, and go.sum is not written.
+! go list -m all
+stderr '^go list -m: rsc.io/quote@v1.5.2: missing go.sum entry; to add it:\n\tgo mod download rsc.io/quote$'
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod
+! exists go.sum
+
+# If go.sum exists but contains hashes from an algorithm we don't know about,
+# we should see the same error.
+cp go.sum.h2only go.sum
+! go list -m all
+stderr '^go list -m: rsc.io/quote@v1.5.2: missing go.sum entry; to add it:\n\tgo mod download rsc.io/quote$'
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod
+cmp go.sum go.sum.h2only
+rm go.sum
+
+# If we replace a module, we should see a missing sum error for the replacement.
+cp go.mod go.mod.orig
+go mod edit -replace rsc.io/quote@v1.5.2=rsc.io/quote@v1.5.1
+! go list -m all
+stderr '^go list -m: rsc.io/quote@v1.5.2 \(replaced by rsc.io/quote@v1.5.1\): missing go.sum entry; to add it:\n\tgo mod download rsc.io/quote$'
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.1.mod
+! exists go.sum
+cp go.mod.orig go.mod
+
+# Control: when sums are present, loading the build list downloads .mod files.
+cp go.sum.buildlistonly go.sum
+go list -m all
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod
+
+
+# When a sum is needed to load a .mod file for a package outside the build list,
+# we get a generic missing import error.
+! go list example.com/doesnotexist
+stderr '^no required module provides package example.com/doesnotexist; to add it:\n\tgo get example.com/doesnotexist$'
+
+# When a sum is needed to load a .zip file, we get a more specific error.
+# The .zip file is not downloaded.
+! go list rsc.io/quote
+stderr '^missing go.sum entry for module providing package rsc.io/quote; to add:\n\tgo mod download rsc.io/quote$'
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
+
+# The error is attached to the package from the missing module. We can load
+# a package that imports it without that error.
+go list -e -deps -f '{{.ImportPath}}{{with .Error}} {{.Err}}{{end}}' .
+stdout '^m$'
+stdout '^rsc.io/quote missing go.sum entry for module providing package rsc.io/quote \(imported by m\); to add:\n\tgo get m$'
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
+
+# go.sum should not have been written.
+cmp go.sum go.sum.buildlistonly
+
+# Control: when sums are present, 'go list' downloads .zip files.
+cp go.sum.tidy go.sum
+go list .
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
+
+-- go.mod --
+module m
+
+go 1.15
+
+require rsc.io/quote v1.5.2
+-- use.go --
+package use
+
+import _ "rsc.io/quote"
+-- go.sum.h2only --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h2:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.2/go.mod h2:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0/go.mod h2:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+-- go.sum.buildlistonly --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+-- go.sum.tidy --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64=
+rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY=
index 9a688e1461ca94efdce410cafbc9d4f06146fd1d..fa3483c5cb1a510b9d5c19cbf16c4bdf116f155d 100644 (file)
@@ -37,3 +37,9 @@ go get -d rsc.io/fortune
 
 -- go.mod.orig --
 module m
+
+go 1.16
+-- m.go --
+package m
+
+import _ "rsc.io/quote"
index 2937b2e4dcd66afce921342bcbf6ae7f13d80a0b..1b38475fb5e378c0e1d4fbb88ec266bba83fe90b 100644 (file)
@@ -43,12 +43,5 @@ env GOPROXY=$proxy/sumdb-504
 ! go get -d rsc.io/quote@v1.5.2
 stderr 504
 
-# but -insecure bypasses the checksum lookup entirely
-env GOINSECURE=
-go get -d -insecure rsc.io/quote@v1.5.2
-
-# and then it is in go.sum again
-go get -d rsc.io/quote@v1.5.2
-
 -- go.mod.orig --
 module m
index cc0b0da474a2286521453d81ca91c1b2c9c263d5..becd88b52e7cffaa18b94b99a574b84c1ab7df2f 100644 (file)
@@ -10,45 +10,73 @@ go env GOSUMDB
 stdout '^sum.golang.org$'
 
 # Download direct from github.
+
 [!net] skip
 [!exec:git] skip
 env GOSUMDB=sum.golang.org
 env GOPROXY=direct
+
 go get -d rsc.io/quote@v1.5.2
 cp go.sum saved.sum
 
+
 # Download from proxy.golang.org with go.sum entry already.
 # Use 'go list' instead of 'go get' since the latter may download extra go.mod
 # files not listed in go.sum.
+
 go clean -modcache
 env GOSUMDB=
 env GOPROXY=
-go list -x -deps rsc.io/quote
+
+go list -x -m all  # Download go.mod files.
 ! stderr github
 stderr proxy.golang.org/rsc.io/quote
 ! stderr sum.golang.org/tile
 ! stderr sum.golang.org/lookup/rsc.io/quote
+
+go list -x -deps rsc.io/quote  # Download module source.
+! stderr github
+stderr proxy.golang.org/rsc.io/quote
+! stderr sum.golang.org/tile
+! stderr sum.golang.org/lookup/rsc.io/quote
+
 cmp go.sum saved.sum
 
+
 # Download again.
 # Should use the checksum database to validate new go.sum lines,
 # but not need to fetch any new data from the proxy.
+
 rm go.sum
-go list -mod=mod -x rsc.io/quote
+
+go list -mod=mod -x -m all  # Add checksums for go.mod files.
+stderr sum.golang.org/tile
 ! stderr github
 ! stderr proxy.golang.org/rsc.io/quote
-stderr sum.golang.org/tile
 stderr sum.golang.org/lookup/rsc.io/quote
+
+go list -mod=mod -x rsc.io/quote  # Add checksums for module source.
+! stderr .  # Adds checksums, but for entities already in the module cache.
+
 cmp go.sum saved.sum
 
+
 # test fallback to direct
+
 env TESTGOPROXY404=1
 go clean -modcache
 rm go.sum
-go list -mod=mod -x rsc.io/quote
+
+go list -mod=mod -x -m all  # Download go.mod files
+stderr 'proxy.golang.org.*404 testing'
+stderr github.com/rsc
+
+go list -mod=mod -x rsc.io/quote  # Download module source.
 stderr 'proxy.golang.org.*404 testing'
 stderr github.com/rsc
+
 cmp go.sum saved.sum
 
+
 -- go.mod --
 module m
diff --git a/libgo/go/cmd/go/testdata/script/mod_symlink_dotgo.txt b/libgo/go/cmd/go/testdata/script/mod_symlink_dotgo.txt
new file mode 100644 (file)
index 0000000..d4cc143
--- /dev/null
@@ -0,0 +1,17 @@
+env GO111MODULE=on
+[!symlink] skip
+
+symlink dir.go -> dir
+
+# Issue #39841: symlinks to directories should be ignored, not treated as source files.
+go list -f '{{range .GoFiles}}{{.}}{{"\n"}}{{end}}' .
+stdout 'p\.go$'
+! stdout 'dir\.go$'
+
+-- go.mod --
+module example.com
+go 1.15
+-- p.go --
+package p
+-- dir/README.txt --
+This file exists to ensure that dir is a directory.
diff --git a/libgo/go/cmd/go/testdata/script/mod_tagged_import_cycle.txt b/libgo/go/cmd/go/testdata/script/mod_tagged_import_cycle.txt
new file mode 100644 (file)
index 0000000..0491acb
--- /dev/null
@@ -0,0 +1,106 @@
+# Because 'go mod' subcommands ignore build constraints, they can encounter
+# package-import cycles that are not possible in an ordinary build. This test
+# verifies that such cycles are handled even when they cross module boundaries.
+
+# First, verify that the import graph depends on build tags as expected.
+go list -deps example.com/left
+stdout '^example.com/right$'
+go list -deps example.com/right
+! stdout left
+
+env GOFLAGS=-tags=mirror
+go list -deps example.com/left
+! stdout right
+go list -deps example.com/right
+stdout '^example.com/left$'
+env GOFLAGS=''
+
+# 'go mod why' should be agnostic to build tags.
+go mod why example.com/left
+stdout '^example.com/chiral$\n^example.com/left$'
+go mod why example.com/right
+stdout '^example.com/chiral$\n^example.com/right$'
+
+env GOFLAGS='-tags=mirror'
+go mod why example.com/left
+stdout '^example.com/chiral$\n^example.com/left$'
+go mod why example.com/right
+stdout '^example.com/chiral$\n^example.com/right$'
+env GOFLAGS=''
+
+# 'go mod tidy' should successfully handle the cycle.
+env GOFLAGS=-mod=readonly
+go mod tidy
+
+# 'go mod vendor' should copy in both packages without crashing.
+go mod vendor
+exists vendor/example.com/left/default.go
+exists vendor/example.com/left/mirror.go
+exists vendor/example.com/right/default.go
+exists vendor/example.com/right/mirror.go
+
+-- go.mod --
+module example.com/chiral
+
+go 1.14
+
+require (
+       example.com/left v0.1.0
+       example.com/right v0.1.0
+)
+
+replace (
+       example.com/left => ./left
+       example.com/right => ./right
+)
+-- chiral.go --
+// Package chiral imports packages in an order that depends on build tags.
+package chiral
+-- default.go --
+// +build !mirror
+
+package chiral
+
+import _ "example.com/left"
+-- mirror.go --
+// +build mirror
+
+package chiral
+
+import _ "example.com/right"
+-- left/go.mod --
+module example.com/left
+
+go 1.14
+
+require example.com/right v0.1.0
+
+replace example.com/right v0.1.0 => ../right
+-- left/default.go --
+// +build !mirror
+
+package left
+
+import _ "example.com/right"
+-- left/mirror.go --
+// +build mirror
+
+package left
+-- right/go.mod --
+module example.com/right
+
+go 1.14
+
+require example.com/left v0.1.0
+
+replace example.com/left v0.1.0 => ../left
+-- right/default.go --
+// +build !mirror
+
+package right
+-- right/mirror.go --
+// +build mirror
+
+package right
+
+import _ "example.com/left"
index 50f00355c17e5bce4ee2621c6ee22661f35decee..76f1d7a9a4d994c20634de26305d0df2aa0ef1cb 100644 (file)
@@ -60,6 +60,8 @@ go list -test
 -- a/go.mod.empty --
 module example.com/user/a
 
+go 1.11
+
 -- a/a.go --
 package a
 
diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_compat.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_compat.txt
new file mode 100644 (file)
index 0000000..e6edef5
--- /dev/null
@@ -0,0 +1,95 @@
+# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
+# default preserve enough checksums for the module to be used by Go 1.16.
+#
+# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
+# 'go' version in the go.mod file to 1.16, without actually updating the
+# requirements to match.
+
+[short] skip
+
+env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
+
+
+# This module has the same module dependency graph in Go 1.16 as in Go 1.17,
+# but in 1.16 requires (checksums for) additional (irrelevant) go.mod files.
+#
+# The module graph under both versions looks like:
+#
+# m ---- example.com/version v1.1.0
+# |
+# + ---- example.net/lazy v0.1.0 ---- example.com/version v1.0.1
+#
+# Go 1.17 avoids loading the go.mod file for example.com/version v1.0.1
+# (because it is lower than the verison explicitly required by m,
+# and the module that requires it — m — specifies 'go 1.17').
+#
+# That go.mod file happens not to affect the final 1.16 module graph anyway,
+# so the pruned graph is equivalent to the unpruned one.
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod go.mod.orig
+
+go list -m all
+cmp stdout m_all.txt
+
+go mod edit -go=1.16
+go list -m all
+cmp stdout m_all.txt
+
+
+# If we explicitly drop compatibility with 1.16, we retain fewer checksums,
+# which gives a cleaner go.sum file but causes 1.16 to fail in readonly mode.
+
+cp go.mod.orig go.mod
+go mod tidy -compat=1.17
+cmp go.mod go.mod.orig
+
+go list -m all
+cmp stdout m_all.txt
+
+go mod edit -go=1.16
+! go list -m all
+stderr '^go list -m: example.net/lazy@v0.1.0 requires\n\texample.com/version@v1.0.1: missing go.sum entry; to add it:\n\tgo mod download example.com/version$'
+
+
+-- go.mod --
+// Module m happens to have the exact same build list as what would be
+// selected under Go 1.16, but computes that build list without looking at
+// as many go.mod files.
+module example.com/m
+
+go 1.17
+
+replace example.net/lazy v0.1.0 => ./lazy
+
+require (
+       example.com/version v1.1.0
+       example.net/lazy v0.1.0
+)
+-- m_all.txt --
+example.com/m
+example.com/version v1.1.0
+example.net/lazy v0.1.0 => ./lazy
+-- compatible.go --
+package compatible
+
+import (
+       _ "example.com/version"
+       _ "example.net/lazy"
+)
+-- lazy/go.mod --
+// Module lazy requires example.com/version v1.0.1.
+//
+// However, since this module is lazy, its dependents
+// should not need checksums for that version of the module
+// unless they actually import packages from it.
+module example.net/lazy
+
+go 1.17
+
+require example.com/version v1.0.1
+-- lazy/lazy.go --
+package lazy
+
+import _ "example.com/version"
diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_compat_added.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_compat_added.txt
new file mode 100644 (file)
index 0000000..94fa79b
--- /dev/null
@@ -0,0 +1,105 @@
+# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
+# default preserve enough checksums for the module to be used by Go 1.16.
+#
+# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
+# 'go' version in the go.mod file to 1.16, without actually updating the
+# requirements to match.
+
+[short] skip
+
+env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
+
+
+# For this module, Go 1.17 produces an error for one module, and Go 1.16
+# produces a different error for a different module.
+
+cp go.mod go.mod.orig
+
+! go mod tidy
+
+stderr '^example\.com/m imports\n\texample\.net/added: module example\.net/added@latest found \(v0\.3\.0, replaced by \./a1\), but does not contain package example\.net/added$'
+
+cmp go.mod go.mod.orig
+
+
+# When we run 'go mod tidy -e', we should proceed past the first error and follow
+# it with a second error describing the version descrepancy.
+#
+# We should not provide advice on how to push past the version descrepancy,
+# because the '-e' flag should already do that, writing out an otherwise-tidied
+# go.mod file.
+
+go mod tidy -e
+
+stderr '^example\.com/m imports\n\texample\.net/added: module example\.net/added@latest found \(v0\.3\.0, replaced by \./a1\), but does not contain package example\.net/added\nexample\.net/added failed to load from any module,\n\tbut go 1\.16 would load it from example\.net/added@v0\.2\.0$'
+
+! stderr '\n\tgo mod tidy'
+
+cmp go.mod go.mod.tidy
+
+
+-- go.mod --
+module example.com/m
+
+go 1.17
+
+replace (
+       example.net/added v0.1.0 => ./a1
+       example.net/added v0.2.0 => ./a2
+       example.net/added v0.3.0 => ./a1
+       example.net/lazy v0.1.0 => ./lazy
+       example.net/pruned v0.1.0 => ./pruned
+)
+
+require (
+       example.net/added v0.1.0
+       example.net/lazy v0.1.0
+)
+-- go.mod.tidy --
+module example.com/m
+
+go 1.17
+
+replace (
+       example.net/added v0.1.0 => ./a1
+       example.net/added v0.2.0 => ./a2
+       example.net/added v0.3.0 => ./a1
+       example.net/lazy v0.1.0 => ./lazy
+       example.net/pruned v0.1.0 => ./pruned
+)
+
+require example.net/lazy v0.1.0
+-- m.go --
+package m
+
+import (
+       _ "example.net/added"
+       _ "example.net/lazy"
+)
+
+-- a1/go.mod --
+module example.net/added
+
+go 1.17
+-- a2/go.mod --
+module example.net/added
+
+go 1.17
+-- a2/added.go --
+package added
+
+-- lazy/go.mod --
+module example.net/lazy
+
+go 1.17
+
+require example.net/pruned v0.1.0
+-- lazy/lazy.go --
+package lazy
+
+-- pruned/go.mod --
+module example.net/pruned
+
+go 1.17
+
+require example.net/added v0.2.0
diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt
new file mode 100644 (file)
index 0000000..c544cb7
--- /dev/null
@@ -0,0 +1,98 @@
+# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
+# default preserve enough checksums for the module to be used by Go 1.16.
+#
+# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
+# 'go' version in the go.mod file to 1.16, without actually updating the
+# requirements to match.
+
+[short] skip
+
+env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
+
+# For this module, the dependency providing package
+# example.net/ambiguous/nested/pkg is unambiguous in Go 1.17 (because only one
+# root of the module graph contains the package), whereas it is ambiguous in
+# Go 1.16 (because two different modules contain plausible packages and Go 1.16
+# does not privilege roots above other dependencies).
+#
+# However, the overall build list is identical for both versions.
+
+cp go.mod go.mod.orig
+
+! go mod tidy
+
+stderr '^example\.com/m imports\n\texample\.net/indirect imports\n\texample\.net/ambiguous/nested/pkg loaded from example\.net/ambiguous/nested@v0\.1\.0,\n\tbut go 1.16 would fail to locate it:\n\tambiguous import: found package example\.net/ambiguous/nested/pkg in multiple modules:\n\texample\.net/ambiguous v0.1.0 \(.*\)\n\texample\.net/ambiguous/nested v0.1.0 \(.*\)\n\n'
+
+stderr '\n\nTo proceed despite packages unresolved in go 1\.16:\n\tgo mod tidy -e\nIf reproducibility with go 1.16 is not needed:\n\tgo mod tidy -compat=1\.17\nFor other options, see:\n\thttps://golang\.org/doc/modules/pruning\n'
+
+cmp go.mod go.mod.orig
+
+
+# If we run 'go mod tidy -e', we should still save enough checksums to run
+# 'go list -m all' reproducibly with go 1.16, even though we can't list
+# the specific package.
+
+go mod tidy -e
+! stderr '\n\tgo mod tidy'
+cmp go.mod go.mod.orig
+
+go list -m all
+cmp stdout all-m.txt
+
+go list -f $MODFMT example.net/ambiguous/nested/pkg
+stdout '^example.net/ambiguous/nested v0\.1\.0$'
+! stderr .
+
+go mod edit -go=1.16
+go list -m all
+cmp stdout all-m.txt
+
+! go list -f $MODFMT example.net/ambiguous/nested/pkg
+stderr '^ambiguous import: found package example\.net/ambiguous/nested/pkg in multiple modules:\n\texample\.net/ambiguous v0\.1\.0 \(.*\)\n\texample\.net/ambiguous/nested v0\.1\.0 \(.*\)\n'
+
+
+# On the other hand, if we use -compat=1.17, 1.16 can't even load
+# the build list (due to missing checksums).
+
+cp go.mod.orig go.mod
+go mod tidy -compat=1.17
+! stderr .
+go list -m all
+cmp stdout all-m.txt
+
+go mod edit -go=1.16
+! go list -m all
+stderr '^go list -m: example\.net/indirect@v0\.1\.0 requires\n\texample\.net/ambiguous@v0\.1\.0: missing go\.sum entry; to add it:\n\tgo mod download example\.net/ambiguous\n'
+
+
+-- go.mod --
+module example.com/m
+
+go 1.17
+
+replace example.net/indirect v0.1.0 => ./indirect
+
+require (
+       example.net/ambiguous/nested v0.1.0 // indirect
+       example.net/indirect v0.1.0
+)
+-- all-m.txt --
+example.com/m
+example.net/ambiguous v0.1.0
+example.net/ambiguous/nested v0.1.0
+example.net/indirect v0.1.0 => ./indirect
+-- m.go --
+package m
+
+import _ "example.net/indirect"
+
+-- indirect/go.mod --
+module example.net/indirect
+
+go 1.17
+
+require example.net/ambiguous v0.1.0
+-- indirect/indirect.go --
+package indirect
+
+import _ "example.net/ambiguous/nested/pkg"
diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_compat_deleted.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_compat_deleted.txt
new file mode 100644 (file)
index 0000000..dcf13e2
--- /dev/null
@@ -0,0 +1,128 @@
+# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
+# default preserve enough checksums for the module to be used by Go 1.16.
+#
+# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
+# 'go' version in the go.mod file to 1.16, without actually updating the
+# requirements to match.
+
+[short] skip
+
+env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
+
+
+# For this module, the "deleted" dependency contains an imported package, but
+# Go 1.16 selects a higher version (in which that package has been deleted).
+
+cp go.mod go.mod.orig
+
+! go mod tidy
+
+stderr '^example\.com/m imports\n\texample\.net/deleted loaded from example\.net/deleted@v0\.1\.0,\n\tbut go 1\.16 would fail to locate it in example\.net/deleted@v0\.2\.0\n\n'
+
+stderr '\n\nTo upgrade to the versions selected by go 1.16, leaving some packages unresolved:\n\tgo mod tidy -e -go=1\.16 && go mod tidy -e -go=1\.17\nIf reproducibility with go 1.16 is not needed:\n\tgo mod tidy -compat=1\.17\nFor other options, see:\n\thttps://golang\.org/doc/modules/pruning\n'
+
+
+# The suggested 'go mod tidy -e' command should proceed anyway.
+
+go mod tidy -e
+cmp go.mod go.mod.tidy
+
+
+# In 'go 1.16' mode we should error out in the way we claimed.
+
+cd 116-outside
+! go list -deps -f $MODFMT example.com/m
+stderr '^\.\.[/\\]m\.go:4:2: no required module provides package example\.net/deleted; to add it:\n\tgo get example\.net/deleted$'
+cd ..
+
+go mod edit -go=1.16
+! go list -deps -f $MODFMT example.com/m
+stderr '^go: updates to go\.mod needed; to update it:\n\tgo mod tidy$'
+
+! go mod tidy
+stderr '^example\.com/m imports\n\texample\.net/deleted: module example\.net/deleted@latest found \(v0\.2\.0, replaced by \./d2\), but does not contain package example\.net/deleted$'
+
+
+-- go.mod --
+module example.com/m
+
+go 1.17
+
+replace (
+       example.net/deleted v0.1.0 => ./d1
+       example.net/deleted v0.2.0 => ./d2
+       example.net/lazy v0.1.0 => ./lazy
+       example.net/pruned v0.1.0 => ./pruned
+)
+
+require (
+       example.net/deleted v0.1.0
+       example.net/deleted v0.1.0 // redundant
+       example.net/lazy v0.1.0
+)
+-- go.mod.tidy --
+module example.com/m
+
+go 1.17
+
+replace (
+       example.net/deleted v0.1.0 => ./d1
+       example.net/deleted v0.2.0 => ./d2
+       example.net/lazy v0.1.0 => ./lazy
+       example.net/pruned v0.1.0 => ./pruned
+)
+
+require (
+       example.net/deleted v0.1.0
+       example.net/lazy v0.1.0
+)
+-- 116-outside/go.mod --
+module outside
+
+go 1.16
+
+replace (
+       example.com/m => ../
+       example.net/deleted v0.1.0 => ../d1
+       example.net/deleted v0.2.0 => ../d2
+       example.net/lazy v0.1.0 => ../lazy
+       example.net/pruned v0.1.0 => ../pruned
+)
+
+require example.com/m v0.1.0
+-- m.go --
+package m
+
+import (
+       _ "example.net/deleted"
+       _ "example.net/lazy"
+)
+
+-- d1/go.mod --
+module example.net/deleted
+
+go 1.17
+-- d1/deleted.go --
+package deleted
+-- d2/go.mod --
+module example.net/deleted
+
+go 1.17
+-- d2/README --
+There is no longer a Go package here.
+
+-- lazy/go.mod --
+module example.net/lazy
+
+go 1.17
+
+require example.net/pruned v0.1.0
+-- lazy/lazy.go --
+package lazy
+
+-- pruned/go.mod --
+module example.net/pruned
+
+go 1.17
+
+require example.net/deleted v0.2.0
diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_compat_implicit.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_compat_implicit.txt
new file mode 100644 (file)
index 0000000..186a3f8
--- /dev/null
@@ -0,0 +1,129 @@
+# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
+# default preserve enough checksums for the module to be used by Go 1.16.
+#
+# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
+# 'go' version in the go.mod file to 1.16, without actually updating the
+# requirements to match.
+
+[short] skip
+
+env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
+
+
+# For this module, Go 1.16 selects the same versions of all explicit dependencies
+# as Go 1.17 does. However, Go 1.16 selects a higher version of an *implicit*
+# dependency, imported by a test of one of the (external) imported packages.
+# As a result, Go 1.16 also needs checksums for the module sources for that higher
+# version.
+#
+# The Go 1.16 module graph looks like:
+#
+# m ---- lazy v0.1.0 ---- incompatible v1.0.0
+#         |
+#         + ------------- requireincompatible v0.1.0 ---- incompatible v2.0.0+incompatible
+#
+# The Go 1.17 module graph is the same except that the dependencies of
+# requireincompatible are pruned out (because the module that requires
+# it — lazy v0.1.0 — specifies 'go 1.17', and it is not otherwise relevant to
+# the main module).
+
+# 'go mod tidy' should by default diagnose the difference in dependencies as an
+# error, with useful suggestions about how to resolve it.
+
+cp go.mod go.mod.orig
+! go mod tidy
+stderr '^example\.com/m imports\n\texample\.net/lazy tested by\n\texample\.net/lazy.test imports\n\texample\.com/retract/incompatible loaded from example\.com/retract/incompatible@v1\.0\.0,\n\tbut go 1\.16 would select v2\.0\.0\+incompatible\n\n'
+stderr '\n\nTo upgrade to the versions selected by go 1\.16:\n\tgo mod tidy -go=1\.16 && go mod tidy -go=1\.17\nIf reproducibility with go 1.16 is not needed:\n\tgo mod tidy -compat=1.17\nFor other options, see:\n\thttps://golang\.org/doc/modules/pruning\n'
+
+cmp go.mod go.mod.orig
+
+# The suggested '-compat' flag to ignore differences should silence the error
+# and leave go.mod unchanged, resulting in checksum errors when Go 1.16 tries
+# to load a module pruned out by Go 1.17.
+
+go mod tidy -compat=1.17
+! stderr .
+cmp go.mod go.mod.orig
+
+go list -deps -test -f $MODFMT all
+stdout '^example\.com/retract/incompatible v1\.0\.0$'
+
+go mod edit -go=1.16
+! go list -deps -test -f $MODFMT all
+
+       # TODO(#46160): -count=1 instead of -count=2.
+stderr -count=2 '^go: example\.net/lazy@v0\.1\.0 requires\n\texample\.com/retract/incompatible@v1\.0\.0: missing go\.sum entry; to add it:\n\tgo mod download example\.com/retract/incompatible$'
+
+
+# If we combine a Go 1.16 go.sum file...
+go mod tidy -go=1.16
+
+# ...with a Go 1.17 go.mod file...
+cp go.mod.orig go.mod
+
+# ...then Go 1.17 no longer works. 😞
+! go list -deps -test -f $MODFMT all
+stderr -count=1 '^can''t load test package: lazy[/\\]lazy_test.go:3:8: missing go\.sum entry for module providing package example\.com/retract/incompatible \(imported by example\.net/lazy\); to add:\n\tgo get -t example.net/lazy@v0\.1\.0$'
+
+
+# However, if we take the union of the go.sum files...
+go list -mod=mod -deps -test all
+cmp go.mod go.mod.orig
+
+# ...then Go 1.17 continues to work...
+go list -deps -test -f $MODFMT all
+stdout '^example\.com/retract/incompatible v1\.0\.0$'
+
+# ...and 1.16 also works(‽), but selects a different version for the
+# external-test dependency.
+go mod edit -go=1.16
+go list -deps -test -f $MODFMT all
+stdout '^example\.com/retract/incompatible v2\.0\.0\+incompatible$'
+
+
+-- go.mod --
+// Module m imports packages from the same versions under Go 1.17
+// as under Go 1.16, but under 1.16 its (implicit) external test dependencies
+// are higher.
+module example.com/m
+
+go 1.17
+
+replace (
+       example.net/lazy v0.1.0 => ./lazy
+       example.net/requireincompatible v0.1.0 => ./requireincompatible
+)
+
+require example.net/lazy v0.1.0
+-- implicit.go --
+package implicit
+
+import _ "example.net/lazy"
+-- lazy/go.mod --
+// Module lazy requires example.com/retract/incompatible v1.0.0.
+//
+// When viewed from the outside it also has a transitive dependency
+// on v2.0.0+incompatible, but in lazy mode that transitive dependency
+// is pruned out.
+module example.net/lazy
+
+go 1.17
+
+exclude example.com/retract/incompatible v2.0.0+incompatible
+
+require (
+       example.com/retract/incompatible v1.0.0
+       example.net/requireincompatible v0.1.0
+)
+-- lazy/lazy.go --
+package lazy
+-- lazy/lazy_test.go --
+package lazy_test
+
+import _ "example.com/retract/incompatible"
+-- requireincompatible/go.mod --
+module example.net/requireincompatible
+
+go 1.15
+
+require example.com/retract/incompatible v2.0.0+incompatible
diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_compat_incompatible.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_compat_incompatible.txt
new file mode 100644 (file)
index 0000000..ea9e42e
--- /dev/null
@@ -0,0 +1,135 @@
+# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
+# default preserve enough checksums for the module to be used by Go 1.16.
+#
+# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
+# 'go' version in the go.mod file to 1.16, without actually updating the
+# requirements to match.
+
+[short] skip
+
+env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
+
+
+# For this module, Go 1.17 prunes out a (transitive and otherwise-irrelevant)
+# requirement on a retracted higher version of a dependency.
+# However, when Go 1.16 reads the same requirements from the go.mod file,
+# it does not prune out that requirement, and selects the retracted version.
+#
+# The Go 1.16 module graph looks like:
+#
+# m ---- lazy v0.1.0 ---- requireincompatible v0.1.0 ---- incompatible v2.0.0+incompatible
+# |        |
+# + -------+------------- incompatible v1.0.0
+#
+# The Go 1.17 module graph is the same except that the dependencies of
+# requireincompatible are pruned out (because the module that requires
+# it — lazy v0.1.0 — specifies 'go 1.17', and it is not otherwise relevant to
+# the main module).
+
+
+# 'go mod tidy' should by default diagnose the difference in dependencies as an
+# error, with useful suggestions about how to resolve it.
+
+cp go.mod go.mod.orig
+! go mod tidy
+stderr '^example\.com/m imports\n\texample\.net/lazy imports\n\texample\.com/retract/incompatible loaded from example\.com/retract/incompatible@v1\.0\.0,\n\tbut go 1\.16 would select v2\.0\.0\+incompatible\n\n'
+stderr '\n\nTo upgrade to the versions selected by go 1\.16:\n\tgo mod tidy -go=1\.16 && go mod tidy -go=1\.17\nIf reproducibility with go 1\.16 is not needed:\n\tgo mod tidy -compat=1.17\nFor other options, see:\n\thttps://golang\.org/doc/modules/pruning\n'
+
+cmp go.mod go.mod.orig
+
+
+# The suggested '-compat' flag to ignore differences should silence the error
+# and leave go.mod unchanged, resulting in checksum errors when Go 1.16 tries
+# to load a module pruned out by Go 1.17.
+
+go mod tidy -compat=1.17
+! stderr .
+cmp go.mod go.mod.orig
+
+go mod edit -go=1.16
+! go list -f $MODFMT -deps ./...
+       # TODO(#46160): -count=1 instead of -count=2.
+stderr -count=2 '^go: example\.net/lazy@v0\.1\.0 requires\n\texample\.net/requireincompatible@v0\.1\.0 requires\n\texample\.com/retract/incompatible@v2\.0\.0\+incompatible: missing go.sum entry; to add it:\n\tgo mod download example.com/retract/incompatible$'
+
+
+# There are two ways for the module author to bring the two into alignment.
+# One is to *explicitly* 'exclude' the version that is already *implicitly*
+# pruned out under 1.17.
+
+go mod edit -exclude=example.com/retract/incompatible@v2.0.0+incompatible
+go list -f $MODFMT -deps ./...
+stdout '^example.com/retract/incompatible v1\.0\.0$'
+! stdout 'v2\.0\.0'
+
+
+# The other is to explicitly upgrade the version required under Go 1.17
+# to match the version selected by Go 1.16. The commands suggested by
+# 'go mod tidy' should do exactly that.
+
+cp go.mod.orig go.mod
+
+go mod tidy -go=1.16
+go list -f $MODFMT -deps ./...
+stdout '^example.com/retract/incompatible v2\.0\.0\+incompatible$'
+! stdout 'v1\.0\.0'
+
+go mod tidy -go=1.17
+go list -f $MODFMT -deps ./...
+stdout '^example.com/retract/incompatible v2\.0\.0\+incompatible$'
+! stdout 'v1\.0\.0'
+
+go mod edit -go=1.16
+go list -f $MODFMT -deps ./...
+stdout '^example.com/retract/incompatible v2\.0\.0\+incompatible$'
+! stdout 'v1\.0\.0'
+
+
+-- go.mod --
+// Module m indirectly imports a package from
+// example.com/retract/incompatible. Its selected version of
+// that module is lower under Go 1.17 semantics than under Go 1.16.
+module example.com/m
+
+go 1.17
+
+replace (
+       example.net/lazy v0.1.0 => ./lazy
+       example.net/requireincompatible v0.1.0 => ./requireincompatible
+)
+
+require (
+       example.com/retract/incompatible v1.0.0 // indirect
+       example.net/lazy v0.1.0
+)
+-- incompatible.go --
+package incompatible
+
+import _ "example.net/lazy"
+
+-- lazy/go.mod --
+// Module lazy requires example.com/retract/incompatible v1.0.0.
+//
+// When viewed from the outside it also has a transitive dependency
+// on v2.0.0+incompatible, but in lazy mode that transitive dependency
+// is pruned out.
+module example.net/lazy
+
+go 1.17
+
+exclude example.com/retract/incompatible v2.0.0+incompatible
+
+require (
+       example.com/retract/incompatible v1.0.0
+       example.net/requireincompatible v0.1.0
+)
+-- lazy/lazy.go --
+package lazy
+
+import _ "example.com/retract/incompatible"
+
+-- requireincompatible/go.mod --
+module example.net/requireincompatible
+
+go 1.15
+
+require example.com/retract/incompatible v2.0.0+incompatible
diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_compat_irrelevant.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_compat_irrelevant.txt
new file mode 100644 (file)
index 0000000..7c22fca
--- /dev/null
@@ -0,0 +1,99 @@
+# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
+# default preserve enough checksums for the module to be used by Go 1.16.
+#
+# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
+# 'go' version in the go.mod file to 1.16, without actually updating the
+# requirements to match.
+
+[short] skip
+
+env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
+
+
+# This module selects the same versions in Go 1.16 and 1.17 for all modules
+# that provide packages (or test dependencies of packages) imported by the
+# main module. However, in Go 1.16 it selects a higher version of a
+# transitive module dependency that is not otherwise relevant to the main module.
+# As a result, Go 1.16 needs an additional checksum for the go.mod file of
+# that irrelevant dependency.
+#
+# The Go 1.16 module graph looks like:
+#
+# m ---- lazy v0.1.0 ---- incompatible v1.0.0
+#         |
+#         + ------------- requireincompatible v0.1.0 ---- incompatible v2.0.0+incompatible
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod go.mod.orig
+
+go list -deps -test -f $MODFMT all
+cp stdout out-117.txt
+
+go mod edit -go=1.16
+go list -deps -test -f $MODFMT all
+cmp stdout out-117.txt
+
+
+# If we explicitly drop compatibility with 1.16, we retain fewer checksums,
+# which gives a cleaner go.sum file but causes 1.16 to fail in readonly mode.
+
+cp go.mod.orig go.mod
+go mod tidy -compat=1.17
+cmp go.mod go.mod.orig
+
+go list -deps -test -f $MODFMT all
+cmp stdout out-117.txt
+
+go mod edit -go=1.16
+! go list -deps -test -f $MODFMT all
+       # TODO(#46160): -count=1 instead of -count=2.
+stderr -count=2 '^go: example.net/lazy@v0.1.0 requires\n\texample.com/retract/incompatible@v1.0.0: missing go.sum entry; to add it:\n\tgo mod download example.com/retract/incompatible$'
+
+
+-- go.mod --
+// Module m imports packages from the same versions under Go 1.17
+// as under Go 1.16, but under 1.16 its (implicit) external test dependencies
+// are higher.
+module example.com/m
+
+go 1.17
+
+replace (
+       example.net/lazy v0.1.0 => ./lazy
+       example.net/requireincompatible v0.1.0 => ./requireincompatible
+)
+
+require example.net/lazy v0.1.0
+-- m.go --
+package m
+
+import _ "example.net/lazy"
+-- lazy/go.mod --
+// Module lazy requires example.com/retract/incompatible v1.0.0.
+//
+// When viewed from the outside it also has a transitive dependency
+// on v2.0.0+incompatible, but in lazy mode that transitive dependency
+// is pruned out.
+module example.net/lazy
+
+go 1.17
+
+exclude example.com/retract/incompatible v2.0.0+incompatible
+
+require (
+       example.com/retract/incompatible v1.0.0
+       example.net/requireincompatible v0.1.0
+)
+-- lazy/lazy.go --
+package lazy
+-- lazy/unimported/unimported.go --
+package unimported
+
+import _ "example.com/retract/incompatible"
+-- requireincompatible/go.mod --
+module example.net/requireincompatible
+
+go 1.15
+
+require example.com/retract/incompatible v2.0.0+incompatible
diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_convergence.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_convergence.txt
new file mode 100644 (file)
index 0000000..09c46f7
--- /dev/null
@@ -0,0 +1,202 @@
+# This test demonstrates a simple case in which 'go mod tidy' may resolve a
+# missing package, only to remove that package when resolving its dependencies.
+#
+# If we naively iterate 'go mod tidy' until the dependency graph converges, this
+# scenario may fail to converge.
+
+# The import graph used in this test looks like:
+#
+# m --- x
+#       |
+#       x_test --- y
+#
+# The module dependency graph of m is initially empty.
+# Modules x and y look like:
+#
+# x.1 (provides package x that imports y, but does not depend on module y)
+#
+# x.2-pre (no dependencies, but does not provide package x)
+#
+# y.1 (no dependencies, but provides package y)
+#
+# y.2 --- x.2-pre (provides package y)
+#
+#
+# When we resolve the missing import of y in x_test, we add y@latest — which is
+# y.2, not y.1 — as a new dependency. That upgrades to x to x.2-pre, which
+# removes package x (and also the need for module y). We can then safely remove
+# the dependency on module y, because nothing imports package y any more!
+#
+# We might be tempted to remove the dependency on module x for the same reason:
+# it no longer provides any imported package. However, that would cause 'go mod
+# tidy -e' to become unstable: with x.2-pre out of the way, we could once again
+# resolve the missing import of package x by re-adding x.1.
+
+cp go.mod go.mod.orig
+
+# 'go mod tidy' without -e should fail without modifying go.mod,
+# because it cannot resolve x and y simultaneously.
+! go mod tidy
+
+cmp go.mod go.mod.orig
+
+stderr '^go: found example\.net/y in example\.net/y v0.2.0$'
+stderr '^go: finding module for package example\.net/x$'
+
+       # TODO: This error message should be clearer — it doesn't indicate why v0.2.0-pre is required.
+stderr '^example\.net/m imports\n\texample\.net/x: package example\.net/x provided by example\.net/x at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$'
+
+
+# 'go mod tidy -e' should follow upgrades to try to resolve the modules that it
+# can, and then stop. When we resolve example.net/y, we upgrade to example.net/x
+# to v0.2.0-pre. At that version, package x no longer exists and no longer
+# imports package y, so the import of x should be left unsatisfied and the
+# existing dependency on example.net/x removed.
+#
+# TODO(bcmills): It would be ever better if we could keep the original
+# dependency on example.net/x v0.1.0, but I don't see a way to do that without
+# making the algorithm way too complicated. (We would have to detect that the
+# new dependency on example.net/y interferes with the package that caused us to
+# to add that dependency in the first place, and back out that part of the change
+# without also backing out any other needed changes.)
+
+go mod tidy -e
+cmp go.mod go.mod.tidye
+stderr '^go: found example\.net/y in example\.net/y v0.2.0$'
+
+       # TODO: This error message should be clearer — it doesn't indicate why v0.2.0-pre is required.
+stderr '^example\.net/m imports\n\texample\.net/x: package example\.net/x provided by example\.net/x at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$'
+
+
+# Since we attempt to resolve the dependencies of package x whenever we add x itself,
+# this end state is stable.
+
+go mod tidy -e
+cmp go.mod go.mod.tidye
+
+
+# An explicit 'go get' with the correct versions should allow 'go mod tidy' to
+# succeed and remain stable. y.1 does not upgrade x, and can therefore be used
+# with it.
+
+go get -d example.net/x@v0.1.0 example.net/y@v0.1.0
+go mod tidy
+cmp go.mod go.mod.postget
+
+
+# The 'tidy' logic for a lazy main module is somewhat different from that for an
+# eager main module, but the overall behavior is the same.
+
+cp go.mod.orig go.mod
+go mod edit -go=1.17 go.mod
+go mod edit -go=1.17 go.mod.tidye
+
+go mod tidy -e
+cmp go.mod go.mod.tidye
+stderr '^go: found example\.net/y in example\.net/y v0.2.0$'
+stderr '^example\.net/m imports\n\texample\.net/x: package example\.net/x provided by example\.net/x at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$'
+
+go get -d example.net/x@v0.1.0 example.net/y@v0.1.0
+go mod tidy
+cmp go.mod go.mod.postget-117
+
+
+-- go.mod --
+module example.net/m
+
+go 1.16
+
+replace (
+       example.net/x v0.1.0 => ./x1
+       example.net/x v0.2.0-pre => ./x2-pre
+       example.net/y v0.1.0 => ./y1
+       example.net/y v0.2.0 => ./y2
+)
+
+require (
+       example.net/x v0.1.0
+)
+-- go.mod.tidye --
+module example.net/m
+
+go 1.16
+
+replace (
+       example.net/x v0.1.0 => ./x1
+       example.net/x v0.2.0-pre => ./x2-pre
+       example.net/y v0.1.0 => ./y1
+       example.net/y v0.2.0 => ./y2
+)
+-- go.mod.postget --
+module example.net/m
+
+go 1.16
+
+replace (
+       example.net/x v0.1.0 => ./x1
+       example.net/x v0.2.0-pre => ./x2-pre
+       example.net/y v0.1.0 => ./y1
+       example.net/y v0.2.0 => ./y2
+)
+
+require (
+       example.net/x v0.1.0
+       example.net/y v0.1.0 // indirect
+)
+-- go.mod.postget-117 --
+module example.net/m
+
+go 1.17
+
+replace (
+       example.net/x v0.1.0 => ./x1
+       example.net/x v0.2.0-pre => ./x2-pre
+       example.net/y v0.1.0 => ./y1
+       example.net/y v0.2.0 => ./y2
+)
+
+require example.net/x v0.1.0
+
+require example.net/y v0.1.0 // indirect
+-- m.go --
+package m
+
+import _ "example.net/x"
+
+-- x1/go.mod --
+module example.net/x
+
+go 1.16
+-- x1/x.go --
+package x
+-- x1/x_test.go --
+package x
+
+import _ "example.net/y"
+
+-- x2-pre/go.mod --
+module example.net/x
+
+go 1.16
+-- x2-pre/README.txt --
+There is no package x here. Use example.com/x/subpkg instead.
+-- x2-pre/subpkg/subpkg.go --
+package subpkg  // import "example.net/x/subpkg"
+
+-- y1/go.mod --
+module example.net/y
+
+go 1.16
+-- y1/y.go --
+package y
+
+-- y2/go.mod --
+module example.net/y
+
+go 1.16
+
+require example.net/x v0.2.0-pre
+-- y2/y.go --
+package y
+
+import _ "example.net/x/subpkg"
diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_convergence_loop.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_convergence_loop.txt
new file mode 100644 (file)
index 0000000..3c4d324
--- /dev/null
@@ -0,0 +1,329 @@
+# This test demonstrates a simple case in which 'go mod tidy' may resolve a
+# missing package, only to remove that package when resolving its dependencies.
+#
+# If we naively iterate 'go mod tidy' until the dependency graph converges, this
+# scenario may fail to converge.
+
+# The import graph used in this test looks like:
+#
+# m --- w
+# |
+# + --- x
+# |
+# + --- y
+# |
+# + --- z
+#
+# The module dependency graph of m initially contains w.1 (and, by extension,
+# y.2-pre and z.2-pre). This is an arbitrary point in the cycle of possible
+# configurations.
+#
+# w.1 requires y.2-pre and z.2-pre
+# x.1 requires z.2-pre and w.2-pre
+# y.1 requires w.2-pre and x.2-pre
+# z.1 requires x.2-pre and y.2-pre
+#
+# At each point, exactly one missing package can be resolved by adding a
+# dependency on the .1 release of the module that provides that package.
+# However, adding that dependency causes the module providing another package to
+# roll over from its .1 release to its .2-pre release, which removes the
+# package. Once the package is removed, 'go mod tidy -e' no longer sees the
+# module as relevant to the main module, and will happily remove the existing
+# dependency on it.
+#
+# The cycle is of length 4 so that at every step only one package can be
+# resolved. This is important because it prevents the iteration from ever
+# reaching a state in which every package is simultaneously over-upgraded — such
+# a state is stable and does not exhibit failure to converge.
+
+cp go.mod go.mod.orig
+
+# 'go mod tidy' without -e should fail without modifying go.mod,
+# because it cannot resolve x, y, and z simultaneously.
+! go mod tidy
+
+cmp go.mod go.mod.orig
+
+stderr '^go: finding module for package example\.net/w$'
+stderr '^go: finding module for package example\.net/x$'
+stderr -count=2 '^go: finding module for package example\.net/y$'
+stderr -count=2 '^go: finding module for package example\.net/z$'
+stderr '^go: found example\.net/x in example\.net/x v0.1.0$'
+
+       # TODO: These error messages should be clearer — it doesn't indicate why v0.2.0-pre is required.
+stderr '^example\.net/m imports\n\texample\.net/w: package example\.net/w provided by example\.net/w at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$'
+stderr '^example\.net/m imports\n\texample\.net/y: package example\.net/y provided by example\.net/y at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$'
+stderr '^example\.net/m imports\n\texample\.net/z: package example\.net/z provided by example\.net/z at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$'
+
+
+# 'go mod tidy -e' should preserve all of the upgrades to modules that could
+# provide the missing packages but don't. That would at least explain why they
+# are missing, and why no individual module can be upgraded in order to satisfy
+# a missing import.
+#
+# TODO(bcmills): Today, it doesn't preserve those upgrades, and instead advances
+# the state by one through the cycle of semi-tidy states.
+
+go mod tidy -e
+
+cmp go.mod go.mod.tidye1
+
+stderr '^go: finding module for package example\.net/w$'
+stderr '^go: finding module for package example\.net/x$'
+stderr -count=2 '^go: finding module for package example\.net/y$'
+stderr -count=2 '^go: finding module for package example\.net/z$'
+stderr '^go: found example\.net/x in example\.net/x v0.1.0$'
+
+stderr '^example\.net/m imports\n\texample\.net/w: package example\.net/w provided by example\.net/w at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$'
+stderr '^example\.net/m imports\n\texample\.net/y: package example\.net/y provided by example\.net/y at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$'
+stderr '^example\.net/m imports\n\texample\.net/z: package example\.net/z provided by example\.net/z at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$'
+
+
+go mod tidy -e
+cmp go.mod go.mod.tidye2
+
+go mod tidy -e
+cmp go.mod go.mod.tidye3
+
+go mod tidy -e
+cmp go.mod go.mod.orig
+
+
+# If we upgrade away all of the packages simultaneously, the resulting tidy
+# state converges at "no dependencies", because simultaneously adding all of the
+# packages simultaneously over-upgrades all of the dependencies, and 'go mod
+# tidy' treats "no package can be added" as a terminal state.
+
+go get -d example.net/w@v0.2.0-pre example.net/x@v0.2.0-pre example.net/y@v0.2.0-pre example.net/z@v0.2.0-pre
+go mod tidy -e
+cmp go.mod go.mod.postget
+go mod tidy -e
+cmp go.mod go.mod.postget
+
+
+# The 'tidy' logic for a lazy main module requires more iterations to converge,
+# because it is willing to drop dependencies on non-root modules that do not
+# otherwise provide imported packages.
+#
+# On the first iteration, it adds x.1 as a root, which upgrades z and w,
+# dropping w.1's requirement on y. w.1 was initially a root, so the upgraded
+# w.2-pre is retained as a root.
+#
+# On the second iteration, it adds y.1 as a root, which upgrades w and x,
+# dropping x.1's requirement on z. x.1 was added as a root in the previous step,
+# so the upgraded x.2-pre is retained as a root.
+#
+# On the third iteration, it adds z.1 as a root, which upgrades x and y.
+# x and y were already roots (from the previous steps), so their upgraded versions
+# are retained (not dropped) and the iteration stops.
+#
+# At that point, we have z.1 as a root providing package z,
+# and w, x, and y have all been upgraded to no longer provide any packages.
+# So only z is retained as a new root.
+#
+# (From the above, we can see that in a lazy module we still cycle through the
+# same possible root states, but in a different order from the eager case.)
+#
+# TODO(bcmills): if we retained the upgrades on w, x, and y (since they are
+# lexical prefixes for unresolved packages w, x, and y, respectively), then 'go
+# mod tidy -e' itself would become stable and no longer cycle through states.
+
+cp go.mod.orig go.mod
+go mod edit -go=1.17 go.mod
+cp go.mod go.mod.117
+go mod edit -go=1.17 go.mod.tidye1
+go mod edit -go=1.17 go.mod.tidye2
+go mod edit -go=1.17 go.mod.tidye3
+go mod edit -go=1.17 go.mod.postget
+
+go list -m all
+
+go mod tidy -e
+cmp go.mod go.mod.tidye3
+
+go mod tidy -e
+cmp go.mod go.mod.tidye2
+
+go mod tidy -e
+cmp go.mod go.mod.tidye1
+
+go mod tidy -e
+cmp go.mod go.mod.117
+
+
+# As in the eager case, for the lazy module the fully-upgraded dependency graph
+# becomes empty, and the empty graph is stable.
+
+go get -d example.net/w@v0.2.0-pre example.net/x@v0.2.0-pre example.net/y@v0.2.0-pre example.net/z@v0.2.0-pre
+go mod tidy -e
+cmp go.mod go.mod.postget
+go mod tidy -e
+cmp go.mod go.mod.postget
+
+
+-- m.go --
+package m
+
+import (
+       _ "example.net/w"
+       _ "example.net/x"
+       _ "example.net/y"
+       _ "example.net/z"
+)
+
+-- go.mod --
+module example.net/m
+
+go 1.16
+
+replace (
+       example.net/w v0.1.0 => ./w1
+       example.net/w v0.2.0-pre => ./w2-pre
+       example.net/x v0.1.0 => ./x1
+       example.net/x v0.2.0-pre => ./x2-pre
+       example.net/y v0.1.0 => ./y1
+       example.net/y v0.2.0-pre => ./y2-pre
+       example.net/z v0.1.0 => ./z1
+       example.net/z v0.2.0-pre => ./z2-pre
+)
+
+require example.net/w v0.1.0
+-- go.mod.tidye1 --
+module example.net/m
+
+go 1.16
+
+replace (
+       example.net/w v0.1.0 => ./w1
+       example.net/w v0.2.0-pre => ./w2-pre
+       example.net/x v0.1.0 => ./x1
+       example.net/x v0.2.0-pre => ./x2-pre
+       example.net/y v0.1.0 => ./y1
+       example.net/y v0.2.0-pre => ./y2-pre
+       example.net/z v0.1.0 => ./z1
+       example.net/z v0.2.0-pre => ./z2-pre
+)
+
+require example.net/x v0.1.0
+-- go.mod.tidye2 --
+module example.net/m
+
+go 1.16
+
+replace (
+       example.net/w v0.1.0 => ./w1
+       example.net/w v0.2.0-pre => ./w2-pre
+       example.net/x v0.1.0 => ./x1
+       example.net/x v0.2.0-pre => ./x2-pre
+       example.net/y v0.1.0 => ./y1
+       example.net/y v0.2.0-pre => ./y2-pre
+       example.net/z v0.1.0 => ./z1
+       example.net/z v0.2.0-pre => ./z2-pre
+)
+
+require example.net/y v0.1.0
+-- go.mod.tidye3 --
+module example.net/m
+
+go 1.16
+
+replace (
+       example.net/w v0.1.0 => ./w1
+       example.net/w v0.2.0-pre => ./w2-pre
+       example.net/x v0.1.0 => ./x1
+       example.net/x v0.2.0-pre => ./x2-pre
+       example.net/y v0.1.0 => ./y1
+       example.net/y v0.2.0-pre => ./y2-pre
+       example.net/z v0.1.0 => ./z1
+       example.net/z v0.2.0-pre => ./z2-pre
+)
+
+require example.net/z v0.1.0
+-- go.mod.postget --
+module example.net/m
+
+go 1.16
+
+replace (
+       example.net/w v0.1.0 => ./w1
+       example.net/w v0.2.0-pre => ./w2-pre
+       example.net/x v0.1.0 => ./x1
+       example.net/x v0.2.0-pre => ./x2-pre
+       example.net/y v0.1.0 => ./y1
+       example.net/y v0.2.0-pre => ./y2-pre
+       example.net/z v0.1.0 => ./z1
+       example.net/z v0.2.0-pre => ./z2-pre
+)
+-- w1/go.mod --
+module example.net/w
+
+go 1.16
+
+require (
+       example.net/y v0.2.0-pre
+       example.net/z v0.2.0-pre
+)
+-- w1/w.go --
+package w
+-- w2-pre/go.mod --
+module example.net/w
+
+go 1.16
+-- w2-pre/README.txt --
+Package w has been removed.
+
+-- x1/go.mod --
+module example.net/x
+
+go 1.16
+
+require (
+       example.net/z v0.2.0-pre
+       example.net/w v0.2.0-pre
+)
+-- x1/x.go --
+package x
+-- x2-pre/go.mod --
+module example.net/x
+
+go 1.16
+-- x2-pre/README.txt --
+Package x has been removed.
+
+-- y1/go.mod --
+module example.net/y
+
+go 1.16
+
+require (
+       example.net/w v0.2.0-pre
+       example.net/x v0.2.0-pre
+)
+-- y1/y.go --
+package y
+
+-- y2-pre/go.mod --
+module example.net/y
+
+go 1.16
+-- y2-pre/README.txt --
+Package y has been removed.
+
+-- z1/go.mod --
+module example.net/z
+
+go 1.16
+
+require (
+       example.net/x v0.2.0-pre
+       example.net/y v0.2.0-pre
+)
+-- z1/z.go --
+package z
+
+-- z2-pre/go.mod --
+module example.net/z
+
+go 1.16
+-- z2-pre/README.txt --
+Package z has been removed.
diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_indirect.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_indirect.txt
new file mode 100644 (file)
index 0000000..1f092b2
--- /dev/null
@@ -0,0 +1,67 @@
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod go.mod.orig
+
+-- go.mod --
+module example.com/tidy
+
+go 1.16
+
+require (
+       example.net/incomplete v0.1.0
+       example.net/indirect v0.2.0 // indirect
+       example.net/toolow v0.1.0
+)
+
+replace (
+       example.net/incomplete v0.1.0 => ./incomplete
+       example.net/indirect v0.1.0 => ./indirect.1
+       example.net/indirect v0.2.0 => ./indirect.2
+       example.net/toolow v0.1.0 => ./toolow
+)
+-- tidy.go --
+package tidy
+
+import (
+       _ "example.net/incomplete"
+       _ "example.net/toolow"
+)
+
+-- incomplete/go.mod --
+module example.net/incomplete
+
+go 1.16
+
+// This module omits a needed requirement on example.net/indirect.
+-- incomplete/incomplete.go --
+package incomplete
+
+import _ "example.net/indirect/newpkg"
+
+-- toolow/go.mod --
+module example.net/toolow
+
+go 1.16
+
+require example.net/indirect v0.1.0
+-- toolow/toolow.go --
+package toolow
+
+import _ "example.net/indirect/oldpkg"
+
+-- indirect.1/go.mod --
+module example.net/indirect
+
+go 1.16
+-- indirect.1/oldpkg/oldpkg.go --
+package oldpkg
+
+
+-- indirect.2/go.mod --
+module example.net/indirect
+
+go 1.16
+-- indirect.2/oldpkg/oldpkg.go --
+package oldpkg
+-- indirect.2/newpkg/newpkg.go --
+package newpkg
diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_lazy_self.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_lazy_self.txt
new file mode 100644 (file)
index 0000000..ffcea18
--- /dev/null
@@ -0,0 +1,71 @@
+# Regression test for https://golang.org/issue/46078:
+# 'go mod tidy' should not panic if the main module initially
+# requires an older version of itself.
+
+
+# A module that explicitly requires an older version of itself should be
+# rejected as inconsistent: we enforce that every explicit requirement is the
+# selected version of its module path, but the selected version of the main
+# module is always itself — not some explicit version.
+
+! go list -m all
+stderr '^go: updates to go\.mod needed; to update it:\n\tgo mod tidy$'
+
+
+# The suggested 'go mod tidy' command should succeed (not crash).
+
+go mod tidy
+
+
+# We prune out redundant roots very early on in module loading, and at that
+# point the indirect requirement on example.net/x v0.1.0 appears to be
+# irrelevant. It should be pruned out; when the import of "example.net/x" is
+# later resolved, it should resolve at the latest version (v0.2.0), not the
+# version implied by the (former) misleading requirement on the older version of
+# the main module.
+
+cmp go.mod go.mod.tidy
+
+
+-- go.mod --
+module golang.org/issue/46078
+
+go 1.17
+
+replace (
+       example.net/x v0.1.0 => ./x
+       example.net/x v0.2.0 => ./x
+       golang.org/issue/46078 v0.1.0 => ./old
+)
+
+require golang.org/issue/46078 v0.1.0
+-- go.mod.tidy --
+module golang.org/issue/46078
+
+go 1.17
+
+replace (
+       example.net/x v0.1.0 => ./x
+       example.net/x v0.2.0 => ./x
+       golang.org/issue/46078 v0.1.0 => ./old
+)
+
+require example.net/x v0.2.0
+-- issue46078/issue.go --
+package issue46078
+
+import _ "example.net/x"
+
+-- old/go.mod --
+module golang.org/issue/46078
+
+go 1.17
+
+require example.net/x v0.1.0
+
+-- x/go.mod --
+module example.net/x
+
+go 1.17
+-- x/x.go --
+package x
diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_newroot.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_newroot.txt
new file mode 100644 (file)
index 0000000..3abd5ef
--- /dev/null
@@ -0,0 +1,82 @@
+# https://golang.org/issue/45952: 'go mod tidy' in an eager module failed due
+# to an erroneous check on root completeness.
+#
+# Per the issue report:
+# > It may have to do with:
+# >
+# > package A imports package B in go.mod, which imports package C in its own go.mod
+# > package A drops direct dependency on package B …
+#
+# We infer from that that package C is still needed by some other indirect
+# dependency, and must be at a higher version than what is required by that
+# dependency (or else no new root would be needed). An additional package D
+# in its own module satisfies that condition, reproducing the bug.
+
+go mod tidy
+cmp go.mod go.mod.tidy
+
+-- go.mod --
+module example.net/a
+
+go 1.16
+
+require (
+       example.net/b v0.1.0
+       example.net/d v0.1.0
+)
+
+replace (
+       example.net/b v0.1.0 => ./b
+       example.net/c v0.1.0 => ./c
+       example.net/c v0.2.0 => ./c
+       example.net/d v0.1.0 => ./d
+)
+-- go.mod.tidy --
+module example.net/a
+
+go 1.16
+
+require (
+       example.net/c v0.2.0 // indirect
+       example.net/d v0.1.0
+)
+
+replace (
+       example.net/b v0.1.0 => ./b
+       example.net/c v0.1.0 => ./c
+       example.net/c v0.2.0 => ./c
+       example.net/d v0.1.0 => ./d
+)
+-- a.go --
+package a
+
+import _ "example.net/d"
+
+-- b/go.mod --
+module example.net/b
+
+go 1.16
+
+require example.net/c v0.2.0
+-- b/b.go --
+package b
+
+import _ "example.net/c"
+
+-- c/go.mod --
+module example.net/c
+
+go 1.16
+-- c/c.go --
+package c
+
+-- d/go.mod --
+module example.net/d
+
+go 1.16
+
+require example.net/c v0.1.0
+-- d/d.go --
+package d
+
+import _ "example.net/c"
diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_old.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_old.txt
new file mode 100644 (file)
index 0000000..7428f0c
--- /dev/null
@@ -0,0 +1,46 @@
+# 'go mod tidy' should remove content sums for module versions that aren't
+# in the build list. It should preserve go.mod sums for module versions that
+# are in the module graph though.
+# Verifies golang.org/issue/33008.
+go mod tidy
+! grep '^rsc.io/quote v1.5.0 h1:' go.sum
+grep '^rsc.io/quote v1.5.0/go.mod h1:' go.sum
+
+-- go.mod --
+module m
+
+go 1.15
+
+require (
+       rsc.io/quote v1.5.2
+       example.com/r v0.0.0
+)
+
+replace example.com/r => ./r
+
+-- go.sum --
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.0 h1:6fJa6E+wGadANKkUMlZ0DhXFpoKlslOQDCo259XtdIE=
+rsc.io/quote v1.5.0/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64=
+rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY=
+
+-- r/go.mod --
+module example.com/r
+
+require rsc.io/quote v1.5.0
+
+-- use.go --
+package use
+
+import _ "example.com/r"
+
+-- r/use.go --
+package use
+
+import _ "rsc.io/quote"
diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_oldgo.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_oldgo.txt
new file mode 100644 (file)
index 0000000..0e88b06
--- /dev/null
@@ -0,0 +1,21 @@
+# Modules were introduced in Go 1.11, but for various reasons users may
+# decide to declare a (much!) older go version in their go.mod file.
+# Modules with very old versions should not be rejected, and should have
+# the same module-graph semantics as in Go 1.11.
+
+cp go.mod go.mod.orig
+go mod tidy
+cmp go.mod go.mod.orig
+
+-- go.mod --
+module example.com/legacy/go1
+
+go 1.0
+
+require golang.org/x/text v0.3.0
+-- main.go --
+package main
+
+import _ "golang.org/x/text/language"
+
+func main() {}
index dd9943889106568addf3a503a22c478b0dfb8bde..297f6a6a45c872da732b127e8a4cb8d376b3ba68 100644 (file)
@@ -136,3 +136,10 @@ require (
 )
 
 replace not-rsc.io/quote/v3 => rsc.io/quote/v3 v3.0.0
+-- multiple-paths/use.go --
+package quoter
+
+import (
+       _ "not-rsc.io/quote/v3"
+       _ "rsc.io/quote/v3"
+)
diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_replace_old.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_replace_old.txt
new file mode 100644 (file)
index 0000000..cfd3792
--- /dev/null
@@ -0,0 +1,34 @@
+# Regression test for https://golang.org/issue/46659.
+#
+# If a 'replace' directive specifies an older-than-selected version of a module,
+# 'go mod tidy' shouldn't try to add that version to the build list to resolve a
+# missing package: it won't be selected, and would cause the module loader to
+# loop indefinitely trying to resolve the package.
+
+cp go.mod go.mod.orig
+
+! go mod tidy
+! stderr panic
+stderr '^golang\.org/issue46659 imports\n\texample\.com/missingpkg/deprecated: package example\.com/missingpkg/deprecated provided by example\.com/missingpkg at latest version v1\.0\.0 but not at required version v1\.0\.1-beta$'
+
+go mod tidy -e
+
+cmp go.mod go.mod.orig
+
+-- go.mod --
+module golang.org/issue46659
+
+go 1.17
+
+replace example.com/missingpkg v1.0.1-alpha => example.com/missingpkg v1.0.0
+
+require example.com/usemissingpre v1.0.0
+
+require example.com/missingpkg v1.0.1-beta // indirect
+-- m.go --
+package m
+
+import (
+       _ "example.com/missingpkg/deprecated"
+       _ "example.com/usemissingpre"
+)
diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_symlink_issue35941.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_symlink_issue35941.txt
new file mode 100644 (file)
index 0000000..d4658c6
--- /dev/null
@@ -0,0 +1,36 @@
+env GO111MODULE=on
+[!symlink] skip
+
+cd m
+symlink symlink -> ../outside
+
+cp go.mod go.mod.orig
+
+# Issue 35941: suppress symlink warnings when running 'go mod tidy'.
+# 'go mod tidy' should not scan packages in symlinked subdirectories.
+go mod tidy
+! stderr 'warning: ignoring symlink'
+cmp go.mod go.mod.orig
+
+! go build ./symlink
+stderr '^symlink[\\/]symlink.go:3:8: module example.net/unresolved provides package example.net/unresolved and is replaced but not required; to add it:\n\tgo get example.net/unresolved@v0.1.0$'
+
+-- m/go.mod --
+module example.net/m
+
+go 1.16
+
+replace example.net/unresolved v0.1.0 => ../unresolved
+-- m/a.go --
+package a
+-- outside/symlink.go --
+package symlink
+
+import _ "example.net/unresolved"
+-- unresolved/go.mod --
+module example.net/unresolved
+
+go 1.16
+-- unresolved/unresolved.go --
+// Package unresolved exists, but 'go mod tidy' won't add it.
+package unresolved
diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_too_new.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_too_new.txt
new file mode 100644 (file)
index 0000000..b9c53b5
--- /dev/null
@@ -0,0 +1,57 @@
+# https://golang.org/issue/46142: 'go mod tidy' should error out if the version
+# in the go.mod file is newer than the most recent supported version.
+
+cp go.mod go.mod.orig
+
+
+# If the go.mod file specifies an unsupported Go version, 'go mod tidy' should
+# refuse to edit it: we don't know what a tidy go.mod file for that version
+# would look like.
+
+! go mod tidy
+stderr 'go mod tidy: go.mod file indicates go 2000.0, but maximum supported version is '$goversion'$'
+cmp go.mod go.mod.orig
+
+
+# The -e flag should push past the error and edit the file anyway,
+# but preserve the too-high version.
+
+cp go.mod.orig go.mod
+go mod tidy -e
+stderr 'go mod tidy: go.mod file indicates go 2000.0, but maximum supported version is '$goversion'$'
+cmp go.mod go.mod.tidy
+
+
+# Explicitly switching to a supported version should suppress the error completely.
+
+cp go.mod.orig go.mod
+go mod tidy -go=1.17
+! stderr 'maximum supported version'
+go mod edit -go=1.17 go.mod.tidy
+cmp go.mod go.mod.tidy
+
+
+-- go.mod --
+module example.net/from/the/future
+
+go 2000.0
+
+replace example.net/m v0.0.0 => ./m
+-- go.mod.tidy --
+module example.net/from/the/future
+
+go 2000.0
+
+replace example.net/m v0.0.0 => ./m
+
+require example.net/m v0.0.0
+-- x.go --
+package x
+
+import "example.net/m"
+-- m/go.mod --
+module example.net/m
+
+go 1.17
+-- m/m.go --
+package m
diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_version.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_version.txt
new file mode 100644 (file)
index 0000000..3bc97bc
--- /dev/null
@@ -0,0 +1,262 @@
+# https://golang.org/issue/45094: 'go mod tidy' now accepts a '-go' flag
+# to change the language version in use.
+#
+# The package import graph used in this test looks like:
+#
+# m --- a --- b
+#             |
+#             b_test --- c
+#                        |
+#                        c_test --- d
+#
+# The module diagram looks like:
+#
+# m --- a --- b
+# |
+# + --- c
+# |
+# + --- d
+#
+# Module b omits its dependency on c, and module c omits its dependency on d.
+#
+# In go 1.15, the tidy main module must require a (because it is direct),
+# c (because it is a missing test dependency of an imported package),
+# and d (because it is a missing transitive test dependency).
+#
+# In go 1.16, the tidy main module can omit d because it is no longer
+# included in "all".
+#
+# In go 1.17, the main module must explicitly require b
+# (because it is transitively imported by the main module).
+
+
+cp go.mod go.mod.orig
+
+
+# An invalid argument should be rejected.
+
+! go mod tidy -go=bananas
+stderr '^invalid value "bananas" for flag -go: expecting a Go version like "'$goversion'"$'
+cmp go.mod go.mod.orig
+
+! go mod tidy -go=0.9
+stderr '^invalid value "0.9" for flag -go: expecting a Go version like "'$goversion'"$'
+
+! go mod tidy -go=2000.0
+stderr '^invalid value "2000.0" for flag -go: maximum supported Go version is '$goversion'$'
+
+
+# Supported versions should change the go.mod file to be tidy according to the
+# indicated version.
+
+go mod tidy -go=1.15
+cmp go.mod go.mod.115
+
+go mod tidy
+cmp go.mod go.mod.115
+
+
+go mod tidy -go=1.16
+cmp go.mod go.mod.116
+
+go mod tidy
+cmp go.mod go.mod.116
+
+
+go mod tidy -go=1.17
+cmp go.mod go.mod.117
+
+go mod tidy
+cmp go.mod go.mod.117
+
+
+# If we downgrade back to 1.15, we should re-resolve d to v0.2.0 instead
+# of the original v0.1.0 (because the original requirement is lost).
+
+go mod tidy -go=1.15
+cmp go.mod go.mod.115-2
+
+
+# -go= (with an empty argument) maintains the existing version or adds the
+#  default version (just like omitting the flag).
+
+go mod tidy -go=''
+cmp go.mod go.mod.115-2
+
+cp go.mod.orig go.mod
+go mod tidy -go=''
+cmpenv go.mod go.mod.latest
+
+
+
+-- go.mod --
+module example.com/m
+
+require example.net/a v0.1.0
+
+require (
+       example.net/c v0.1.0 // indirect
+       example.net/d v0.1.0 // indirect
+)
+
+replace (
+       example.net/a v0.1.0 => ./a
+       example.net/a v0.2.0 => ./a
+       example.net/b v0.1.0 => ./b
+       example.net/b v0.2.0 => ./b
+       example.net/c v0.1.0 => ./c
+       example.net/c v0.2.0 => ./c
+       example.net/d v0.1.0 => ./d
+       example.net/d v0.2.0 => ./d
+)
+-- m.go --
+package m
+
+import _ "example.net/a"
+
+-- go.mod.115 --
+module example.com/m
+
+go 1.15
+
+require example.net/a v0.1.0
+
+require (
+       example.net/c v0.1.0 // indirect
+       example.net/d v0.1.0 // indirect
+)
+
+replace (
+       example.net/a v0.1.0 => ./a
+       example.net/a v0.2.0 => ./a
+       example.net/b v0.1.0 => ./b
+       example.net/b v0.2.0 => ./b
+       example.net/c v0.1.0 => ./c
+       example.net/c v0.2.0 => ./c
+       example.net/d v0.1.0 => ./d
+       example.net/d v0.2.0 => ./d
+)
+-- go.mod.115-2 --
+module example.com/m
+
+go 1.15
+
+require example.net/a v0.1.0
+
+require (
+       example.net/c v0.1.0 // indirect
+       example.net/d v0.2.0 // indirect
+)
+
+replace (
+       example.net/a v0.1.0 => ./a
+       example.net/a v0.2.0 => ./a
+       example.net/b v0.1.0 => ./b
+       example.net/b v0.2.0 => ./b
+       example.net/c v0.1.0 => ./c
+       example.net/c v0.2.0 => ./c
+       example.net/d v0.1.0 => ./d
+       example.net/d v0.2.0 => ./d
+)
+-- go.mod.116 --
+module example.com/m
+
+go 1.16
+
+require example.net/a v0.1.0
+
+require example.net/c v0.1.0 // indirect
+
+replace (
+       example.net/a v0.1.0 => ./a
+       example.net/a v0.2.0 => ./a
+       example.net/b v0.1.0 => ./b
+       example.net/b v0.2.0 => ./b
+       example.net/c v0.1.0 => ./c
+       example.net/c v0.2.0 => ./c
+       example.net/d v0.1.0 => ./d
+       example.net/d v0.2.0 => ./d
+)
+-- go.mod.117 --
+module example.com/m
+
+go 1.17
+
+require example.net/a v0.1.0
+
+require (
+       example.net/b v0.1.0 // indirect
+       example.net/c v0.1.0 // indirect
+)
+
+replace (
+       example.net/a v0.1.0 => ./a
+       example.net/a v0.2.0 => ./a
+       example.net/b v0.1.0 => ./b
+       example.net/b v0.2.0 => ./b
+       example.net/c v0.1.0 => ./c
+       example.net/c v0.2.0 => ./c
+       example.net/d v0.1.0 => ./d
+       example.net/d v0.2.0 => ./d
+)
+-- go.mod.latest --
+module example.com/m
+
+go $goversion
+
+require example.net/a v0.1.0
+
+require (
+       example.net/b v0.1.0 // indirect
+       example.net/c v0.1.0 // indirect
+)
+
+replace (
+       example.net/a v0.1.0 => ./a
+       example.net/a v0.2.0 => ./a
+       example.net/b v0.1.0 => ./b
+       example.net/b v0.2.0 => ./b
+       example.net/c v0.1.0 => ./c
+       example.net/c v0.2.0 => ./c
+       example.net/d v0.1.0 => ./d
+       example.net/d v0.2.0 => ./d
+)
+-- a/go.mod --
+module example.net/a
+
+go 1.15
+
+require example.net/b v0.1.0
+-- a/a.go --
+package a
+
+import _ "example.net/b"
+
+-- b/go.mod --
+module example.net/b
+
+go 1.15
+-- b/b.go --
+package b
+-- b/b_test.go --
+package b_test
+
+import _ "example.net/c"
+
+-- c/go.mod --
+module example.net/c
+
+go 1.15
+-- c/c.go --
+package c
+-- c/c_test.go --
+package c_test
+
+import _ "example.net/d"
+
+-- d/go.mod --
+module example.net/d
+
+go 1.15
+-- d/d.go --
+package d
diff --git a/libgo/go/cmd/go/testdata/script/mod_update_sum_readonly.txt b/libgo/go/cmd/go/testdata/script/mod_update_sum_readonly.txt
new file mode 100644 (file)
index 0000000..41f12e4
--- /dev/null
@@ -0,0 +1,34 @@
+# When finding the latest version of a module, we should not download version
+# contents. Previously, we downloaded .zip files to determine whether a real
+# .mod file was present in order to decide whether +incompatible versions
+# could be "latest".
+#
+# Verifies #47377.
+
+# rsc.io/breaker has two versions, neither of which has a .mod file.
+go list -m -versions rsc.io/breaker
+stdout '^rsc.io/breaker v1.0.0 v2.0.0\+incompatible$'
+go mod download rsc.io/breaker@v1.0.0
+! grep '^go' $GOPATH/pkg/mod/cache/download/rsc.io/breaker/@v/v1.0.0.mod
+go mod download rsc.io/breaker@v2.0.0+incompatible
+! grep '^go' $GOPATH/pkg/mod/cache/download/rsc.io/breaker/@v/v2.0.0+incompatible.mod
+
+# Delete downloaded .zip files.
+go clean -modcache
+
+# Check for updates.
+go list -m -u rsc.io/breaker
+stdout '^rsc.io/breaker v1.0.0 \[v2.0.0\+incompatible\]$'
+
+# We should not have downloaded zips.
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/breaker/@v/v1.0.0.zip
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/breaker/@v/v2.0.0+incompatible.zip
+
+-- go.mod --
+module m
+
+go 1.16
+
+require rsc.io/breaker v1.0.0
+-- go.sum --
+rsc.io/breaker v1.0.0/go.mod h1:s5yxDXvD88U1/ESC23I2FK3Lkv4YIKaB1ij/Hbm805g=
diff --git a/libgo/go/cmd/go/testdata/script/mod_vendor_embed.txt b/libgo/go/cmd/go/testdata/script/mod_vendor_embed.txt
new file mode 100644 (file)
index 0000000..be11415
--- /dev/null
@@ -0,0 +1,179 @@
+go mod vendor
+cmp vendor/example.com/a/samedir_embed.txt a/samedir_embed.txt
+cmp vendor/example.com/a/subdir/embed.txt a/subdir/embed.txt
+cmp vendor/example.com/a/subdir/test/embed.txt a/subdir/test/embed.txt
+cmp vendor/example.com/a/subdir/test/xtest/embed.txt a/subdir/test/xtest/embed.txt
+
+cd broken_no_matching_files
+! go mod vendor
+stderr 'go mod vendor: pattern foo.txt: no matching files found'
+
+cd ../broken_bad_pattern
+! go mod vendor
+stderr 'go mod vendor: pattern ../foo.txt: invalid pattern syntax'
+
+# matchPotentialSourceFile prunes out tests and unbuilt code.
+# Make sure that they are vendored if they are embedded files.
+cd ../embed_unbuilt
+go mod vendor
+cmp vendor/example.com/dep/unbuilt.go dep/unbuilt.go
+cmp vendor/example.com/dep/dep_test.go dep/dep_test.go
+! exists vendor/example.com/dep/not_embedded_unbuilt.go
+! exists vendor/example.com/dep/not_embedded_dep_test.go
+-- go.mod --
+module example.com/foo
+go 1.16
+
+require (
+       example.com/a v0.1.0
+)
+
+replace (
+       example.com/a v0.1.0 => ./a
+)
+-- foo.go --
+package main
+
+import (
+       "fmt"
+
+       "example.com/a"
+)
+
+func main() {
+    fmt.Println(a.Str())
+}
+-- a/go.mod --
+module example.com/a
+-- a/a.go --
+package a
+
+import _ "embed"
+
+//go:embed samedir_embed.txt
+var sameDir string
+
+//go:embed subdir/embed.txt
+var subDir string
+
+func Str() string {
+       return sameDir + subDir
+}
+-- a/a_test.go --
+package a
+
+import _ "embed"
+
+//go:embed subdir/test/embed.txt
+var subderTest string
+-- a/a_x_test.go --
+package a_test
+
+import _ "embed"
+
+//go:embed subdir/test/xtest/embed.txt
+var subdirXtest string
+-- a/samedir_embed.txt --
+embedded file in same directory as package
+-- a/subdir/embed.txt --
+embedded file in subdirectory of package
+-- a/subdir/test/embed.txt --
+embedded file of test in subdirectory of package
+-- a/subdir/test/xtest/embed.txt --
+embedded file of xtest in subdirectory of package
+-- broken_no_matching_files/go.mod --
+module example.com/broken
+go 1.16
+
+require (
+       example.com/brokendep v0.1.0
+)
+
+replace (
+       example.com/brokendep v0.1.0 => ./brokendep
+)
+-- broken_no_matching_files/f.go --
+package broken
+
+import _ "example.com/brokendep"
+
+func F() {}
+-- broken_no_matching_files/brokendep/go.mod --
+module example.com/brokendep
+go 1.16
+-- broken_no_matching_files/brokendep/f.go --
+package brokendep
+
+import _ "embed"
+
+//go:embed foo.txt
+var foo string
+-- broken_bad_pattern/go.mod --
+module example.com/broken
+go 1.16
+
+require (
+       example.com/brokendep v0.1.0
+)
+
+replace (
+       example.com/brokendep v0.1.0 => ./brokendep
+)
+-- broken_bad_pattern/f.go --
+package broken
+
+import _ "example.com/brokendep"
+
+func F() {}
+-- broken_bad_pattern/brokendep/go.mod --
+module example.com/brokendep
+go 1.16
+-- broken_bad_pattern/brokendep/f.go --
+package brokendep
+
+import _ "embed"
+
+//go:embed ../foo.txt
+var foo string
+-- embed_unbuilt/go.mod --
+module example.com/foo
+go 1.16
+
+require (
+       example.com/dep v0.1.0
+)
+
+replace (
+       example.com/dep v0.1.0 => ./dep
+)
+-- embed_unbuilt/foo.go --
+package a
+
+import _ "example.com/dep"
+
+func F() {}
+-- embed_unbuilt/dep/go.mod --
+module example.com/dep
+go 1.16
+-- embed_unbuilt/dep/dep.go --
+package dep
+
+import _ "embed"
+
+//go:embed unbuilt.go
+var unbuilt string
+
+//go:embed dep_test.go
+var depTest string
+-- embed_unbuilt/dep/unbuilt.go --
+// +build ignore
+
+package dep
+-- embed_unbuilt/dep/not_embedded_unbuilt.go --
+// +build ignore
+
+package dep
+-- embed_unbuilt/dep/dep_test.go --
+package dep
+-- embed_unbuilt/dep/not_embedded_dep_test.go --
+package dep
diff --git a/libgo/go/cmd/go/testdata/script/mod_vendor_gomod.txt b/libgo/go/cmd/go/testdata/script/mod_vendor_gomod.txt
new file mode 100644 (file)
index 0000000..3f6ea35
--- /dev/null
@@ -0,0 +1,38 @@
+# https://golang.org/issue/42970: As of Go 1.17, go.mod and go.sum files should
+# be stripped from vendored dependencies.
+
+go mod vendor
+cd vendor/example.net/x
+go list all
+! stdout '^example.net/m'
+stdout '^example.net/x$'
+exists ./go.sum
+
+cd ../../..
+go mod edit -go=1.17
+go mod vendor
+cd vendor/example.net/x
+go list all
+stdout '^example.net/m$'
+stdout '^example.net/x$'
+! exists ./go.sum
+
+-- go.mod --
+module example.net/m
+
+go 1.16
+
+require example.net/x v0.1.0
+
+replace example.net/x v0.1.0 => ./x
+-- m.go --
+package m
+
+import _ "example.net/x"
+-- x/go.mod --
+module example.net/x
+
+go 1.16
+-- x/go.sum --
+-- x/x.go --
+package x
diff --git a/libgo/go/cmd/go/testdata/script/mod_vendor_goversion.txt b/libgo/go/cmd/go/testdata/script/mod_vendor_goversion.txt
new file mode 100644 (file)
index 0000000..aa4cb41
--- /dev/null
@@ -0,0 +1,102 @@
+# https://golang.org/issue/36876: As of Go 1.17, vendor/modules.txt should
+# indicate the language version used by each dependency.
+
+[short] skip
+
+
+# Control case: without a vendor directory, need117 builds and bad114 doesn't.
+
+go build example.net/need117
+! go build example.net/bad114
+stderr '^bad114[/\\]bad114.go:15:2: duplicate method Y$'
+
+
+# With a vendor/modules.txt lacking language versions, the world is topsy-turvy,
+# because we have to guess a uniform version for everything.
+#
+# We always guess Go 1.16, because that was the last version for which
+# 'go mod vendor' failed to record dependency versions, and it has most of
+# the language features added since modules were introduced in Go 1.11.
+#
+# Even so, modules that declare 'go 1.17' and use 1.17 features spuriously fail
+# to build, and modules that declare an older version and use features from a
+# newer one spuriously build (instead of failing as they ought to).
+
+go mod vendor
+
+! grep 1.17 vendor/modules.txt
+! go build example.net/need117
+stderr '^vendor[/\\]example\.net[/\\]need117[/\\]need117.go:5:18: .*\n\tconversion of slices to array pointers only supported as of -lang=go1\.17'
+
+! grep 1.13 vendor/modules.txt
+go build example.net/bad114
+
+
+# Upgrading the main module to 1.17 adds version annotations.
+# Then everything is once again consistent with the non-vendored world.
+
+go mod edit -go=1.17
+go mod vendor
+
+grep '^## explicit; go 1.17$' vendor/modules.txt
+go build example.net/need117
+
+grep '^## explicit; go 1.13$' vendor/modules.txt
+! go build example.net/bad114
+stderr '^vendor[/\\]example\.net[/\\]bad114[/\\]bad114.go:15:2: duplicate method Y$'
+
+-- go.mod --
+module example.net/m
+
+go 1.16
+
+require (
+       example.net/bad114 v0.1.0
+       example.net/need117 v0.1.0
+)
+
+replace (
+       example.net/bad114 v0.1.0 => ./bad114
+       example.net/need117 v0.1.0 => ./need117
+)
+-- m.go --
+package m
+
+import _ "example.net/bad114"
+import _ "example.net/need117"
+
+-- bad114/go.mod --
+// Module bad114 requires Go 1.14 or higher, but declares Go 1.13.
+module example.net/bad114
+
+go 1.13
+-- bad114/bad114.go --
+package bad114
+
+type XY interface {
+       X()
+       Y()
+}
+
+type YZ interface {
+       Y()
+       Z()
+}
+
+type XYZ interface {
+       XY
+       YZ
+}
+
+-- need117/go.mod --
+// Module need117 requires Go 1.17 or higher.
+module example.net/need117
+
+go 1.17
+-- need117/need117.go --
+package need117
+
+func init() {
+                s := make([]byte, 4)
+                _ = (*[4]byte)(s)
+}
diff --git a/libgo/go/cmd/go/testdata/script/mod_vendor_issue46867.txt b/libgo/go/cmd/go/testdata/script/mod_vendor_issue46867.txt
new file mode 100644 (file)
index 0000000..38ae87b
--- /dev/null
@@ -0,0 +1,31 @@
+# Regression test for golang.org/issue/46867:
+# 'go mod vendor' on Windows attempted to open and copy
+# files from directories outside of the module.
+
+cd subdir
+go mod vendor
+! exists vendor/example.net/NOTICE
+exists vendor/example.net/m/NOTICE
+
+-- subdir/go.mod --
+module golang.org/issue46867
+
+go 1.17
+
+replace example.net/m v0.1.0 => ./m
+
+require example.net/m v0.1.0
+-- subdir/issue.go --
+package issue
+
+import _ "example.net/m/n"
+-- subdir/m/go.mod --
+module example.net/m
+
+go 1.17
+-- subdir/m/n/n.go --
+package n
+-- subdir/m/NOTICE --
+This notice is in module m and SHOULD be vendored.
+-- subdir/NOTICE --
+This notice is outside of module m and SHOULD NOT be vendored.
diff --git a/libgo/go/cmd/go/testdata/script/mod_vendor_trimpath.txt b/libgo/go/cmd/go/testdata/script/mod_vendor_trimpath.txt
new file mode 100644 (file)
index 0000000..5451aa7
--- /dev/null
@@ -0,0 +1,45 @@
+# Check that when -trimpath and -mod=vendor are used together,
+# paths in vendored packages are properly trimmed.
+# Verifies golang.org/issue/36566.
+
+[short] skip
+
+# Only the main module has a root directory in vendor mode.
+go mod vendor
+go list -f {{.Module.Dir}} example.com/main
+stdout $PWD
+go list -f {{.Module.Dir}} example.com/stack
+! stdout .
+
+# The program prints a file name from a vendored package.
+# Without -trimpath, the name should include the vendor directory.
+go run main.go
+stdout vendor
+
+# With -trimpath, everything before the package path should be trimmed.
+# As with -mod=mod, the version should appear as part of the module path.
+go run -mod=vendor -trimpath main.go
+stdout '^example.com/stack@v1.0.0/stack.go$'
+
+# With pristinely vendored source code, a trimmed binary built from vendored
+# code should have the same behavior as one build from the module cache.
+go run -mod=mod -trimpath main.go
+stdout '^example.com/stack@v1.0.0/stack.go$'
+
+-- go.mod --
+module example.com/main
+
+require example.com/stack v1.0.0
+
+-- main.go --
+package main
+
+import (
+  "fmt"
+
+  "example.com/stack"
+)
+
+func main() {
+  fmt.Println(stack.TopFile())
+}
diff --git a/libgo/go/cmd/go/testdata/script/mod_vendor_unused_only.txt b/libgo/go/cmd/go/testdata/script/mod_vendor_unused_only.txt
new file mode 100644 (file)
index 0000000..839c645
--- /dev/null
@@ -0,0 +1,17 @@
+# Ensure that we generate a vendor/modules.txt file even when the only
+# requirements in go.mod are unused.  Regression test for
+# golang.org/issue/36580
+
+env GO111MODULE=on
+
+go mod vendor
+cmp go1.14-modules.txt vendor/modules.txt
+
+-- go.mod --
+module example.com/m
+go 1.14
+
+require example.com v1.0.0 // indirect
+-- go1.14-modules.txt --
+# example.com v1.0.0
+## explicit
diff --git a/libgo/go/cmd/go/testdata/script/run_dirs.txt b/libgo/go/cmd/go/testdata/script/run_dirs.txt
new file mode 100644 (file)
index 0000000..538a6ac
--- /dev/null
@@ -0,0 +1,11 @@
+cd rundir
+
+! go run x.go sub/sub.go
+stderr 'named files must all be in one directory; have ./ and sub/'
+! go run sub/sub.go x.go
+stderr 'named files must all be in one directory; have sub/ and ./'
+
+-- rundir/sub/sub.go --
+package main
+-- rundir/x.go --
+package main
diff --git a/libgo/go/cmd/go/testdata/script/run_hello_pkg.txt b/libgo/go/cmd/go/testdata/script/run_hello_pkg.txt
new file mode 100644 (file)
index 0000000..ea2b4d7
--- /dev/null
@@ -0,0 +1,17 @@
+go run m/hello
+stderr 'hello, world'
+
+cd hello
+go run .
+stderr 'hello, world'
+
+-- go.mod --
+module m
+
+go 1.16
+-- hello/hello.go --
+package main
+
+func main() {
+       println("hello, world")
+}
diff --git a/libgo/go/cmd/go/testdata/script/run_internal.txt b/libgo/go/cmd/go/testdata/script/run_internal.txt
new file mode 100644 (file)
index 0000000..d021850
--- /dev/null
@@ -0,0 +1,64 @@
+env GO111MODULE=off
+
+go list -e -f '{{.Incomplete}}' m/runbad1.go
+stdout true
+! go run m/runbad1.go
+stderr 'use of internal package m/x/internal not allowed'
+
+go list -e -f '{{.Incomplete}}' m/runbad2.go
+stdout true
+! go run m/runbad2.go
+stderr 'use of internal package m/x/internal/y not allowed'
+
+go list -e -f '{{.Incomplete}}' m/runok.go
+stdout false
+go run m/runok.go
+
+cd m
+env GO111MODULE=on
+
+go list -e -f '{{.Incomplete}}' runbad1.go
+stdout true
+! go run runbad1.go
+stderr 'use of internal package m/x/internal not allowed'
+
+go list -e -f '{{.Incomplete}}' runbad2.go
+stdout true
+! go run runbad2.go
+stderr 'use of internal package m/x/internal/y not allowed'
+
+go list -e -f '{{.Incomplete}}' runok.go
+stdout false
+go run runok.go
+
+
+-- m/go.mod --
+module m
+
+-- m/x/internal/internal.go --
+package internal
+
+-- m/x/internal/y/y.go --
+package y
+
+-- m/internal/internal.go --
+package internal
+
+-- m/internal/z/z.go --
+package z
+
+-- m/runbad1.go --
+package main
+import _ "m/x/internal"
+func main() {}
+
+-- m/runbad2.go --
+package main
+import _ "m/x/internal/y"
+func main() {}
+
+-- m/runok.go --
+package main
+import _ "m/internal"
+import _ "m/internal/z"
+func main() {}
diff --git a/libgo/go/cmd/go/testdata/script/run_issue11709.txt b/libgo/go/cmd/go/testdata/script/run_issue11709.txt
new file mode 100644 (file)
index 0000000..c8ba998
--- /dev/null
@@ -0,0 +1,15 @@
+# 'go run' should not pass extraneous environment variables to the subprocess.
+go run run.go
+! stdout .
+! stderr .
+
+-- run.go --
+package main
+
+import "os"
+
+func main() {
+       if os.Getenv("TERM") != "" {
+               os.Exit(1)
+       }
+}
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/run_vendor.txt b/libgo/go/cmd/go/testdata/script/run_vendor.txt
new file mode 100644 (file)
index 0000000..46cac06
--- /dev/null
@@ -0,0 +1,34 @@
+# Run
+env GO111MODULE=off
+cd vend/hello
+go run hello.go
+stdout 'hello, world'
+
+-- vend/hello/hello.go --
+package main
+
+import (
+       "fmt"
+       "strings" // really ../vendor/strings
+)
+
+func main() {
+       fmt.Printf("%s\n", strings.Msg)
+}
+-- vend/hello/hello_test.go --
+package main
+
+import (
+       "strings" // really ../vendor/strings
+       "testing"
+)
+
+func TestMsgInternal(t *testing.T) {
+       if strings.Msg != "hello, world" {
+               t.Fatalf("unexpected msg: %v", strings.Msg)
+       }
+}
+-- vend/vendor/strings/msg.go --
+package strings
+
+var Msg = "hello, world"
diff --git a/libgo/go/cmd/go/testdata/script/test_benchmark_chatty_fail.txt b/libgo/go/cmd/go/testdata/script/test_benchmark_chatty_fail.txt
new file mode 100644 (file)
index 0000000..6031ead
--- /dev/null
@@ -0,0 +1,32 @@
+# Run chatty tests. Assert on CONT lines.
+! go test chatty_test.go -v -bench . chatty_bench
+
+# Sanity check that output occurs.
+stdout -count=2 'this is sub-0'
+stdout -count=2 'this is sub-1'
+stdout -count=2 'this is sub-2'
+stdout -count=1 'error from sub-0'
+stdout -count=1 'error from sub-1'
+stdout -count=1 'error from sub-2'
+
+# Benchmarks should not print CONT.
+! stdout CONT
+
+-- chatty_test.go --
+package chatty_bench
+
+import (
+       "testing"
+       "fmt"
+)
+
+func BenchmarkChatty(b *testing.B) {
+    for i := 0; i < 3; i++ {
+        b.Run(fmt.Sprintf("sub-%d", i), func(b *testing.B) {
+            for j := 0; j < 2; j++ {
+                b.Logf("this is sub-%d", i)
+            }
+            b.Errorf("error from sub-%d", i)
+        })
+    }
+}
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/test_benchmark_chatty_success.txt b/libgo/go/cmd/go/testdata/script/test_benchmark_chatty_success.txt
new file mode 100644 (file)
index 0000000..a1c0d65
--- /dev/null
@@ -0,0 +1,29 @@
+# Run chatty tests. Assert on CONT lines.
+go test chatty_test.go -v -bench . chatty_bench
+
+# Sanity check that output happens. We don't provide -count because the amount
+# of output is variable.
+stdout 'this is sub-0'
+stdout 'this is sub-1'
+stdout 'this is sub-2'
+
+# Benchmarks should not print CONT.
+! stdout CONT
+
+-- chatty_test.go --
+package chatty_bench
+
+import (
+       "testing"
+       "fmt"
+)
+
+func BenchmarkChatty(b *testing.B) {
+    for i := 0; i < 3; i++ {
+        b.Run(fmt.Sprintf("sub-%d", i), func(b *testing.B) {
+            for j := 0; j < 2; j++ {
+                b.Logf("this is sub-%d", i)
+            }
+        })
+    }
+}
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/test_benchmark_fatal.txt b/libgo/go/cmd/go/testdata/script/test_benchmark_fatal.txt
new file mode 100644 (file)
index 0000000..e281379
--- /dev/null
@@ -0,0 +1,19 @@
+# Test that calling t.Fatal in a benchmark causes a non-zero exit status.
+
+! go test -run '^$' -bench . benchfatal
+! stdout ^ok
+! stderr ^ok
+stdout FAIL.*benchfatal
+
+-- go.mod --
+module benchfatal
+
+go 1.16
+-- x_test.go --
+package benchfatal
+
+import "testing"
+
+func BenchmarkThatCallsFatal(b *testing.B) {
+       b.Fatal("called by benchmark")
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_benchmark_labels.txt b/libgo/go/cmd/go/testdata/script/test_benchmark_labels.txt
new file mode 100644 (file)
index 0000000..6b424c1
--- /dev/null
@@ -0,0 +1,23 @@
+# Tests that go test -bench prints out goos, goarch, and pkg.
+
+# Check for goos, goarch, and pkg.
+go test -run ^$ -bench . bench
+stdout '^goos: '$GOOS
+stdout '^goarch: '$GOARCH
+stdout '^pkg: bench'
+
+# Check go test does not print pkg multiple times
+! stdout 'pkg:.*pkg: '
+! stderr 'pkg:.*pkg:'
+
+-- go.mod --
+module bench
+
+go 1.16
+-- x_test.go --
+package bench
+
+import "testing"
+
+func Benchmark(b *testing.B) {
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_benchmark_timeout.txt b/libgo/go/cmd/go/testdata/script/test_benchmark_timeout.txt
new file mode 100644 (file)
index 0000000..4bae7e7
--- /dev/null
@@ -0,0 +1,18 @@
+# Tests issue #18845
+[short] skip
+
+go test -bench . -timeout=750ms timeoutbench_test.go
+stdout ok
+stdout PASS
+
+-- timeoutbench_test.go --
+package timeoutbench_test
+
+import (
+       "testing"
+       "time"
+)
+
+func BenchmarkSleep1s(b *testing.B) {
+       time.Sleep(1 * time.Second)
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_build_failure.txt b/libgo/go/cmd/go/testdata/script/test_build_failure.txt
new file mode 100644 (file)
index 0000000..8d13634
--- /dev/null
@@ -0,0 +1,31 @@
+[short] skip
+
+! go test -x coverbad
+! stderr '[\\/]coverbad\.test( |$)' # 'go test' should not claim to have run the test.
+stderr 'undefined: g'
+stderr 'undefined: j'
+
+-- go.mod --
+module coverbad
+
+go 1.16
+-- p.go --
+package p
+
+func f() {
+       g()
+}
+-- p1.go --
+package p
+
+import "C"
+
+func h() {
+       j()
+}
+-- p_test.go --
+package p
+
+import "testing"
+
+func Test(t *testing.T) {}
index 50486e19090dd304c0fe22a9241e5c8ca1b8a5ff..d694a30994710e70145469998b3fd086b5f2964f 100644 (file)
@@ -99,6 +99,15 @@ rm $WORK/external.txt
 go test testcache -run=ExternalFile
 stdout '\(cached\)'
 
+# The -benchtime flag without -bench should not affect caching.
+go test testcache -run=Benchtime -benchtime=1x
+go test testcache -run=Benchtime -benchtime=1x
+stdout '\(cached\)'
+
+go test testcache -run=Benchtime -bench=Benchtime -benchtime=1x
+go test testcache -run=Benchtime -bench=Benchtime -benchtime=1x
+! stdout '\(cached\)'
+
 # Executables within GOROOT and GOPATH should affect caching,
 # even if the test does not stat them explicitly.
 
@@ -228,6 +237,10 @@ func TestExternalFile(t *testing.T) {
 func TestOSArgs(t *testing.T) {
        t.Log(os.Args)
 }
+
+func TestBenchtime(t *testing.T) {
+}
+
 -- mkold.go --
 package main
 
diff --git a/libgo/go/cmd/go/testdata/script/test_chatty_fail.txt b/libgo/go/cmd/go/testdata/script/test_chatty_fail.txt
new file mode 100644 (file)
index 0000000..a5ef559
--- /dev/null
@@ -0,0 +1,32 @@
+# Run chatty tests. Assert on CONT lines.
+! go test chatty_test.go -v
+
+# Sanity check that output occurs.
+stdout -count=2 'this is sub-0'
+stdout -count=2 'this is sub-1'
+stdout -count=2 'this is sub-2'
+stdout -count=1 'error from sub-0'
+stdout -count=1 'error from sub-1'
+stdout -count=1 'error from sub-2'
+
+# Non-parallel tests should not print CONT.
+! stdout CONT
+
+-- chatty_test.go --
+package chatty_test
+
+import (
+       "testing"
+       "fmt"
+)
+
+func TestChatty(t *testing.T) {
+    for i := 0; i < 3; i++ {
+        t.Run(fmt.Sprintf("sub-%d", i), func(t *testing.T) {
+            for j := 0; j < 2; j++ {
+                t.Logf("this is sub-%d", i)
+            }
+            t.Errorf("error from sub-%d", i)
+        })
+    }
+}
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/test_chatty_parallel_fail.txt b/libgo/go/cmd/go/testdata/script/test_chatty_parallel_fail.txt
new file mode 100644 (file)
index 0000000..f8faa93
--- /dev/null
@@ -0,0 +1,58 @@
+# Run parallel chatty tests. Assert on CONT lines. This test makes sure that
+# multiple parallel outputs have the appropriate CONT lines between them.
+! go test -parallel 3 chatty_parallel_test.go -v
+
+stdout -count=1 '^=== CONT  TestChattyParallel/sub-0\n    chatty_parallel_test.go:38: error from sub-0$'
+stdout -count=1 '^=== CONT  TestChattyParallel/sub-1\n    chatty_parallel_test.go:38: error from sub-1$'
+stdout -count=1 '^=== CONT  TestChattyParallel/sub-2\n    chatty_parallel_test.go:38: error from sub-2$'
+
+# Run parallel chatty tests with -json. Assert on CONT lines as above - make
+# sure there are CONT lines before each output line.
+! go test -json -parallel 3 chatty_parallel_test.go -v
+stdout -count=1 '{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-0","Output":"=== CONT  TestChattyParallel/sub-0\\n"}\n{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-0","Output":"    chatty_parallel_test.go:38: error from sub-0\\n"}'
+stdout -count=1 '{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-1","Output":"=== CONT  TestChattyParallel/sub-1\\n"}\n{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-1","Output":"    chatty_parallel_test.go:38: error from sub-1\\n"}'
+stdout -count=1 '{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-2","Output":"=== CONT  TestChattyParallel/sub-2\\n"}\n{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-2","Output":"    chatty_parallel_test.go:38: error from sub-2\\n"}'
+
+-- chatty_parallel_test.go --
+package chatty_parallel_test
+
+import (
+       "testing"
+       "fmt"
+       "flag"
+)
+
+// This test ensures the order of CONT lines in parallel chatty tests.
+func TestChattyParallel(t *testing.T) {
+       t.Parallel()
+
+       // The number of concurrent tests running. This is closely tied to the
+       // -parallel test flag, so we grab it from the flag rather than setting it
+       // to some constant.
+       parallel := flag.Lookup("test.parallel").Value.(flag.Getter).Get().(int)
+
+       // ready is a synchronization mechanism that causes subtests to execute
+       // round robin.
+       ready := make([]chan bool, parallel)
+       for i := range ready {
+               ready[i] = make(chan bool, 1)
+       }
+       ready[0] <- true
+
+       for i := range ready {
+               i := i
+               t.Run(fmt.Sprintf("sub-%d", i), func(t *testing.T) {
+                       t.Parallel()
+
+                       // Some basic log output to precede the failures.
+                       <-ready[i]
+                       t.Logf("this is sub-%d", i)
+                       ready[(i+1)%len(ready)] <- true
+
+                       // The actual failure messages we care about.
+                       <-ready[i]
+                       t.Errorf("error from sub-%d", i)
+                       ready[(i+1)%len(ready)] <- true
+               })
+       }
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_chatty_parallel_success.txt b/libgo/go/cmd/go/testdata/script/test_chatty_parallel_success.txt
new file mode 100644 (file)
index 0000000..63034fa
--- /dev/null
@@ -0,0 +1,52 @@
+# Run parallel chatty tests. Assert on CONT lines. This test makes sure that
+# multiple parallel outputs have the appropriate CONT lines between them.
+go test -parallel 3 chatty_parallel_test.go -v
+stdout -count=2 '^=== CONT  TestChattyParallel/sub-0\n    chatty_parallel_test.go:32: this is sub-0$'
+stdout -count=2 '^=== CONT  TestChattyParallel/sub-1\n    chatty_parallel_test.go:32: this is sub-1$'
+stdout -count=2 '^=== CONT  TestChattyParallel/sub-2\n    chatty_parallel_test.go:32: this is sub-2$'
+
+# Run parallel chatty tests with -json. Assert on CONT lines as above - make
+# sure there are CONT lines before each output line.
+go test -json -parallel 3 chatty_parallel_test.go -v
+stdout -count=2 '{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-0","Output":"=== CONT  TestChattyParallel/sub-0\\n"}\n{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-0","Output":"    chatty_parallel_test.go:32: this is sub-0\\n"}'
+stdout -count=2 '{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-1","Output":"=== CONT  TestChattyParallel/sub-1\\n"}\n{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-1","Output":"    chatty_parallel_test.go:32: this is sub-1\\n"}'
+stdout -count=2 '{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-2","Output":"=== CONT  TestChattyParallel/sub-2\\n"}\n{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-2","Output":"    chatty_parallel_test.go:32: this is sub-2\\n"}'
+
+-- chatty_parallel_test.go --
+package chatty_parallel_test
+
+import (
+       "testing"
+       "fmt"
+       "flag"
+)
+
+// This test ensures the order of CONT lines in parallel chatty tests.
+func TestChattyParallel(t *testing.T) {
+       t.Parallel()
+
+       // The number of concurrent tests running. This is closely tied to the
+       // -parallel test flag, so we grab it from the flag rather than setting it
+       // to some constant.
+       parallel := flag.Lookup("test.parallel").Value.(flag.Getter).Get().(int)
+
+       // ready is a synchronization mechanism that causes subtests to execute
+       // round robin.
+       ready := make([]chan bool, parallel)
+       for i := range ready {
+               ready[i] = make(chan bool, 1)
+       }
+       ready[0] <- true
+
+       for i := range ready {
+               i := i
+               t.Run(fmt.Sprintf("sub-%d", i), func(t *testing.T) {
+                       t.Parallel()
+                       for j := 0; j < 2; j++ {
+                               <-ready[i]
+                               t.Logf("this is sub-%d", i)
+                               ready[(i+1)%len(ready)] <- true
+                       }
+               })
+       }
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_chatty_parallel_success_sleepy.txt b/libgo/go/cmd/go/testdata/script/test_chatty_parallel_success_sleepy.txt
new file mode 100644 (file)
index 0000000..e651a7e
--- /dev/null
@@ -0,0 +1,39 @@
+# Run parallel chatty tests. Assert on CONT lines. This test makes sure that
+# multiple parallel outputs have the appropriate CONT lines between them.
+go test -parallel 3 chatty_parallel_test.go -v
+
+stdout '--- PASS: TestFast \([0-9.]{4}s\)\n=== CONT  TestSlow\n    chatty_parallel_test.go:31: this is the second TestSlow log\n--- PASS: TestSlow \([0-9.]{4}s\)'
+
+-- chatty_parallel_test.go --
+package chatty_parallel_test
+
+import (
+       "testing"
+       "time"
+)
+
+var (
+       run           = make(chan struct{})
+       afterFirstLog = make(chan struct{})
+       afterPass     = make(chan struct{})
+)
+
+func TestFast(t *testing.T) {
+       t.Parallel()
+
+       <-afterFirstLog
+       t.Cleanup(func() {
+               close(afterPass)
+       })
+}
+
+func TestSlow(t *testing.T) {
+       t.Parallel()
+
+       t.Logf("this is the first TestSlow log")
+       close(afterFirstLog)
+
+       <-afterPass
+       time.Sleep(100 * time.Millisecond)
+       t.Logf("this is the second TestSlow log")
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_chatty_success.txt b/libgo/go/cmd/go/testdata/script/test_chatty_success.txt
new file mode 100644 (file)
index 0000000..8bfa569
--- /dev/null
@@ -0,0 +1,27 @@
+# Run chatty tests. Assert on CONT lines.
+go test chatty_test.go -v
+
+# Non-parallel tests should not print CONT.
+! stdout CONT
+
+# The assertion is condensed into one line so that it precisely matches output,
+# rather than skipping lines and allow rogue CONT lines.
+stdout '=== RUN   TestChatty\n=== RUN   TestChatty/sub-0\n    chatty_test.go:12: this is sub-0\n    chatty_test.go:12: this is sub-0\n=== RUN   TestChatty/sub-1\n    chatty_test.go:12: this is sub-1\n    chatty_test.go:12: this is sub-1\n=== RUN   TestChatty/sub-2\n    chatty_test.go:12: this is sub-2\n    chatty_test.go:12: this is sub-2\n--- PASS: TestChatty'
+
+-- chatty_test.go --
+package chatty_test
+
+import (
+       "testing"
+       "fmt"
+)
+
+func TestChatty(t *testing.T) {
+    for i := 0; i < 3; i++ {
+        t.Run(fmt.Sprintf("sub-%d", i), func(t *testing.T) {
+            for j := 0; j < 2; j++ {
+                t.Logf("this is sub-%d", i)
+            }
+        })
+    }
+}
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/test_cleanup_failnow.txt b/libgo/go/cmd/go/testdata/script/test_cleanup_failnow.txt
new file mode 100644 (file)
index 0000000..0737a93
--- /dev/null
@@ -0,0 +1,47 @@
+# For issue 41355
+[short] skip
+
+# This test could fail if the testing package does not wait until
+# a panicking test does the panic. Turn off multithreading, GC, and
+# async preemption to increase the probability of such a failure.
+env GOMAXPROCS=1
+env GOGC=off
+env GODEBUG=asyncpreempt=off
+
+# If the test exits with 'no tests to run', it means the testing package
+# implementation is incorrect and does not wait until a test panic.
+# If the test exits with '(?s)panic: die.*panic: die', it means
+# the testing package did an extra panic for a panicking test.
+
+! go test -v cleanup_failnow/panic_nocleanup_test.go
+! stdout 'no tests to run'
+stdout '(?s)panic: die \[recovered\].*panic: die'
+! stdout '(?s)panic: die \[recovered\].*panic: die.*panic: die'
+
+! go test -v cleanup_failnow/panic_withcleanup_test.go
+! stdout 'no tests to run'
+stdout '(?s)panic: die \[recovered\].*panic: die'
+! stdout '(?s)panic: die \[recovered\].*panic: die.*panic: die'
+
+-- cleanup_failnow/panic_nocleanup_test.go --
+package panic_nocleanup_test
+import "testing"
+func TestX(t *testing.T) {
+       t.Run("x", func(t *testing.T) {
+               panic("die")
+       })
+}
+
+-- cleanup_failnow/panic_withcleanup_test.go --
+package panic_withcleanup_test
+import "testing"
+func TestCleanupWithFailNow(t *testing.T) {
+       t.Cleanup(func() {
+               t.FailNow()
+       })
+       t.Run("x", func(t *testing.T) {
+               t.Run("y", func(t *testing.T) {
+                       panic("die")
+               })
+       })
+}
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/test_deadline.txt b/libgo/go/cmd/go/testdata/script/test_deadline.txt
new file mode 100644 (file)
index 0000000..06ae16f
--- /dev/null
@@ -0,0 +1,54 @@
+[short] skip
+
+go test -timeout=0 -run=TestNoDeadline
+go test -timeout=1m -run=TestDeadlineWithinMinute
+go test -timeout=1m -run=TestSubtestDeadlineWithinMinute
+
+-- go.mod --
+module m
+
+go 1.16
+-- deadline_test.go --
+package testing_test
+
+import (
+       "testing"
+       "time"
+)
+
+func TestNoDeadline(t *testing.T) {
+       d, ok := t.Deadline()
+       if ok || !d.IsZero() {
+               t.Fatalf("t.Deadline() = %v, %v; want 0, false", d, ok)
+       }
+}
+
+func TestDeadlineWithinMinute(t *testing.T) {
+       now := time.Now()
+       d, ok := t.Deadline()
+       if !ok || d.IsZero() {
+               t.Fatalf("t.Deadline() = %v, %v; want nonzero deadline", d, ok)
+       }
+       if !d.After(now) {
+               t.Fatalf("t.Deadline() = %v; want after start of test (%v)", d, now)
+       }
+       if d.Sub(now) > time.Minute {
+               t.Fatalf("t.Deadline() = %v; want within one minute of start of test (%v)", d, now)
+       }
+}
+
+func TestSubtestDeadlineWithinMinute(t *testing.T) {
+       t.Run("sub", func(t *testing.T) {
+               now := time.Now()
+               d, ok := t.Deadline()
+               if !ok || d.IsZero() {
+                       t.Fatalf("t.Deadline() = %v, %v; want nonzero deadline", d, ok)
+               }
+               if !d.After(now) {
+                       t.Fatalf("t.Deadline() = %v; want after start of test (%v)", d, now)
+               }
+               if d.Sub(now) > time.Minute {
+                       t.Fatalf("t.Deadline() = %v; want within one minute of start of test (%v)", d, now)
+               }
+       })
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_empty.txt b/libgo/go/cmd/go/testdata/script/test_empty.txt
new file mode 100644 (file)
index 0000000..5ebbecd
--- /dev/null
@@ -0,0 +1,53 @@
+[!race] skip
+
+cd $GOPATH/src/empty/pkg
+go test -cover -coverpkg=. -race
+
+[short] stop # Only run first case in short mode
+
+cd $GOPATH/src/empty/test
+go test -cover -coverpkg=. -race
+
+cd $GOPATH/src/empty/xtest
+go test -cover -coverpkg=. -race
+
+cd $GOPATH/src/empty/pkgtest
+go test -cover -coverpkg=. -race
+
+cd $GOPATH/src/empty/pkgxtest
+go test -cover -coverpkg=. -race
+
+cd $GOPATH/src/empty/pkgtestxtest
+go test -cover -coverpkg=. -race
+
+cd $GOPATH/src/empty/testxtest
+go test -cover -coverpkg=. -race
+
+-- empty/go.mod --
+module empty
+
+go 1.16
+-- empty/pkg/pkg.go --
+package p
+-- empty/pkgtest/pkg.go --
+package p
+-- empty/pkgtest/test_test.go --
+package p
+-- empty/pkgtestxtest/pkg.go --
+package p
+-- empty/pkgtestxtest/test_test.go --
+package p
+-- empty/pkgtestxtest/xtest_test.go --
+package p_test
+-- empty/pkgxtest/pkg.go --
+package p
+-- empty/pkgxtest/xtest_test.go --
+package p_test
+-- empty/test/test_test.go --
+package p
+-- empty/testxtest/test_test.go --
+package p
+-- empty/testxtest/xtest_test.go --
+package p_test
+-- empty/xtest/xtest_test.go --
+package p_test
diff --git a/libgo/go/cmd/go/testdata/script/test_env_term.txt b/libgo/go/cmd/go/testdata/script/test_env_term.txt
new file mode 100644 (file)
index 0000000..8a5f79a
--- /dev/null
@@ -0,0 +1,15 @@
+# Tests golang.org/issue/12096
+
+env TERM=''
+go test test_test.go
+! stdout '^ok.*\[no tests to run\]'
+stdout '^ok'
+
+-- test_test.go --
+package main
+import ("os"; "testing")
+func TestEnv(t *testing.T) {
+       if os.Getenv("TERM") != "" {
+               t.Fatal("TERM is set")
+       }
+}
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/test_example_goexit.txt b/libgo/go/cmd/go/testdata/script/test_example_goexit.txt
new file mode 100644 (file)
index 0000000..984f434
--- /dev/null
@@ -0,0 +1,29 @@
+# For issue golang.org/issue/41084
+[short] skip
+
+! go test -v examplegoexit
+stdout '(?s)--- PASS.*--- FAIL.*'
+stdout 'panic: test executed panic\(nil\) or runtime\.Goexit'
+
+-- go.mod --
+module examplegoexit
+
+go 1.16
+-- example_test.go --
+package main
+
+import (
+       "fmt"
+       "runtime"
+)
+
+func ExamplePass() {
+       fmt.Println("pass")
+       // Output:
+       // pass
+}
+
+func ExampleGoexit() {
+       runtime.Goexit()
+       // Output:
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_exit.txt b/libgo/go/cmd/go/testdata/script/test_exit.txt
new file mode 100644 (file)
index 0000000..3703ba5
--- /dev/null
@@ -0,0 +1,131 @@
+# Builds and runs test binaries, so skip in short mode.
+[short] skip
+
+env GO111MODULE=on
+
+# If a test invoked by 'go test' exits with a zero status code,
+# it will panic.
+! go test ./zero
+! stdout ^ok
+! stdout 'exit status'
+stdout 'panic'
+stdout ^FAIL
+
+# If a test exits with a non-zero status code, 'go test' fails normally.
+! go test ./one
+! stdout ^ok
+stdout 'exit status'
+! stdout 'panic'
+stdout ^FAIL
+
+# Ensure that other flags still do the right thing.
+go test -list=. ./zero
+stdout ExitZero
+
+! go test -bench=. ./zero
+stdout 'panic'
+
+# 'go test' with no args streams output without buffering. Ensure that it still
+# catches a zero exit with missing output.
+cd zero
+! go test
+stdout 'panic'
+cd ../normal
+go test
+stdout ^ok
+cd ..
+
+# If a TestMain exits with a zero status code, 'go test' shouldn't
+# complain about that. It's a common way to skip testing a package
+# entirely.
+go test ./main_zero
+! stdout 'skipping all tests'
+stdout ^ok
+
+# With -v, we'll see the warning from TestMain.
+go test -v ./main_zero
+stdout 'skipping all tests'
+stdout ^ok
+
+# Listing all tests won't actually give a result if TestMain exits. That's okay,
+# because this is how TestMain works. If we decide to support -list even when
+# TestMain is used to skip entire packages, we can change this test case.
+go test -list=. ./main_zero
+stdout 'skipping all tests'
+! stdout TestNotListed
+
+# Running the test directly still fails, if we pass the flag.
+go test -c -o ./zero.exe ./zero
+! exec ./zero.exe -test.paniconexit0
+
+# Using -json doesn't affect the exit status.
+! go test -json ./zero
+! stdout '"Output":"ok'
+! stdout 'exit status'
+stdout 'panic'
+stdout '"Output":"FAIL'
+
+# Running the test via test2json also fails.
+! go tool test2json ./zero.exe -test.v -test.paniconexit0
+! stdout '"Output":"ok'
+! stdout 'exit status'
+stdout 'panic'
+
+-- go.mod --
+module m
+
+-- ./normal/normal.go --
+package normal
+-- ./normal/normal_test.go --
+package normal
+
+import "testing"
+
+func TestExitZero(t *testing.T) {
+}
+
+-- ./zero/zero.go --
+package zero
+-- ./zero/zero_test.go --
+package zero
+
+import (
+       "os"
+       "testing"
+)
+
+func TestExitZero(t *testing.T) {
+       os.Exit(0)
+}
+
+-- ./one/one.go --
+package one
+-- ./one/one_test.go --
+package one
+
+import (
+       "os"
+       "testing"
+)
+
+func TestExitOne(t *testing.T) {
+       os.Exit(1)
+}
+
+-- ./main_zero/zero.go --
+package zero
+-- ./main_zero/zero_test.go --
+package zero
+
+import (
+       "fmt"
+       "os"
+       "testing"
+)
+
+func TestMain(m *testing.M) {
+       fmt.Println("skipping all tests")
+       os.Exit(0)
+}
+
+func TestNotListed(t *testing.T) {}
diff --git a/libgo/go/cmd/go/testdata/script/test_fail_fast.txt b/libgo/go/cmd/go/testdata/script/test_fail_fast.txt
new file mode 100644 (file)
index 0000000..132ea70
--- /dev/null
@@ -0,0 +1,113 @@
+[short] skip
+
+# test fail fast
+! go test ./failfast_test.go -run='TestFailingA' -failfast=true
+stdout -count=1 'FAIL - '
+! go test ./failfast_test.go -run='TestFailing[AB]' -failfast=true
+stdout -count=1 'FAIL - '
+! go test ./failfast_test.go -run='TestFailing[AB]' -failfast=false
+stdout -count=2 'FAIL - '
+
+# mix with non-failing tests
+! go test ./failfast_test.go -run='TestA|TestFailing[AB]' -failfast=true
+stdout -count=1 'FAIL - '
+! go test ./failfast_test.go -run='TestA|TestFailing[AB]' -failfast=false
+stdout -count=2 'FAIL - '
+
+# mix with parallel tests
+! go test ./failfast_test.go -run='TestFailingB|TestParallelFailingA' -failfast=true
+stdout -count=2 'FAIL - '
+! go test ./failfast_test.go -run='TestFailingB|TestParallelFailingA' -failfast=false
+stdout -count=2 'FAIL - '
+! go test ./failfast_test.go -run='TestFailingB|TestParallelFailing[AB]' -failfast=true
+stdout -count=3 'FAIL - '
+! go test ./failfast_test.go -run='TestFailingB|TestParallelFailing[AB]' -failfast=false
+stdout -count=3 'FAIL - '
+
+# mix with parallel sub-tests
+! go test ./failfast_test.go -run='TestFailingB|TestParallelFailing[AB]|TestParallelFailingSubtestsA' -failfast=true
+stdout -count=3 'FAIL - '
+! go test ./failfast_test.go -run='TestFailingB|TestParallelFailing[AB]|TestParallelFailingSubtestsA' -failfast=false
+stdout -count=5 'FAIL - '
+! go test ./failfast_test.go -run='TestParallelFailingSubtestsA' -failfast=true
+stdout -count=1 'FAIL - '
+
+# only parallels
+! go test ./failfast_test.go -run='TestParallelFailing[AB]' -failfast=false
+stdout -count=2 'FAIL - '
+
+# non-parallel subtests
+! go test ./failfast_test.go -run='TestFailingSubtestsA' -failfast=true
+stdout -count=1 'FAIL - '
+! go test ./failfast_test.go -run='TestFailingSubtestsA' -failfast=false
+stdout -count=2 'FAIL - '
+
+# fatal test
+! go test ./failfast_test.go -run='TestFatal[CD]' -failfast=true
+stdout -count=1 'FAIL - '
+! go test ./failfast_test.go -run='TestFatal[CD]' -failfast=false
+stdout -count=2 'FAIL - '
+
+-- failfast_test.go --
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package failfast
+
+import "testing"
+
+func TestA(t *testing.T) {
+       // Edge-case testing, mixing unparallel tests too
+       t.Logf("LOG: %s", t.Name())
+}
+
+func TestFailingA(t *testing.T) {
+       t.Errorf("FAIL - %s", t.Name())
+}
+
+func TestB(t *testing.T) {
+       // Edge-case testing, mixing unparallel tests too
+       t.Logf("LOG: %s", t.Name())
+}
+
+func TestParallelFailingA(t *testing.T) {
+       t.Parallel()
+       t.Errorf("FAIL - %s", t.Name())
+}
+
+func TestParallelFailingB(t *testing.T) {
+       t.Parallel()
+       t.Errorf("FAIL - %s", t.Name())
+}
+
+func TestParallelFailingSubtestsA(t *testing.T) {
+       t.Parallel()
+       t.Run("TestFailingSubtestsA1", func(t *testing.T) {
+               t.Errorf("FAIL - %s", t.Name())
+       })
+       t.Run("TestFailingSubtestsA2", func(t *testing.T) {
+               t.Errorf("FAIL - %s", t.Name())
+       })
+}
+
+func TestFailingSubtestsA(t *testing.T) {
+       t.Run("TestFailingSubtestsA1", func(t *testing.T) {
+               t.Errorf("FAIL - %s", t.Name())
+       })
+       t.Run("TestFailingSubtestsA2", func(t *testing.T) {
+               t.Errorf("FAIL - %s", t.Name())
+       })
+}
+
+func TestFailingB(t *testing.T) {
+       t.Errorf("FAIL - %s", t.Name())
+}
+
+func TestFatalC(t *testing.T) {
+       t.Fatalf("FAIL - %s", t.Name())
+}
+
+func TestFatalD(t *testing.T) {
+       t.Fatalf("FAIL - %s", t.Name())
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_finished_subtest_goroutines.txt b/libgo/go/cmd/go/testdata/script/test_finished_subtest_goroutines.txt
new file mode 100644 (file)
index 0000000..8db821e
--- /dev/null
@@ -0,0 +1,52 @@
+# Regression test for https://golang.org/issue/45127:
+# Goroutines for completed parallel subtests should exit immediately,
+# not block until earlier subtests have finished.
+
+[short] skip
+
+! go test .
+stdout 'panic: slow failure'
+! stdout '\[chan send'
+
+-- go.mod --
+module golang.org/issue45127
+
+go 1.16
+-- issue45127_test.go --
+package main
+
+import (
+       "fmt"
+       "runtime"
+       "runtime/debug"
+       "sync"
+       "testing"
+)
+
+func TestTestingGoroutineLeak(t *testing.T) {
+       debug.SetTraceback("all")
+
+       var wg sync.WaitGroup
+       const nFast = 10
+
+       t.Run("slow", func(t *testing.T) {
+               t.Parallel()
+               wg.Wait()
+               for i := 0; i < nFast; i++ {
+                       // If the subtest goroutines are going to park on the channel
+                       // send, allow them to park now. If they're not going to park,
+                       // make sure they have had a chance to run to completion so
+                       // that they aren't spuriously parked when we panic.
+                       runtime.Gosched()
+               }
+               panic("slow failure")
+       })
+
+       wg.Add(nFast)
+       for i := 0; i < nFast; i++ {
+               t.Run(fmt.Sprintf("leaky%d", i), func(t *testing.T) {
+                       t.Parallel()
+                       wg.Done()
+               })
+       }
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_flag.txt b/libgo/go/cmd/go/testdata/script/test_flag.txt
new file mode 100644 (file)
index 0000000..0142b3f
--- /dev/null
@@ -0,0 +1,40 @@
+[short] skip
+
+go test flag_test.go -v -args -v=7 # Two distinct -v flags
+go test -v flag_test.go -args -v=7 # Two distinct -v flags
+
+# Using a custom flag mixed with regular 'go test' flags should be OK.
+go test -count=1 -custom -args -v=7
+
+# However, it should be an error to use custom flags when -i or -c are used,
+# since we know for sure that no test binary will run at all.
+! go test -i -custom
+stderr '^go test: unknown flag -custom cannot be used with -i$'
+! go test -c -custom
+stderr '^go test: unknown flag -custom cannot be used with -c$'
+
+# The same should apply even if -c or -i come after a custom flag.
+! go test -custom -c
+stderr '^go test: unknown flag -custom cannot be used with -c$'
+
+-- go.mod --
+module m
+-- flag_test.go --
+package flag_test
+
+import (
+       "flag"
+       "log"
+       "testing"
+)
+
+var v = flag.Int("v", 0, "v flag")
+
+var custom = flag.Bool("custom", false, "")
+
+// Run this as go test pkg -v=7
+func TestVFlagIsSet(t *testing.T) {
+       if *v != 7 {
+               log.Fatal("v flag not set")
+       }
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_import_error_stack.txt b/libgo/go/cmd/go/testdata/script/test_import_error_stack.txt
new file mode 100644 (file)
index 0000000..6c60f3d
--- /dev/null
@@ -0,0 +1,31 @@
+env GO111MODULE=off
+! go test testdep/p1
+stderr 'package testdep/p1 \(test\)\n\timports testdep/p2\n\timports testdep/p3: build constraints exclude all Go files ' # check for full import stack
+! go vet testdep/p1
+stderr 'package testdep/p1 \(test\)\n\timports testdep/p2\n\timports testdep/p3: build constraints exclude all Go files ' # check for full import stack
+
+env GO111MODULE=on
+cd testdep
+! go test testdep/p1
+stderr 'package testdep/p1 \(test\)\n\timports testdep/p2\n\timports testdep/p3: build constraints exclude all Go files ' # check for full import stack
+! go vet testdep/p1
+stderr 'package testdep/p1 \(test\)\n\timports testdep/p2\n\timports testdep/p3: build constraints exclude all Go files ' # check for full import stack
+
+-- testdep/go.mod --
+module testdep
+
+go 1.16
+-- testdep/p1/p1.go --
+package p1
+-- testdep/p1/p1_test.go --
+package p1
+
+import _ "testdep/p2"
+-- testdep/p2/p2.go --
+package p2
+
+import _ "testdep/p3"
+-- testdep/p3/p3.go --
+// +build ignore
+
+package ignored
diff --git a/libgo/go/cmd/go/testdata/script/test_json.txt b/libgo/go/cmd/go/testdata/script/test_json.txt
new file mode 100644 (file)
index 0000000..cd5b0b9
--- /dev/null
@@ -0,0 +1,74 @@
+[gccgo] skip # gccgo does not have standard packages
+[short] skip
+
+env GOCACHE=$WORK/tmp
+
+# Run go test -json on errors m/empty/pkg and m/skipper
+# It would be nice to test that the output is interlaced
+# but it seems to be impossible to do that in a short test
+# that isn't also flaky. Just check that we get JSON output.
+go test -json -short -v errors m/empty/pkg m/skipper
+
+# Check errors for run action
+stdout '"Package":"errors"'
+stdout '"Action":"run","Package":"errors"'
+
+# Check m/empty/pkg for output and skip actions
+stdout '"Action":"output","Package":"m/empty/pkg","Output":".*no test files'
+stdout '"Action":"skip","Package":"m/empty/pkg"'
+
+# Check skipper for output and skip actions
+stdout '"Action":"output","Package":"m/skipper","Test":"Test","Output":"--- SKIP:'
+stdout '"Action":"skip","Package":"m/skipper","Test":"Test"'
+
+# Run go test -json on errors and check it's cached
+go test -json -short -v errors
+stdout '"Action":"output","Package":"errors","Output":".*\(cached\)'
+
+go test -json -bench=NONE -short -v errors
+stdout '"Package":"errors"'
+stdout '"Action":"run"'
+
+# Test running test2json
+go test -o $WORK/tmp/errors.test$GOEXE -c errors
+go tool test2json -p errors $WORK/tmp/errors.test$GOEXE -test.v -test.short
+stdout '"Package":"errors"'
+stdout '"Action":"run"'
+stdout '\{"Action":"pass","Package":"errors"\}'
+
+-- go.mod --
+module m
+
+go 1.16
+-- skipper/skip_test.go --
+package skipper
+
+import "testing"
+
+func Test(t *testing.T) {
+       t.Skip("skipping")
+}
+-- empty/pkg/pkg.go --
+package p
+-- empty/pkgtest/pkg.go --
+package p
+-- empty/pkgtest/test_test.go --
+package p
+-- empty/pkgtestxtest/pkg.go --
+package p
+-- empty/pkgtestxtest/test_test.go --
+package p
+-- empty/pkgtestxtest/xtest_test.go --
+package p_test
+-- empty/pkgxtest/pkg.go --
+package p
+-- empty/pkgxtest/xtest_test.go --
+package p_test
+-- empty/test/test_test.go --
+package p
+-- empty/testxtest/test_test.go --
+package p
+-- empty/testxtest/xtest_test.go --
+package p_test
+-- empty/xtest/xtest_test.go --
+package p_test
diff --git a/libgo/go/cmd/go/testdata/script/test_json_exit.txt b/libgo/go/cmd/go/testdata/script/test_json_exit.txt
new file mode 100644 (file)
index 0000000..dc7ffb0
--- /dev/null
@@ -0,0 +1,102 @@
+[short] skip
+
+go test -c -o mainpanic.exe ./mainpanic &
+go test -c -o mainexit0.exe ./mainexit0 &
+go test -c -o testpanic.exe ./testpanic &
+go test -c -o testbgpanic.exe ./testbgpanic &
+wait
+
+# Test binaries that panic in TestMain should be marked as failing.
+
+! go test -json ./mainpanic
+stdout '"Action":"fail"'
+! stdout '"Action":"pass"'
+
+! go tool test2json ./mainpanic.exe
+stdout '"Action":"fail"'
+! stdout '"Action":"pass"'
+
+# Test binaries that exit with status 0 should be marked as passing.
+
+go test -json ./mainexit0
+stdout '"Action":"pass"'
+! stdout '"Action":"fail"'
+
+go tool test2json ./mainexit0.exe
+stdout '"Action":"pass"'
+! stdout '"Action":"fail"'
+
+# Test functions that panic should never be marked as passing
+# (https://golang.org/issue/40132).
+
+! go test -json ./testpanic
+stdout '"Action":"fail"'
+! stdout '"Action":"pass"'
+
+! go tool test2json ./testpanic.exe -test.v
+stdout '"Action":"fail"'
+! stdout '"Action":"pass"'
+
+! go tool test2json ./testpanic.exe
+stdout '"Action":"fail"'
+! stdout '"Action":"pass"'
+
+# Tests that panic in a background goroutine should be marked as failing.
+
+! go test -json ./testbgpanic
+stdout '"Action":"fail"'
+! stdout '"Action":"pass"'
+
+! go tool test2json ./testbgpanic.exe -test.v
+stdout '"Action":"fail"'
+! stdout '"Action":"pass"'
+
+! go tool test2json ./testbgpanic.exe
+stdout '"Action":"fail"'
+! stdout '"Action":"pass"'
+
+-- go.mod --
+module m
+go 1.14
+-- mainpanic/mainpanic_test.go --
+package mainpanic_test
+
+import "testing"
+
+func TestMain(m *testing.M) {
+       panic("haha no")
+}
+-- mainexit0/mainexit0_test.go --
+package mainexit0_test
+
+import (
+       "fmt"
+       "os"
+       "testing"
+)
+
+func TestMain(m *testing.M) {
+       fmt.Println("nothing to do")
+       os.Exit(0)
+}
+-- testpanic/testpanic_test.go --
+package testpanic_test
+
+import "testing"
+
+func TestPanic(*testing.T) {
+       panic("haha no")
+}
+-- testbgpanic/testbgpanic_test.go --
+package testbgpanic_test
+
+import "testing"
+
+func TestPanicInBackground(*testing.T) {
+       c := make(chan struct{})
+       go func() {
+               panic("haha no")
+               close(c)
+       }()
+       <-c
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_json_interleaved.txt b/libgo/go/cmd/go/testdata/script/test_json_interleaved.txt
new file mode 100644 (file)
index 0000000..e2d349e
--- /dev/null
@@ -0,0 +1,27 @@
+# Regression test for https://golang.org/issue/40657: output from the main test
+# function should be attributed correctly even if interleaved with the PAUSE
+# line for a new parallel subtest.
+
+[short] skip
+
+go test -json
+stdout '"Test":"TestWeirdTiming","Output":"[^"]* logging to outer again\\n"'
+
+-- go.mod --
+module example.com
+go 1.15
+-- main_test.go --
+package main
+
+import (
+       "testing"
+)
+
+func TestWeirdTiming(outer *testing.T) {
+       outer.Run("pauser", func(pauser *testing.T) {
+               outer.Logf("logging to outer")
+               pauser.Parallel()
+       })
+
+       outer.Logf("logging to outer again")
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_json_panic_exit.txt b/libgo/go/cmd/go/testdata/script/test_json_panic_exit.txt
new file mode 100644 (file)
index 0000000..d0a7991
--- /dev/null
@@ -0,0 +1,69 @@
+# Verifies golang.org/issue/37555.
+
+[short] skip
+
+# 'go test -json' should say a test passes if it says it passes.
+go test -json ./pass
+stdout '"Action":"pass".*\n\z'
+! stdout '"Test":.*\n\z'
+
+# 'go test -json' should say a test passes if it exits 0 and prints nothing.
+# TODO(golang.org/issue/29062): this should fail in the future.
+go test -json ./exit0main
+stdout '"Action":"pass".*\n\z'
+! stdout '"Test":.*\n\z'
+
+# 'go test -json' should say a test fails if it exits 1 and prints nothing.
+! go test -json ./exit1main
+stdout '"Action":"fail".*\n\z'
+! stdout '"Test":.*\n\z'
+
+# 'go test -json' should say a test fails if it panics.
+! go test -json ./panic
+stdout '"Action":"fail".*\n\z'
+! stdout '"Test":.*\n\z'
+
+-- go.mod --
+module example.com/test
+
+go 1.14
+
+-- pass/pass_test.go --
+package pass_test
+
+import "testing"
+
+func TestPass(t *testing.T) {}
+
+-- exit0main/exit0main_test.go --
+package exit0_test
+
+import (
+       "os"
+       "testing"
+)
+
+func TestMain(m *testing.M) {
+       os.Exit(0)
+}
+
+-- exit1main/exit1main_test.go --
+package exit1_test
+
+import (
+       "os"
+       "testing"
+)
+
+func TestMain(m *testing.M) {
+       os.Exit(1)
+}
+
+-- panic/panic_test.go --
+package panic_test
+
+import "testing"
+
+func TestPanic(t *testing.T) {
+       panic("oh no")
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_main.txt b/libgo/go/cmd/go/testdata/script/test_main.txt
new file mode 100644 (file)
index 0000000..25d02e4
--- /dev/null
@@ -0,0 +1,92 @@
+# Test TestMain
+go test standalone_main_normal_test.go
+! stdout '^ok.*\[no tests to run\]'
+! stderr '^ok.*\[no tests to run\]'
+stdout '^ok'
+
+# Test TestMain sees testing flags
+go test standalone_testmain_flag_test.go
+stdout '^ok.*\[no tests to run\]'
+
+# Test TestMain with wrong signature (Issue #22388)
+! go test standalone_main_wrong_test.go
+stderr 'wrong signature for TestMain, must be: func TestMain\(m \*testing.M\)'
+
+# Test TestMain does not call os.Exit (Issue #34129)
+! go test standalone_testmain_not_call_os_exit_test.go
+! stdout '^ok'
+
+-- standalone_main_normal_test.go --
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package standalone_main_normal_test
+
+import "testing"
+
+func TestMain(t *testing.T) {
+}
+-- standalone_main_wrong_test.go --
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package standalone_main_wrong_test
+
+import "testing"
+
+func TestMain(m *testing.Main) {
+}
+-- standalone_testmain_flag_test.go --
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package standalone_testmain_flag_test
+
+import (
+       "flag"
+       "fmt"
+       "os"
+       "testing"
+)
+
+func TestMain(m *testing.M) {
+       // A TestMain should be able to access testing flags if it calls
+       // flag.Parse without needing to use testing.Init.
+       flag.Parse()
+       found := false
+       flag.VisitAll(func(f *flag.Flag) {
+               if f.Name == "test.count" {
+                       found = true
+               }
+       })
+       if !found {
+               fmt.Println("testing flags not registered")
+               os.Exit(1)
+       }
+       os.Exit(m.Run())
+}
+-- standalone_testmain_not_call_os_exit_test.go --
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package standalone_testmain_not_call_os_exit_test
+
+import (
+       "testing"
+)
+
+func TestWillFail(t *testing.T) {
+       t.Error("this test will fail.")
+}
+
+func TestMain(m *testing.M) {
+       defer func() {
+               recover()
+       }()
+       exit := m.Run()
+       panic(exit)
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_main_panic.txt b/libgo/go/cmd/go/testdata/script/test_main_panic.txt
new file mode 100644 (file)
index 0000000..45887c5
--- /dev/null
@@ -0,0 +1,30 @@
+[short] skip
+[!race] skip
+
+! go test -v -race main_panic/testmain_parallel_sub_panic_test.go
+! stdout 'DATA RACE'
+-- main_panic/testmain_parallel_sub_panic_test.go --
+package testmain_parallel_sub_panic_test
+
+import "testing"
+
+func setup()    { println("setup()") }
+func teardown() { println("teardown()") }
+func TestA(t *testing.T) {
+       t.Run("1", func(t *testing.T) {
+               t.Run("1", func(t *testing.T) {
+                       t.Parallel()
+                       panic("A/1/1 panics")
+               })
+               t.Run("2", func(t *testing.T) {
+                       t.Parallel()
+                       println("A/1/2 is ok")
+               })
+       })
+}
+
+func TestMain(m *testing.M) {
+       setup()
+       defer teardown()
+       m.Run()
+}
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/test_main_twice.txt b/libgo/go/cmd/go/testdata/script/test_main_twice.txt
new file mode 100644 (file)
index 0000000..f32d4fc
--- /dev/null
@@ -0,0 +1,27 @@
+[short] skip
+
+env GOCACHE=$WORK/tmp
+go test -v multimain
+stdout -count=2 notwithstanding # check tests ran twice
+
+-- go.mod --
+module multimain
+
+go 1.16
+-- multimain_test.go --
+package multimain_test
+
+import "testing"
+
+func TestMain(m *testing.M) {
+       // Some users run m.Run multiple times, changing
+       // some kind of global state between runs.
+       // This used to work so I guess now it has to keep working.
+       // See golang.org/issue/23129.
+       m.Run()
+       m.Run()
+}
+
+func Test(t *testing.T) {
+       t.Log("notwithstanding")
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_match_benchmark_labels.txt b/libgo/go/cmd/go/testdata/script/test_match_benchmark_labels.txt
new file mode 100644 (file)
index 0000000..13c4007
--- /dev/null
@@ -0,0 +1,18 @@
+# Benchmark labels, file outside gopath
+# TODO(matloob): This test was called TestBenchmarkLabelsOutsideGOPATH
+# why "OutsideGOPATH"? Does the go command need to be run outside GOPATH?
+# Do the files need to exist outside GOPATH?
+cp $GOPATH/src/standalone_benchmark_test.go $WORK/tmp/standalone_benchmark_test.go
+go test -run '^$' -bench . $WORK/tmp/standalone_benchmark_test.go
+stdout '^goos: '$GOOS
+stdout '^goarch: '$GOARCH
+! stdout '^pkg:'
+! stderr '^pkg:'
+
+-- standalone_benchmark_test.go --
+package standalone_benchmark
+
+import "testing"
+
+func Benchmark(b *testing.B) {
+}
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/test_match_no_benchmarks.txt b/libgo/go/cmd/go/testdata/script/test_match_no_benchmarks.txt
new file mode 100644 (file)
index 0000000..30f4be8
--- /dev/null
@@ -0,0 +1,13 @@
+# Matches no benchmarks
+go test -run '^$' -bench ThisWillNotMatch standalone_benchmark_test.go
+! stdout '^ok.*\[no tests to run\]'
+! stderr '^ok.*\[no tests to run\]'
+stdout '^ok'
+
+-- standalone_benchmark_test.go --
+package standalone_benchmark
+
+import "testing"
+
+func Benchmark(b *testing.B) {
+}
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/test_match_no_subtests.txt b/libgo/go/cmd/go/testdata/script/test_match_no_subtests.txt
new file mode 100644 (file)
index 0000000..7abb1eb
--- /dev/null
@@ -0,0 +1,12 @@
+# The subtests don't match
+go test -run Test/ThisWillNotMatch standalone_sub_test.go
+stdout '^ok.*\[no tests to run\]'
+
+-- standalone_sub_test.go --
+package standalone_sub_test
+
+import "testing"
+
+func Test(t *testing.T) {
+       t.Run("Sub", func(t *testing.T) {})
+}
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/test_match_no_subtests_failure.txt b/libgo/go/cmd/go/testdata/script/test_match_no_subtests_failure.txt
new file mode 100644 (file)
index 0000000..b3c5b92
--- /dev/null
@@ -0,0 +1,15 @@
+# Matches no subtests, but parent test still fails
+! go test -run TestThatFails/ThisWillNotMatch standalone_fail_sub_test.go
+! stdout '^ok.*\[no tests to run\]'
+! stderr '^ok.*\[no tests to run\]'
+stdout 'FAIL'
+
+-- standalone_fail_sub_test.go --
+package standalone_fail_sub_test
+
+import "testing"
+
+func TestThatFails(t *testing.T) {
+       t.Run("Sub", func(t *testing.T) {})
+       t.Fail()
+}
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/test_match_no_subtests_parallel.txt b/libgo/go/cmd/go/testdata/script/test_match_no_subtests_parallel.txt
new file mode 100644 (file)
index 0000000..11c734c
--- /dev/null
@@ -0,0 +1,19 @@
+# Matches no subtests, parallel
+go test -run Test/Sub/ThisWillNotMatch standalone_parallel_sub_test.go
+stdout '^ok.*\[no tests to run\]'
+
+-- standalone_parallel_sub_test.go --
+package standalone_parallel_sub_test
+
+import "testing"
+
+func Test(t *testing.T) {
+       ch := make(chan bool, 1)
+       t.Run("Sub", func(t *testing.T) {
+               t.Parallel()
+               <-ch
+               t.Run("Nested", func(t *testing.T) {})
+       })
+       // Ensures that Sub will finish after its t.Run call already returned.
+       ch <- true
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_match_no_tests.txt b/libgo/go/cmd/go/testdata/script/test_match_no_tests.txt
new file mode 100644 (file)
index 0000000..1ad2097
--- /dev/null
@@ -0,0 +1,11 @@
+# Matches no tests
+go test -run ThisWillNotMatch standalone_test.go
+stdout '^ok.*\[no tests to run\]'
+
+-- standalone_test.go --
+package standalone_test
+
+import "testing"
+
+func Test(t *testing.T) {
+}
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/test_match_no_tests_build_failure.txt b/libgo/go/cmd/go/testdata/script/test_match_no_tests_build_failure.txt
new file mode 100644 (file)
index 0000000..e1c9643
--- /dev/null
@@ -0,0 +1,19 @@
+# Test that when there's a build failure and a -run flag that doesn't match,
+# that the error for not matching tests does not override the error for
+# the build failure.
+
+! go test -run ThisWillNotMatch syntaxerror
+! stderr '(?m)^ok.*\[no tests to run\]'
+stdout 'FAIL'
+
+-- go.mod --
+module syntaxerror
+
+go 1.16
+-- x.go --
+package p
+-- x_test.go --
+package p
+
+func f() (x.y, z int) {
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_match_no_tests_with_subtests.txt b/libgo/go/cmd/go/testdata/script/test_match_no_tests_with_subtests.txt
new file mode 100644 (file)
index 0000000..0d94918
--- /dev/null
@@ -0,0 +1,12 @@
+# Matches no tests with subtests
+go test -run ThisWillNotMatch standalone_sub_test.go
+stdout '^ok.*\[no tests to run\]'
+
+-- standalone_sub_test.go --
+package standalone_sub_test
+
+import "testing"
+
+func Test(t *testing.T) {
+       t.Run("Sub", func(t *testing.T) {})
+}
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/test_match_only_benchmarks.txt b/libgo/go/cmd/go/testdata/script/test_match_only_benchmarks.txt
new file mode 100644 (file)
index 0000000..5dfb96e
--- /dev/null
@@ -0,0 +1,13 @@
+# Matches only benchmarks
+go test -run '^$' -bench . standalone_benchmark_test.go
+! stdout '^ok.*\[no tests to run\]'
+! stderr '^ok.*\[no tests to run\]'
+stdout '^ok'
+
+-- standalone_benchmark_test.go --
+package standalone_benchmark
+
+import "testing"
+
+func Benchmark(b *testing.B) {
+}
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/test_match_only_example.txt b/libgo/go/cmd/go/testdata/script/test_match_only_example.txt
new file mode 100644 (file)
index 0000000..515ccb3
--- /dev/null
@@ -0,0 +1,31 @@
+[short] skip
+
+# Check that it's okay for test pattern to match only examples.
+go test -run Example example1_test.go
+! stderr '^ok.*\[no tests to run\]'
+stdout '^ok'
+
+-- example1_test.go --
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure that go test runs Example_Z before Example_A, preserving source order.
+
+package p
+
+import "fmt"
+
+var n int
+
+func Example_Z() {
+       n++
+       fmt.Println(n)
+       // Output: 1
+}
+
+func Example_A() {
+       n++
+       fmt.Println(n)
+       // Output: 2
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_match_only_subtests.txt b/libgo/go/cmd/go/testdata/script/test_match_only_subtests.txt
new file mode 100644 (file)
index 0000000..beea895
--- /dev/null
@@ -0,0 +1,14 @@
+# Matches only subtests
+go test -run Test/Sub standalone_sub_test.go
+! stdout '^ok.*\[no tests to run\]'
+! stderr '^ok.*\[no tests to run\]'
+stdout '^ok'
+
+-- standalone_sub_test.go --
+package standalone_sub_test
+
+import "testing"
+
+func Test(t *testing.T) {
+       t.Run("Sub", func(t *testing.T) {})
+}
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/test_match_only_subtests_parallel.txt b/libgo/go/cmd/go/testdata/script/test_match_only_subtests_parallel.txt
new file mode 100644 (file)
index 0000000..11872c2
--- /dev/null
@@ -0,0 +1,21 @@
+# Matches only subtests, parallel
+go test -run Test/Sub/Nested standalone_parallel_sub_test.go
+! stdout '^ok.*\[no tests to run\]'
+! stderr '^ok.*\[no tests to run\]'
+stdout '^ok'
+
+-- standalone_parallel_sub_test.go --
+package standalone_parallel_sub_test
+
+import "testing"
+
+func Test(t *testing.T) {
+       ch := make(chan bool, 1)
+       t.Run("Sub", func(t *testing.T) {
+               t.Parallel()
+               <-ch
+               t.Run("Nested", func(t *testing.T) {})
+       })
+       // Ensures that Sub will finish after its t.Run call already returned.
+       ch <- true
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_match_only_tests.txt b/libgo/go/cmd/go/testdata/script/test_match_only_tests.txt
new file mode 100644 (file)
index 0000000..9185793
--- /dev/null
@@ -0,0 +1,13 @@
+# Matches only tests
+go test -run Test standalone_test.go
+! stdout '^ok.*\[no tests to run\]'
+! stderr '^ok.*\[no tests to run\]'
+stdout '^ok'
+
+-- standalone_test.go --
+package standalone_test
+
+import "testing"
+
+func Test(t *testing.T) {
+}
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/test_minus_n.txt b/libgo/go/cmd/go/testdata/script/test_minus_n.txt
new file mode 100644 (file)
index 0000000..9900dbc
--- /dev/null
@@ -0,0 +1,14 @@
+# The intent here is to verify that 'go test -n' works without crashing.
+# Any test will do.
+
+go test -n x_test.go
+
+-- x_test.go --
+package x_test
+
+import (
+       "testing"
+)
+
+func TestEmpty(t *testing.T) {
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_no_run_example.txt b/libgo/go/cmd/go/testdata/script/test_no_run_example.txt
new file mode 100644 (file)
index 0000000..53ac755
--- /dev/null
@@ -0,0 +1,30 @@
+go test -v norunexample
+stdout 'File with non-runnable example was built.'
+
+-- go.mod --
+module norunexample
+
+go 1.16
+-- example_test.go --
+package pkg_test
+
+import "os"
+
+func init() {
+       os.Stdout.Write([]byte("File with non-runnable example was built.\n"))
+}
+
+func Example_test() {
+       // This test will not be run, it has no "Output:" comment.
+}
+-- test_test.go --
+package pkg
+
+import (
+       "os"
+       "testing"
+)
+
+func TestBuilt(t *testing.T) {
+       os.Stdout.Write([]byte("A normal test was executed.\n"))
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_no_tests.txt b/libgo/go/cmd/go/testdata/script/test_no_tests.txt
new file mode 100644 (file)
index 0000000..2d624d1
--- /dev/null
@@ -0,0 +1,15 @@
+# Tests issue #26242
+
+go test testnorun
+stdout 'testnorun\t\[no test files\]'
+
+-- go.mod --
+module testnorun
+
+go 1.16
+-- p.go --
+package p
+
+func init() {
+       panic("go test must not link and run test binaries without tests")
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_overlay.txt b/libgo/go/cmd/go/testdata/script/test_overlay.txt
new file mode 100644 (file)
index 0000000..b6bdc11
--- /dev/null
@@ -0,0 +1,24 @@
+[short] skip
+
+cd $WORK/gopath/src/foo
+go test -list=. -overlay=overlay.json .
+stdout 'TestBar'
+
+-- go.mod --
+module test.pkg
+-- foo/foo_test.go --
+package foo
+
+import "testing"
+
+func TestFoo(t *testing.T) { }
+-- tmp/bar_test.go --
+package foo
+
+import "testing"
+
+func TestBar(t *testing.T) {
+       t.Fatal("dummy failure")
+}
+-- foo/overlay.json --
+{"Replace": {"foo_test.go": "../tmp/bar_test.go"}}
diff --git a/libgo/go/cmd/go/testdata/script/test_parallel_number.txt b/libgo/go/cmd/go/testdata/script/test_parallel_number.txt
new file mode 100644 (file)
index 0000000..4eb9794
--- /dev/null
@@ -0,0 +1,25 @@
+[short] skip
+
+# go test -parallel -1 shouldn't work
+! go test -parallel -1 standalone_parallel_sub_test.go
+stdout '-parallel can only be given'
+
+# go test -parallel 0 shouldn't work
+! go test -parallel 0 standalone_parallel_sub_test.go
+stdout '-parallel can only be given'
+
+-- standalone_parallel_sub_test.go --
+package standalone_parallel_sub_test
+
+import "testing"
+
+func Test(t *testing.T) {
+       ch := make(chan bool, 1)
+       t.Run("Sub", func(t *testing.T) {
+               t.Parallel()
+               <-ch
+               t.Run("Nested", func(t *testing.T) {})
+       })
+       // Ensures that Sub will finish after its t.Run call already returned.
+       ch <- true
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_profile.txt b/libgo/go/cmd/go/testdata/script/test_profile.txt
new file mode 100644 (file)
index 0000000..4bfa2cc
--- /dev/null
@@ -0,0 +1,19 @@
+[gccgo] skip 'gccgo has no standard packages'
+[short] skip
+
+# Check go test -cpuprofile creates errors.test
+go test -cpuprofile errors.prof errors
+exists -exec errors.test$GOEXE
+
+# Check go test -cpuprofile -o myerrors.test creates errors.test
+go test -cpuprofile errors.prof -o myerrors.test$GOEXE errors
+exists -exec myerrors.test$GOEXE
+
+# Check go test -mutexprofile creates errors.test
+go test -mutexprofile errors.prof errors
+exists -exec errors.test$GOEXE
+
+# Check go test -mutexprofile -o myerrors.test creates errors.test
+go test -mutexprofile errors.prof -o myerrors.test$GOEXE errors
+exists -exec myerrors.test$GOEXE
+
diff --git a/libgo/go/cmd/go/testdata/script/test_race.txt b/libgo/go/cmd/go/testdata/script/test_race.txt
new file mode 100644 (file)
index 0000000..2ffea46
--- /dev/null
@@ -0,0 +1,51 @@
+[short] skip
+[!race] skip
+
+go test testrace
+
+! go test -race testrace
+stdout 'FAIL: TestRace'
+! stdout 'PASS'
+! stderr 'PASS'
+
+! go test -race testrace -run XXX -bench .
+stdout 'FAIL: BenchmarkRace'
+! stdout 'PASS'
+! stderr 'PASS'
+
+-- go.mod --
+module testrace
+
+go 1.16
+-- race_test.go --
+package testrace
+
+import "testing"
+
+func TestRace(t *testing.T) {
+       for i := 0; i < 10; i++ {
+               c := make(chan int)
+               x := 1
+               go func() {
+                       x = 2
+                       c <- 1
+               }()
+               x = 3
+               <-c
+               _ = x
+       }
+}
+
+func BenchmarkRace(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               c := make(chan int)
+               x := 1
+               go func() {
+                       x = 2
+                       c <- 1
+               }()
+               x = 3
+               <-c
+               _ = x
+       }
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_race_cover_mode_issue20435.txt b/libgo/go/cmd/go/testdata/script/test_race_cover_mode_issue20435.txt
new file mode 100644 (file)
index 0000000..eacc882
--- /dev/null
@@ -0,0 +1,48 @@
+[short] skip
+[!race] skip
+
+# Make sure test is functional.
+go test testrace
+
+# Now, check that -race -covermode=set is not allowed.
+! go test -race -covermode=set testrace
+stderr '-covermode must be "atomic", not "set", when -race is enabled'
+! stdout PASS
+! stderr PASS
+
+-- go.mod --
+module testrace
+
+go 1.16
+-- race_test.go --
+package testrace
+
+import "testing"
+
+func TestRace(t *testing.T) {
+       for i := 0; i < 10; i++ {
+               c := make(chan int)
+               x := 1
+               go func() {
+                       x = 2
+                       c <- 1
+               }()
+               x = 3
+               <-c
+               _ = x
+       }
+}
+
+func BenchmarkRace(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               c := make(chan int)
+               x := 1
+               go func() {
+                       x = 2
+                       c <- 1
+               }()
+               x = 3
+               <-c
+               _ = x
+       }
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_race_install.txt b/libgo/go/cmd/go/testdata/script/test_race_install.txt
new file mode 100644 (file)
index 0000000..8b1f343
--- /dev/null
@@ -0,0 +1,18 @@
+[!race] skip
+[short] skip
+
+mkdir $WORKDIR/tmp/pkg
+go install -race -pkgdir=$WORKDIR/tmp/pkg std
+
+# Make sure go test -i -race doesn't rebuild cached packages
+go test -race -pkgdir=$WORKDIR/tmp/pkg -i -v empty/pkg
+cmp stderr stderr.txt
+
+-- go.mod --
+module empty
+
+go 1.16
+-- pkg/pkg.go --
+package p
+-- stderr.txt --
+go test: -i flag is deprecated
diff --git a/libgo/go/cmd/go/testdata/script/test_race_install_cgo.txt b/libgo/go/cmd/go/testdata/script/test_race_install_cgo.txt
new file mode 100644 (file)
index 0000000..e1fe4f2
--- /dev/null
@@ -0,0 +1,91 @@
+# Tests Issue #10500
+
+[!race] skip
+
+env GOBIN=$WORK/bin
+go install m/mtime m/sametime
+
+go tool -n cgo
+cp stdout cgopath.txt
+exec $GOBIN/mtime cgopath.txt # get the mtime of the file whose name is in cgopath.txt
+cp stdout cgotime_before.txt
+
+ # For this test, we don't actually care whether 'go test -race -i' succeeds.
+ # It may fail if GOROOT is read-only (perhaps it was installed as root).
+ # We only care that it does not overwrite cmd/cgo regardless.
+? go test -race -i runtime/race
+
+exec $GOBIN/mtime cgopath.txt # get the mtime of the file whose name is in cgopath.txt
+cp stdout cgotime_after.txt
+exec $GOBIN/sametime cgotime_before.txt cgotime_after.txt
+
+-- go.mod --
+module m
+
+go 1.16
+-- mtime/mtime.go --
+package main
+
+import (
+       "encoding/json"
+       "fmt"
+       "os"
+       "strings"
+)
+
+func main() {
+       b, err := os.ReadFile(os.Args[1])
+       if err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+       filename := strings.TrimSpace(string(b))
+       info, err := os.Stat(filename)
+       if err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+       if err := json.NewEncoder(os.Stdout).Encode(info.ModTime()); err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+}
+-- sametime/sametime.go --
+package main
+
+import (
+       "encoding/json"
+       "fmt"
+       "os"
+       "time"
+)
+
+
+func main() {
+       var t1 time.Time
+       b1, err := os.ReadFile(os.Args[1])
+       if err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+       if err := json.Unmarshal(b1, &t1); err != nil  {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+
+       var t2 time.Time
+       b2, err := os.ReadFile(os.Args[2])
+       if err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+       if err := json.Unmarshal(b2, &t2); err != nil  {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+
+       if !t1.Equal(t2) {
+               fmt.Fprintf(os.Stderr, "time in %v (%v) is not the same as time in %v (%v)", os.Args[1], t1, os.Args[2], t2)
+               os.Exit(1)
+       }
+}
similarity index 96%
rename from libgo/go/cmd/go/testdata/test_regexps.txt
rename to libgo/go/cmd/go/testdata/script/test_regexps.txt
index a616195caba9184b448f248680b5d3b494e94d2a..2f33080a00474e3cd7c3c0b656de7a76b775b07c 100644 (file)
@@ -35,7 +35,11 @@ stdout -count=1 '^    z_test.go:18: LOG: XX running N=1$'
 # a large number, and the last iteration count prints right before the results.
 stdout -count=2 '^    x_test.go:15: LOG: Y running N=[1-9]\d{4,}\nBenchmarkX/Y\s+\d+'
 
--- testregexp/x_test.go --
+-- go.mod --
+module testregexp
+
+go 1.16
+-- x_test.go --
 package x
 
 import "testing"
@@ -53,7 +57,7 @@ func BenchmarkX(b *testing.B) {
                b.Logf("LOG: Y running N=%d", b.N)
        })
 }
--- testregexp/z_test.go --
+-- z_test.go --
 package x
 
 import "testing"
diff --git a/libgo/go/cmd/go/testdata/script/test_relative_cmdline.txt b/libgo/go/cmd/go/testdata/script/test_relative_cmdline.txt
new file mode 100644 (file)
index 0000000..2f9c80f
--- /dev/null
@@ -0,0 +1,50 @@
+# Relative imports in command line package
+
+# Run tests outside GOPATH.
+env GOPATH=$WORK/tmp
+
+go test ./testimport/p.go ./testimport/p_test.go ./testimport/x_test.go
+stdout '^ok'
+
+-- testimport/p.go --
+package p
+
+func F() int { return 1 }
+-- testimport/p1/p1.go --
+package p1
+
+func F() int { return 1 }
+-- testimport/p2/p2.go --
+package p2
+
+func F() int { return 1 }
+-- testimport/p_test.go --
+package p
+
+import (
+       "./p1"
+
+       "testing"
+)
+
+func TestF(t *testing.T) {
+       if F() != p1.F() {
+               t.Fatal(F())
+       }
+}
+-- testimport/x_test.go --
+package p_test
+
+import (
+       . "../testimport"
+
+       "./p2"
+
+       "testing"
+)
+
+func TestF1(t *testing.T) {
+       if F() != p2.F() {
+               t.Fatal(F())
+       }
+}
\ No newline at end of file
diff --git a/libgo/go/cmd/go/testdata/script/test_relative_import.txt b/libgo/go/cmd/go/testdata/script/test_relative_import.txt
new file mode 100644 (file)
index 0000000..938a875
--- /dev/null
@@ -0,0 +1,31 @@
+# Relative imports in go test
+env GO111MODULE=off # relative import not supported in module mode
+
+# Run tests outside GOPATH.
+env GOPATH=$WORK/tmp
+
+go test ./testimport
+stdout '^ok'
+
+-- testimport/p.go --
+package p
+
+func F() int { return 1 }
+-- testimport/p1/p1.go --
+package p1
+
+func F() int { return 1 }
+-- testimport/p_test.go --
+package p
+
+import (
+       "./p1"
+
+       "testing"
+)
+
+func TestF(t *testing.T) {
+       if F() != p1.F() {
+               t.Fatal(F())
+       }
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_relative_import_dash_i.txt b/libgo/go/cmd/go/testdata/script/test_relative_import_dash_i.txt
new file mode 100644 (file)
index 0000000..b2716d8
--- /dev/null
@@ -0,0 +1,32 @@
+# Relative imports in go test -i
+env GO111MODULE=off # relative import not supported in module mode
+
+# Run tests outside GOPATH.
+env GOPATH=$WORK/tmp
+
+# Check that it's safe to pass -i (which installs dependencies in $GOPATH/pkg) to go test.
+! stale runtime # don't let test -i overwrite runtime
+go test -i ./testimport
+
+-- testimport/p.go --
+package p
+
+func F() int { return 1 }
+-- testimport/p1/p1.go --
+package p1
+
+func F() int { return 1 }
+-- testimport/p_test.go --
+package p
+
+import (
+       "./p1"
+
+       "testing"
+)
+
+func TestF(t *testing.T) {
+       if F() != p1.F() {
+               t.Fatal(F())
+       }
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_script_cmdcd.txt b/libgo/go/cmd/go/testdata/script/test_script_cmdcd.txt
new file mode 100644 (file)
index 0000000..6e6f67e
--- /dev/null
@@ -0,0 +1,13 @@
+# Tests that after a cd command, where usually the UNIX path separator is used,
+# a match against $PWD does not fail on Windows.
+
+cd $WORK/a/b/c/pkg
+
+go list -find -f {{.Root}}
+stdout $PWD
+
+-- $WORK/a/b/c/pkg/go.mod --
+module pkg
+
+-- $WORK/a/b/c/pkg/pkg.go --
+package pkg
diff --git a/libgo/go/cmd/go/testdata/script/test_shuffle.txt b/libgo/go/cmd/go/testdata/script/test_shuffle.txt
new file mode 100644 (file)
index 0000000..3a50605
--- /dev/null
@@ -0,0 +1,148 @@
+# Shuffle order of tests and benchmarks
+
+# Run tests
+go test -v foo_test.go
+! stdout '-test.shuffle '
+stdout '(?s)TestOne(.*)TestTwo(.*)TestThree'
+
+go test -v -shuffle=off foo_test.go
+! stdout '-test.shuffle '
+stdout '(?s)TestOne(.*)TestTwo(.*)TestThree'
+
+go test -v -shuffle=42 foo_test.go
+stdout '^-test.shuffle 42'
+stdout '(?s)TestThree(.*)TestOne(.*)TestTwo'
+
+go test -v -shuffle=43 foo_test.go
+stdout '^-test.shuffle 43'
+stdout '(?s)TestThree(.*)TestTwo(.*)TestOne'
+
+go test -v -shuffle=44 foo_test.go
+stdout '^-test.shuffle 44'
+stdout '(?s)TestOne(.*)TestThree(.*)TestTwo'
+
+go test -v -shuffle=0 foo_test.go
+stdout '^-test.shuffle 0'
+stdout '(?s)TestTwo(.*)TestOne(.*)TestThree'
+
+go test -v -shuffle -1 foo_test.go
+stdout '^-test.shuffle -1'
+stdout '(?s)TestThree(.*)TestOne(.*)TestTwo'
+
+go test -v -shuffle=on foo_test.go
+stdout '^-test.shuffle '
+stdout '(?s)=== RUN   TestOne(.*)--- PASS: TestOne'
+stdout '(?s)=== RUN   TestTwo(.*)--- PASS: TestTwo'
+stdout '(?s)=== RUN   TestThree(.*)--- PASS: TestThree'
+
+
+# Run tests and benchmarks
+go test -v -bench=. foo_test.go
+! stdout '-test.shuffle '
+stdout '(?s)TestOne(.*)TestTwo(.*)TestThree(.*)BenchmarkOne(.*)BenchmarkTwo(.*)BenchmarkThree'
+
+go test -v -bench=. -shuffle=off foo_test.go
+! stdout '-test.shuffle '
+stdout '(?s)TestOne(.*)TestTwo(.*)TestThree(.*)BenchmarkOne(.*)BenchmarkTwo(.*)BenchmarkThree'
+
+go test -v -bench=. -shuffle=42 foo_test.go
+stdout '^-test.shuffle 42'
+stdout '(?s)TestThree(.*)TestOne(.*)TestTwo(.*)BenchmarkThree(.*)BenchmarkOne(.*)BenchmarkTwo'
+
+go test -v -bench=. -shuffle=43 foo_test.go
+stdout '^-test.shuffle 43'
+stdout '(?s)TestThree(.*)TestTwo(.*)TestOne(.*)BenchmarkThree(.*)BenchmarkOne(.*)BenchmarkTwo'
+
+go test -v -bench=. -shuffle=44 foo_test.go
+stdout '^-test.shuffle 44'
+stdout '(?s)TestOne(.*)TestThree(.*)TestTwo(.*)BenchmarkTwo(.*)BenchmarkOne(.*)BenchmarkThree'
+
+go test -v -bench=. -shuffle=0 foo_test.go
+stdout '^-test.shuffle 0'
+stdout '(?s)TestTwo(.*)TestOne(.*)TestThree(.*)BenchmarkThree(.*)BenchmarkOne(.*)BenchmarkTwo'
+
+go test -v -bench=. -shuffle -1 foo_test.go
+stdout '^-test.shuffle -1'
+stdout '(?s)TestThree(.*)TestOne(.*)TestTwo(.*)BenchmarkOne(.*)BenchmarkThree(.*)BenchmarkTwo'
+
+go test -v -bench=. -shuffle=on foo_test.go
+stdout '^-test.shuffle '
+stdout '(?s)=== RUN   TestOne(.*)--- PASS: TestOne'
+stdout '(?s)=== RUN   TestTwo(.*)--- PASS: TestTwo'
+stdout '(?s)=== RUN   TestThree(.*)--- PASS: TestThree'
+stdout -count=2 'BenchmarkOne'
+stdout -count=2 'BenchmarkTwo'
+stdout -count=2 'BenchmarkThree'
+
+
+# When running go test -count=N, each of the N runs distinct runs should maintain the same
+# shuffled order of these tests.
+go test -v -shuffle=43 -count=4 foo_test.go
+stdout '^-test.shuffle 43'
+stdout '(?s)TestThree(.*)TestTwo(.*)TestOne(.*)TestThree(.*)TestTwo(.*)TestOne(.*)TestThree(.*)TestTwo(.*)TestOne(.*)TestThree(.*)TestTwo(.*)TestOne'
+
+go test -v -bench=. -shuffle=44 -count=2 foo_test.go
+stdout '^-test.shuffle 44'
+stdout '(?s)TestOne(.*)TestThree(.*)TestTwo(.*)TestOne(.*)TestThree(.*)TestTwo(.*)BenchmarkTwo(.*)BenchmarkOne(.*)BenchmarkThree(.*)'
+
+
+# The feature should work with test binaries as well
+go test -c
+exec ./m.test -test.shuffle=off
+! stdout '^-test.shuffle '
+
+exec ./m.test -test.shuffle=on
+stdout '^-test.shuffle '
+
+exec ./m.test -test.v -test.bench=. -test.shuffle=0 foo_test.go
+stdout '^-test.shuffle 0'
+stdout '(?s)TestTwo(.*)TestOne(.*)TestThree(.*)BenchmarkThree(.*)BenchmarkOne(.*)BenchmarkTwo'
+
+exec ./m.test -test.v -test.bench=. -test.shuffle=123 foo_test.go
+stdout '^-test.shuffle 123'
+stdout '(?s)TestThree(.*)TestOne(.*)TestTwo(.*)BenchmarkThree(.*)BenchmarkTwo(.*)BenchmarkOne'
+
+exec ./m.test -test.v -test.bench=. -test.shuffle=-1 foo_test.go
+stdout '^-test.shuffle -1'
+stdout '(?s)TestThree(.*)TestOne(.*)TestTwo(.*)BenchmarkOne(.*)BenchmarkThree(.*)BenchmarkTwo'
+
+exec ./m.test -test.v -test.bench=. -test.shuffle=44 -test.count=2 foo_test.go
+stdout '^-test.shuffle 44'
+stdout '(?s)TestOne(.*)TestThree(.*)TestTwo(.*)TestOne(.*)TestThree(.*)TestTwo(.*)BenchmarkTwo(.*)BenchmarkOne(.*)BenchmarkThree(.*)'
+
+
+# Negative testcases for invalid input
+! go test -shuffle -count=2
+stderr 'invalid value "-count=2" for flag -shuffle: -shuffle argument must be "on", "off", or an int64: strconv.ParseInt: parsing "-count=2": invalid syntax'
+
+! go test -shuffle=
+stderr '(?s)invalid value "" for flag -shuffle: -shuffle argument must be "on", "off", or an int64: strconv.ParseInt: parsing "": invalid syntax'
+
+! go test -shuffle=' '
+stderr '(?s)invalid value " " for flag -shuffle: -shuffle argument must be "on", "off", or an int64: strconv.ParseInt: parsing " ": invalid syntax'
+
+! go test -shuffle=true
+stderr 'invalid value "true" for flag -shuffle: -shuffle argument must be "on", "off", or an int64: strconv.ParseInt: parsing "true": invalid syntax'
+
+! go test -shuffle='abc'
+stderr 'invalid value "abc" for flag -shuffle: -shuffle argument must be "on", "off", or an int64: strconv.ParseInt: parsing "abc": invalid syntax'
+
+-- go.mod --
+module m
+
+go 1.16
+-- foo_test.go --
+package foo
+
+import "testing"
+
+func TestOne(t *testing.T)   {}
+func TestTwo(t *testing.T)   {}
+func TestThree(t *testing.T) {}
+
+func BenchmarkOne(b *testing.B)   {}
+func BenchmarkTwo(b *testing.B)   {}
+func BenchmarkThree(b *testing.B) {}
+
+-- foo.go --
+package foo
diff --git a/libgo/go/cmd/go/testdata/script/test_source_order.txt b/libgo/go/cmd/go/testdata/script/test_source_order.txt
new file mode 100644 (file)
index 0000000..2865276
--- /dev/null
@@ -0,0 +1,54 @@
+[short] skip
+
+# Control
+! go test example2_test.go example1_test.go
+
+# This test only passes if the source order is preserved
+go test example1_test.go example2_test.go
+
+-- example1_test.go --
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure that go test runs Example_Z before Example_A, preserving source order.
+
+package p
+
+import "fmt"
+
+var n int
+
+func Example_Z() {
+       n++
+       fmt.Println(n)
+       // Output: 1
+}
+
+func Example_A() {
+       n++
+       fmt.Println(n)
+       // Output: 2
+}
+-- example2_test.go --
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure that go test runs Example_Y before Example_B, preserving source order.
+
+package p
+
+import "fmt"
+
+func Example_Y() {
+       n++
+       fmt.Println(n)
+       // Output: 3
+}
+
+func Example_B() {
+       n++
+       fmt.Println(n)
+       // Output: 4
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_syntax_error_says_fail.txt b/libgo/go/cmd/go/testdata/script/test_syntax_error_says_fail.txt
new file mode 100644 (file)
index 0000000..44ff6e2
--- /dev/null
@@ -0,0 +1,25 @@
+# Test that the error message for a syntax error in a test go file
+# says FAIL.
+
+env GO111MODULE=off
+! go test syntaxerror
+stderr 'x_test.go:' # check that the error is diagnosed
+stdout 'FAIL' # check that go test says FAIL
+
+env GO111MODULE=on
+cd syntaxerror
+! go test syntaxerror
+stderr 'x_test.go:' # check that the error is diagnosed
+stdout 'FAIL' # check that go test says FAIL
+
+-- syntaxerror/go.mod --
+module syntaxerror
+
+go 1.16
+-- syntaxerror/x.go --
+package p
+-- syntaxerror/x_test.go --
+package p
+
+func f() (x.y, z int) {
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_trimpath.txt b/libgo/go/cmd/go/testdata/script/test_trimpath.txt
new file mode 100644 (file)
index 0000000..065f9ce
--- /dev/null
@@ -0,0 +1,51 @@
+[short] skip
+
+go test -trimpath -v .
+! stdout '[/\\]pkg_test[/\\]'
+stdout -count=3 '[/\\]pkg[/\\]'
+
+-- go.mod --
+module example.com/pkg
+
+go 1.17
+
+-- pkg.go --
+package pkg
+
+import "runtime"
+
+func PrintFile() {
+       _, file, _, _ := runtime.Caller(0)
+       println(file)
+}
+
+-- pkg_test.go --
+package pkg
+
+import "runtime"
+
+func PrintFileForTest() {
+       _, file, _, _ := runtime.Caller(0)
+       println(file)
+}
+
+-- pkg_x_test.go --
+package pkg_test
+
+import (
+       "runtime"
+       "testing"
+
+       "example.com/pkg"
+)
+
+func TestMain(m *testing.M) {
+       pkg.PrintFile()
+       pkg.PrintFileForTest()
+       PrintFileInXTest()
+}
+
+func PrintFileInXTest() {
+       _, file, _, _ := runtime.Caller(0)
+       println(file)
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_trimpath_main.txt b/libgo/go/cmd/go/testdata/script/test_trimpath_main.txt
new file mode 100644 (file)
index 0000000..c076212
--- /dev/null
@@ -0,0 +1,38 @@
+[short] skip
+
+go test -trimpath -v .
+! stdout '[/\\]pkg_test[/\\]'
+stdout -count=2 '[/\\]pkg[/\\]'
+
+-- go.mod --
+module example.com/pkg
+
+go 1.17
+
+-- main.go --
+package main
+
+import "runtime"
+
+func PrintFile() {
+       _, file, _, _ := runtime.Caller(0)
+       println(file)
+}
+
+-- main_test.go --
+package main
+
+import (
+       "runtime"
+       "testing"
+)
+
+func PrintFileForTest() {
+       _, file, _, _ := runtime.Caller(0)
+       println(file)
+}
+
+func TestMain(m *testing.M) {
+       PrintFile()
+       PrintFileForTest()
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_trimpath_test_suffix.txt b/libgo/go/cmd/go/testdata/script/test_trimpath_test_suffix.txt
new file mode 100644 (file)
index 0000000..6cbad83
--- /dev/null
@@ -0,0 +1,40 @@
+[short] skip
+
+go test -trimpath -v .
+! stdout '[/\\]pkg_test_test[/\\]'
+stdout -count=2 '[/\\]pkg_test[/\\]'
+
+-- go.mod --
+module example.com/pkg_test
+
+go 1.17
+
+-- pkg.go --
+package pkg_test
+
+import "runtime"
+
+func PrintFile() {
+       _, file, _, _ := runtime.Caller(0)
+       println(file)
+}
+
+-- pkg_x_test.go --
+package pkg_test_test
+
+import (
+       "runtime"
+       "testing"
+
+       "example.com/pkg_test"
+)
+
+func PrintFileForTest() {
+       _, file, _, _ := runtime.Caller(0)
+       println(file)
+}
+
+func TestMain(m *testing.M) {
+       pkg_test.PrintFile()
+       PrintFileForTest()
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_vendor.txt b/libgo/go/cmd/go/testdata/script/test_vendor.txt
new file mode 100644 (file)
index 0000000..c67c847
--- /dev/null
@@ -0,0 +1,57 @@
+# In GOPATH mode, vendored packages can replace std packages.
+env GO111MODULE=off
+cd vend/hello
+go test -v
+stdout TestMsgInternal
+stdout TestMsgExternal
+
+# In module mode, they cannot.
+env GO111MODULE=on
+! go test -mod=vendor
+stderr 'undefined.*strings.Msg'
+
+-- vend/hello/go.mod --
+module vend/hello
+
+go 1.16
+-- vend/hello/hello.go --
+package main
+
+import (
+       "fmt"
+       "strings" // really ../vendor/strings
+)
+
+func main() {
+       fmt.Printf("%s\n", strings.Msg)
+}
+-- vend/hello/hello_test.go --
+package main
+
+import (
+       "strings" // really ../vendor/strings
+       "testing"
+)
+
+func TestMsgInternal(t *testing.T) {
+       if strings.Msg != "hello, world" {
+               t.Fatalf("unexpected msg: %v", strings.Msg)
+       }
+}
+-- vend/hello/hellox_test.go --
+package main_test
+
+import (
+       "strings" // really ../vendor/strings
+       "testing"
+)
+
+func TestMsgExternal(t *testing.T) {
+       if strings.Msg != "hello, world" {
+               t.Fatalf("unexpected msg: %v", strings.Msg)
+       }
+}
+-- vend/vendor/strings/msg.go --
+package strings
+
+var Msg = "hello, world"
diff --git a/libgo/go/cmd/go/testdata/script/test_vet.txt b/libgo/go/cmd/go/testdata/script/test_vet.txt
new file mode 100644 (file)
index 0000000..5af26b5
--- /dev/null
@@ -0,0 +1,92 @@
+[short] skip
+
+# Test file
+! go test p1_test.go
+stderr 'Logf format %d'
+go test -vet=off
+stdout '^ok'
+
+# Non-test file
+! go test p1.go
+stderr 'Printf format %d'
+go test -x -vet=shift p1.go
+stderr '[\\/]vet.*-shift'
+stdout '\[no test files\]'
+go test -vet=off p1.go
+! stderr '[\\/]vet.*-shift'
+stdout '\[no test files\]'
+
+# Test issue #22890
+go test m/vetcycle
+stdout 'm/vetcycle.*\[no test files\]'
+
+# Test with ...
+! go test ./vetfail/...
+stderr 'Printf format %d'
+stdout 'ok\s+m/vetfail/p2'
+
+# Check there's no diagnosis of a bad build constraint in vetxonly mode.
+# Use -a so that we need to recompute the vet-specific export data for
+# vetfail/p1.
+go test -a m/vetfail/p2
+! stderr 'invalid.*constraint'
+
+-- go.mod --
+module m
+
+go 1.16
+-- p1_test.go --
+package p
+
+import "testing"
+
+func Test(t *testing.T) {
+       t.Logf("%d") // oops
+}
+-- p1.go --
+package p
+
+import "fmt"
+
+func F() {
+       fmt.Printf("%d") // oops
+}
+-- vetcycle/p.go --
+package p
+
+type (
+       _  interface{ m(B1) }
+       A1 interface{ a(D1) }
+       B1 interface{ A1 }
+       C1 interface {
+               B1 /* ERROR issue #18395 */
+       }
+       D1 interface{ C1 }
+)
+
+var _ A1 = C1 /* ERROR cannot use C1 */ (nil)
+-- vetfail/p1/p1.go --
+// +build !foo-bar
+
+package p1
+
+import "fmt"
+
+func F() {
+       fmt.Printf("%d", "hello") // causes vet error
+}
+-- vetfail/p2/p2.go --
+package p2
+
+import _ "m/vetfail/p1"
+
+func F() {
+}
+-- vetfail/p2/p2_test.go --
+package p2
+
+import "testing"
+
+func TestF(t *testing.T) {
+       F()
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_write_profiles_on_timeout.txt b/libgo/go/cmd/go/testdata/script/test_write_profiles_on_timeout.txt
new file mode 100644 (file)
index 0000000..0db183f
--- /dev/null
@@ -0,0 +1,26 @@
+# Tests issue 19394
+
+[short] skip
+
+! go test -cpuprofile cpu.pprof -memprofile mem.pprof -timeout 1ms
+stdout '^panic: test timed out'
+grep . cpu.pprof
+grep . mem.pprof
+
+-- go.mod --
+module profiling
+
+go 1.16
+-- timeout_test.go --
+package timeouttest_test
+
+import (
+       "testing"
+       "time"
+)
+
+func TestSleep(t *testing.T) {
+       for {
+               time.Sleep(1 * time.Second)
+       }
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_xtestonly_works.txt b/libgo/go/cmd/go/testdata/script/test_xtestonly_works.txt
new file mode 100644 (file)
index 0000000..8e150db
--- /dev/null
@@ -0,0 +1,27 @@
+[short] skip
+
+go test xtestonly
+! stdout '^ok.*\[no tests to run\]'
+stdout '^ok'
+
+-- go.mod --
+module xtestonly
+
+go 1.16
+-- f.go --
+package xtestonly
+
+func F() int { return 42 }
+-- f_test.go --
+package xtestonly_test
+
+import (
+       "testing"
+       "xtestonly"
+)
+
+func TestF(t *testing.T) {
+       if x := xtestonly.F(); x != 42 {
+               t.Errorf("f.F() = %d, want 42", x)
+       }
+}
diff --git a/libgo/go/cmd/go/testdata/script/testing_issue40908.txt b/libgo/go/cmd/go/testdata/script/testing_issue40908.txt
new file mode 100644 (file)
index 0000000..839320e
--- /dev/null
@@ -0,0 +1,25 @@
+[short] skip
+[!race] skip
+
+go test -race testrace
+
+-- go.mod --
+module testrace
+
+go 1.16
+-- race_test.go --
+package testrace
+
+import "testing"
+
+func TestRace(t *testing.T) {
+       helperDone := make(chan struct{})
+       go func() {
+               t.Logf("Something happened before cleanup.")
+               close(helperDone)
+       }()
+
+       t.Cleanup(func() {
+               <-helperDone
+       })
+}
diff --git a/libgo/go/cmd/go/testdata/script/toolexec.txt b/libgo/go/cmd/go/testdata/script/toolexec.txt
new file mode 100644 (file)
index 0000000..bb86467
--- /dev/null
@@ -0,0 +1,128 @@
+[short] skip
+
+# Build our simple toolexec program.
+go build ./cmd/mytool
+
+# Use an ephemeral build cache so that our toolexec output is not cached
+# for any stale standard-library dependencies.
+#
+# TODO(#27628): This should not be necessary.
+env GOCACHE=$WORK/gocache
+
+# Build the main package with our toolexec program. For each action, it will
+# print the tool's name and the TOOLEXEC_IMPORTPATH value. We expect to compile
+# each package once, and link the main package once.
+# Don't check the entire output at once, because the order in which the tools
+# are run is irrelevant here.
+# Finally, note that asm and cgo are run twice.
+
+go build -toolexec=$PWD/mytool
+[amd64] stderr -count=2 '^asm'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main/withasm"$'
+stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main/withasm"$'
+[cgo] stderr -count=2 '^cgo'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main/withcgo"$'
+[cgo] stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main/withcgo"$'
+stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main"$'
+stderr -count=1 '^link'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main"$'
+
+# Test packages are a little bit trickier.
+# We have four variants of test/main, as reported by 'go list -test':
+#
+#    test/main                        - the regular non-test package
+#    test/main.test                   - the generated test program
+#    test/main [test/main.test]       - the test package for foo_test.go
+#    test/main_test [test/main.test]  - the test package for foo_separate_test.go
+#
+# As such, TOOLEXEC_IMPORTPATH must see the same strings, to be able to uniquely
+# identify each package being built as reported by 'go list -f {{.ImportPath}}'.
+# Note that these are not really "import paths" anymore, but that naming is
+# consistent with 'go list -json' at least.
+
+go test -toolexec=$PWD/mytool
+
+stderr -count=2 '^# test/main\.test$'
+stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main\.test"$'
+stderr -count=1 '^link'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main\.test"$'
+
+stderr -count=1 '^# test/main \[test/main\.test\]$'
+stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main \[test/main\.test\]"$'
+
+stderr -count=1 '^# test/main_test \[test/main\.test\]$'
+stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main_test \[test/main\.test\]"$'
+
+-- go.mod --
+module test/main
+-- foo.go --
+// Simple package so we can test a program build with -toolexec.
+// With a dummy import, to test different TOOLEXEC_IMPORTPATH values.
+// Includes dummy uses of cgo and asm, to cover those tools as well.
+package main
+
+import (
+       _ "test/main/withasm"
+       _ "test/main/withcgo"
+)
+
+func main() {}
+-- foo_test.go --
+package main
+
+import "testing"
+
+func TestFoo(t *testing.T) {}
+-- foo_separate_test.go --
+package main_test
+
+import "testing"
+
+func TestSeparateFoo(t *testing.T) {}
+-- withcgo/withcgo.go --
+package withcgo
+
+// int fortytwo()
+// {
+//     return 42;
+// }
+import "C"
+-- withcgo/stub.go --
+package withcgo
+
+// Stub file to ensure we build without cgo too.
+-- withasm/withasm.go --
+package withasm
+
+// Note that we don't need to declare the Add func at all.
+-- withasm/withasm_amd64.s --
+TEXT ·Add(SB),$0-24
+       MOVQ a+0(FP), AX
+       ADDQ b+8(FP), AX
+       MOVQ AX, ret+16(FP)
+       RET
+-- cmd/mytool/main.go --
+package main
+
+import (
+       "fmt"
+       "os"
+       "os/exec"
+       "path/filepath"
+)
+
+func main() {
+       tool, args := os.Args[1], os.Args[2:]
+       toolName := filepath.Base(tool)
+       if len(args) > 0 && args[0] == "-V=full" {
+               // We can't alter the version output.
+       } else {
+               // Print which tool we're running, and on what package.
+               fmt.Fprintf(os.Stdout, "%s TOOLEXEC_IMPORTPATH=%q\n", toolName, os.Getenv("TOOLEXEC_IMPORTPATH"))
+       }
+
+       // Simply run the tool.
+       cmd := exec.Command(tool, args...)
+       cmd.Stdout = os.Stdout
+       cmd.Stderr = os.Stderr
+       if err := cmd.Run(); err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+}
diff --git a/libgo/go/cmd/go/testdata/script/vendor_gopath_issue11409.txt b/libgo/go/cmd/go/testdata/script/vendor_gopath_issue11409.txt
new file mode 100644 (file)
index 0000000..da52f9a
--- /dev/null
@@ -0,0 +1,52 @@
+[!windows] [short] stop 'this test only applies to Windows'
+env GO111MODULE=off
+
+go build run_go.go
+exec ./run_go$GOEXE $GOPATH $GOPATH/src/vend/hello
+stdout 'hello, world'
+
+-- run_go.go --
+package main
+
+import (
+       "fmt"
+       "os"
+       "os/exec"
+       "path/filepath"
+       "strings"
+)
+
+func changeVolume(s string, f func(s string) string) string {
+       vol := filepath.VolumeName(s)
+       return f(vol) + s[len(vol):]
+}
+
+func main() {
+       gopath := changeVolume(os.Args[1], strings.ToLower)
+       dir := changeVolume(os.Args[2], strings.ToUpper)
+       cmd := exec.Command("go", "run", "hello.go")
+       cmd.Dir = dir
+       cmd.Env = append(os.Environ(), "GOPATH="+gopath)
+       cmd.Stdout = os.Stdout
+       cmd.Stderr = os.Stderr
+       if err := cmd.Run(); err != nil {
+               fmt.Fprintln(os.Stderr, err)
+               os.Exit(1)
+       }
+}
+
+-- vend/hello/hello.go --
+package main
+
+import (
+       "fmt"
+       "strings" // really ../vendor/strings
+)
+
+func main() {
+       fmt.Printf("%s\n", strings.Msg)
+}
+-- vend/vendor/strings/msg.go --
+package strings
+
+var Msg = "hello, world"
diff --git a/libgo/go/cmd/go/testdata/script/vendor_import.txt b/libgo/go/cmd/go/testdata/script/vendor_import.txt
new file mode 100644 (file)
index 0000000..df4c27d
--- /dev/null
@@ -0,0 +1,104 @@
+# Imports
+env GO111MODULE=off
+go list -f  '{{.ImportPath}} {{.Imports}}' 'vend/...' 'vend/vendor/...' 'vend/x/vendor/...'
+cmp stdout want_vendor_imports.txt
+
+-- want_vendor_imports.txt --
+vend [vend/vendor/p r]
+vend/dir1 []
+vend/hello [fmt vend/vendor/strings]
+vend/subdir [vend/vendor/p r]
+vend/x [vend/x/vendor/p vend/vendor/q vend/x/vendor/r vend/dir1 vend/vendor/vend/dir1/dir2]
+vend/x/invalid [vend/x/invalid/vendor/foo]
+vend/vendor/p []
+vend/vendor/q []
+vend/vendor/strings []
+vend/vendor/vend/dir1/dir2 []
+vend/x/vendor/p []
+vend/x/vendor/p/p [notfound]
+vend/x/vendor/r []
+-- vend/bad.go --
+package vend
+
+import _ "r"
+-- vend/dir1/dir1.go --
+package dir1
+-- vend/good.go --
+package vend
+
+import _ "p"
+-- vend/hello/hello.go --
+package main
+
+import (
+       "fmt"
+       "strings" // really ../vendor/strings
+)
+
+func main() {
+       fmt.Printf("%s\n", strings.Msg)
+}
+-- vend/hello/hello_test.go --
+package main
+
+import (
+       "strings" // really ../vendor/strings
+       "testing"
+)
+
+func TestMsgInternal(t *testing.T) {
+       if strings.Msg != "hello, world" {
+               t.Fatalf("unexpected msg: %v", strings.Msg)
+       }
+}
+-- vend/hello/hellox_test.go --
+package main_test
+
+import (
+       "strings" // really ../vendor/strings
+       "testing"
+)
+
+func TestMsgExternal(t *testing.T) {
+       if strings.Msg != "hello, world" {
+               t.Fatalf("unexpected msg: %v", strings.Msg)
+       }
+}
+-- vend/subdir/bad.go --
+package subdir
+
+import _ "r"
+-- vend/subdir/good.go --
+package subdir
+
+import _ "p"
+-- vend/vendor/p/p.go --
+package p
+-- vend/vendor/q/q.go --
+package q
+-- vend/vendor/strings/msg.go --
+package strings
+
+var Msg = "hello, world"
+-- vend/vendor/vend/dir1/dir2/dir2.go --
+package dir2
+-- vend/x/invalid/invalid.go --
+package invalid
+
+import "vend/x/invalid/vendor/foo"
+-- vend/x/vendor/p/p/p.go --
+package p
+
+import _ "notfound"
+-- vend/x/vendor/p/p.go --
+package p
+-- vend/x/vendor/r/r.go --
+package r
+-- vend/x/x.go --
+package x
+
+import _ "p"
+import _ "q"
+import _ "r"
+import _ "vend/dir1"      // not vendored
+import _ "vend/dir1/dir2" // vendored
diff --git a/libgo/go/cmd/go/testdata/script/vendor_import_missing.txt b/libgo/go/cmd/go/testdata/script/vendor_import_missing.txt
new file mode 100644 (file)
index 0000000..8e50dfe
--- /dev/null
@@ -0,0 +1,7 @@
+# Missing package error message
+! go build vend/x/vendor/p/p
+
+-- vend/x/vendor/p/p/p.go --
+package p
+
+import _ "notfound"
diff --git a/libgo/go/cmd/go/testdata/script/vendor_import_wrong.txt b/libgo/go/cmd/go/testdata/script/vendor_import_wrong.txt
new file mode 100644 (file)
index 0000000..73bf595
--- /dev/null
@@ -0,0 +1,20 @@
+# Wrong import path
+env GO111MODULE=off
+! go build vend/x/invalid
+stderr 'must be imported as foo'
+
+env GO111MODULE=
+cd vend/x/invalid
+! go build vend/x/invalid
+stderr 'must be imported as foo'
+
+-- vend/x/invalid/go.mod --
+module vend/x/invalid
+
+go 1.16
+
+-- vend/x/invalid/invalid.go --
+package invalid
+
+import "vend/x/invalid/vendor/foo"
+
diff --git a/libgo/go/cmd/go/testdata/script/vendor_issue12156.txt b/libgo/go/cmd/go/testdata/script/vendor_issue12156.txt
new file mode 100644 (file)
index 0000000..ac95c6d
--- /dev/null
@@ -0,0 +1,16 @@
+# Tests issue #12156, a former index out of range panic.
+
+env GO111MODULE=off
+env GOPATH=$WORK/gopath/src/testvendor2 # vendor/x is directly in $GOPATH, not in $GOPATH/src
+cd $WORK/gopath/src/testvendor2/src/p
+
+! go build p.go
+! stderr panic # Make sure it doesn't panic
+stderr 'cannot find package "x"'
+
+-- testvendor2/src/p/p.go --
+package p
+
+import "x"
+-- testvendor2/vendor/x/x.go --
+package x
diff --git a/libgo/go/cmd/go/testdata/script/vendor_list_issue11977.txt b/libgo/go/cmd/go/testdata/script/vendor_list_issue11977.txt
new file mode 100644 (file)
index 0000000..ce2e29f
--- /dev/null
@@ -0,0 +1,17 @@
+[!net] skip
+[!exec:git] skip
+env GO111MODULE=off
+
+go get -d github.com/rsc/go-get-issue-11864
+
+go list -f '{{join .TestImports "\n"}}' github.com/rsc/go-get-issue-11864/t
+stdout 'go-get-issue-11864/vendor/vendor.org/p'
+
+go list -f '{{join .XTestImports "\n"}}' github.com/rsc/go-get-issue-11864/tx
+stdout 'go-get-issue-11864/vendor/vendor.org/p'
+
+go list -f '{{join .XTestImports "\n"}}' github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2
+stdout 'go-get-issue-11864/vendor/vendor.org/tx2'
+
+go list -f '{{join .XTestImports "\n"}}' github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx3
+stdout 'go-get-issue-11864/vendor/vendor.org/tx3'
diff --git a/libgo/go/cmd/go/testdata/script/vendor_resolve.txt b/libgo/go/cmd/go/testdata/script/vendor_resolve.txt
new file mode 100644 (file)
index 0000000..bc8cf0a
--- /dev/null
@@ -0,0 +1,21 @@
+env GO111MODULE=off
+! go build p
+stderr 'must be imported as x'
+
+-- p/p.go --
+package p
+
+import (
+       _ "q/y"
+       _ "q/z"
+)
+-- q/vendor/x/x.go --
+package x
+-- q/y/y.go --
+package y
+
+import _ "x"
+-- q/z/z.go --
+package z
+
+import _ "q/vendor/x"
diff --git a/libgo/go/cmd/go/testdata/script/vendor_test_issue11864.txt b/libgo/go/cmd/go/testdata/script/vendor_test_issue11864.txt
new file mode 100644 (file)
index 0000000..cfb43bf
--- /dev/null
@@ -0,0 +1,20 @@
+[!net] skip
+[!exec:git] skip
+env GO111MODULE=off
+
+go get github.com/rsc/go-get-issue-11864
+
+# build -i should work
+go build -i github.com/rsc/go-get-issue-11864
+go build -i github.com/rsc/go-get-issue-11864/t
+
+# test -i should work like build -i (golang.org/issue/11988)
+go test -i github.com/rsc/go-get-issue-11864
+go test -i github.com/rsc/go-get-issue-11864/t
+
+# test should work too
+go test github.com/rsc/go-get-issue-11864
+go test github.com/rsc/go-get-issue-11864/t
+
+# external tests should observe internal test exports (golang.org/issue/11977)
+go test github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2
diff --git a/libgo/go/cmd/go/testdata/script/vendor_test_issue14613.txt b/libgo/go/cmd/go/testdata/script/vendor_test_issue14613.txt
new file mode 100644 (file)
index 0000000..cfd7e58
--- /dev/null
@@ -0,0 +1,22 @@
+[!net] skip
+[!exec:git] skip
+env GO111MODULE=off
+
+cd $GOPATH
+
+go get github.com/clsung/go-vendor-issue-14613
+go build -o $WORK/a.out -i github.com/clsung/go-vendor-issue-14613
+
+# test folder should work
+go test -i github.com/clsung/go-vendor-issue-14613
+go test github.com/clsung/go-vendor-issue-14613
+
+# test with specified _test.go should work too
+cd $GOPATH/src
+go test -i github.com/clsung/go-vendor-issue-14613/vendor_test.go
+go test github.com/clsung/go-vendor-issue-14613/vendor_test.go
+
+# test with imported and not used
+go test -i github.com/clsung/go-vendor-issue-14613/vendor/mylibtesttest/myapp/myapp_test.go
+! go test github.com/clsung/go-vendor-issue-14613/vendor/mylibtesttest/myapp/myapp_test.go
+stderr 'imported and not used'
diff --git a/libgo/go/cmd/go/testdata/script/version_goexperiment.txt b/libgo/go/cmd/go/testdata/script/version_goexperiment.txt
new file mode 100644 (file)
index 0000000..4b165eb
--- /dev/null
@@ -0,0 +1,16 @@
+# Test that experiments appear in "go version <binary>"
+
+# This test requires rebuilding the runtime, which takes a while.
+[short] skip
+
+env GOEXPERIMENT=fieldtrack
+go build -o main$GOEXE version.go
+go version main$GOEXE
+stdout 'X:fieldtrack$'
+exec ./main$GOEXE
+stderr 'X:fieldtrack$'
+
+-- version.go --
+package main
+import "runtime"
+func main() { println(runtime.Version()) }
diff --git a/libgo/go/cmd/go/testdata/script/version_replace.txt b/libgo/go/cmd/go/testdata/script/version_replace.txt
new file mode 100644 (file)
index 0000000..ec98f4e
--- /dev/null
@@ -0,0 +1,33 @@
+[short] skip
+
+go mod download example.com/printversion@v0.1.0 example.com/printversion@v1.0.0
+go get -d example.com/printversion@v0.1.0
+go install example.com/printversion
+
+go run example.com/printversion
+cmp stdout out.txt
+
+go version -m $GOPATH/bin/printversion$GOEXE
+stdout '^.*[/\\]bin[/\\]printversion'$GOEXE': .*$'
+stdout '^      path    example.com/printversion$'
+stdout '^      mod     example.com/printversion        v0.1.0$'
+stdout '^      =>      example.com/printversion        v1.0.0  h1:.*$'
+stdout '^      dep     example.com/version     v1.0.0$'
+stdout '^      =>      example.com/version     v1.0.1  h1:.*$'
+
+-- go.mod --
+module golang.org/issue/37392
+go 1.14
+require (
+       example.com/printversion v0.1.0
+)
+replace (
+       example.com/printversion => example.com/printversion v1.0.0
+       example.com/version v1.0.0 => example.com/version v1.0.1
+)
+-- out.txt --
+path is example.com/printversion
+main is example.com/printversion v0.1.0
+       (replaced by example.com/printversion v1.0.0)
+using example.com/version v1.0.0
+       (replaced by example.com/version v1.0.1)
diff --git a/libgo/go/cmd/go/testdata/script/vet.txt b/libgo/go/cmd/go/testdata/script/vet.txt
new file mode 100644 (file)
index 0000000..6573ae3
--- /dev/null
@@ -0,0 +1,62 @@
+# Package with external tests
+! go vet m/vetpkg
+stderr 'Printf'
+
+# With tags
+! go vet -tags tagtest m/vetpkg
+stderr 'c\.go.*Printf'
+
+# With flags on
+! go vet -printf m/vetpkg
+stderr 'Printf'
+
+# With flags off
+go vet -printf=false m/vetpkg
+! stderr .
+
+# With only test files (tests issue #23395)
+go vet m/onlytest
+! stderr .
+
+# With only cgo files (tests issue #24193)
+[!cgo] skip
+[short] skip
+go vet m/onlycgo
+! stderr .
+
+-- go.mod --
+module m
+
+go 1.16
+-- vetpkg/a_test.go --
+package p_test
+-- vetpkg/b.go --
+package p
+
+import "fmt"
+
+func f() {
+       fmt.Printf("%d")
+}
+-- vetpkg/c.go --
+// +build tagtest
+
+package p
+
+import "fmt"
+
+func g() {
+       fmt.Printf("%d", 3, 4)
+}
+-- onlytest/p_test.go --
+package p
+
+import "testing"
+
+func TestMe(*testing.T) {}
+-- onlycgo/p.go --
+package p
+
+import "C"
+
+func F() {}
diff --git a/libgo/go/cmd/go/testdata/script/vet_internal.txt b/libgo/go/cmd/go/testdata/script/vet_internal.txt
new file mode 100644 (file)
index 0000000..85f7093
--- /dev/null
@@ -0,0 +1,71 @@
+env GO111MODULE=off
+
+# Issue 36173. Verify that "go vet" prints line numbers on load errors.
+
+! go vet a/a.go
+stderr '^package command-line-arguments\n\ta[/\\]a.go:5:3: use of internal package'
+
+! go vet a/a_test.go
+stderr '^package command-line-arguments \(test\)\n\ta[/\\]a_test.go:4:3: use of internal package'
+
+! go vet a
+stderr '^package a\n\ta[/\\]a.go:5:3: use of internal package'
+
+go vet b/b.go
+! stderr 'use of internal package'
+
+! go vet b/b_test.go
+stderr '^package command-line-arguments \(test\)\n\tb[/\\]b_test.go:4:3: use of internal package'
+
+! go vet depends-on-a/depends-on-a.go
+stderr '^package command-line-arguments\n\timports a\n\ta[/\\]a.go:5:3: use of internal package'
+
+! go vet depends-on-a/depends-on-a_test.go
+stderr '^package command-line-arguments \(test\)\n\timports a\n\ta[/\\]a.go:5:3: use of internal package a/x/internal/y not allowed'
+
+! go vet depends-on-a
+stderr '^package depends-on-a\n\timports a\n\ta[/\\]a.go:5:3: use of internal package'
+
+-- a/a.go --
+// A package with bad imports in both src and test
+package a
+
+import (
+  _ "a/x/internal/y"
+)
+
+-- a/a_test.go --
+package a
+
+import (
+  _ "a/x/internal/y"
+)
+
+-- b/b.go --
+// A package with a bad import in test only
+package b
+
+-- b/b_test.go --
+package b
+
+import (
+  _ "a/x/internal/y"
+)
+
+-- depends-on-a/depends-on-a.go --
+// A package that depends on a package with a bad import
+package depends
+
+import (
+  _ "a"
+)
+
+-- depends-on-a/depends-on-a_test.go --
+package depends
+
+import (
+  _ "a"
+)
+
+-- a/x/internal/y/y.go --
+package y
index 2793c2c2a43f0891f9d91c0cdb94515c72572e50..b3c120daab42c41c824c91f6bd901b3eeda25a0c 100644 (file)
@@ -151,7 +151,7 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error
                        if err != nil {
                                return fmt.Errorf("computing diff: %s", err)
                        }
-                       fmt.Printf("diff -u %s %s\n", filepath.ToSlash(filename+".orig"), filepath.ToSlash(filename))
+                       fmt.Fprintf(out, "diff -u %s %s\n", filepath.ToSlash(filename+".orig"), filepath.ToSlash(filename))
                        out.Write(data)
                }
        }
@@ -164,21 +164,15 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error
 }
 
 func visitFile(path string, f fs.DirEntry, err error) error {
-       if err == nil && isGoFile(f) {
-               err = processFile(path, nil, os.Stdout, false)
+       if err != nil || !isGoFile(f) {
+               return err
        }
-       // Don't complain if a file was deleted in the meantime (i.e.
-       // the directory changed concurrently while running gofmt).
-       if err != nil && !os.IsNotExist(err) {
+       if err := processFile(path, nil, os.Stdout, false); err != nil {
                report(err)
        }
        return nil
 }
 
-func walkDir(path string) {
-       filepath.WalkDir(path, visitFile)
-}
-
 func main() {
        // call gofmtMain in a separate function
        // so that it can use defer and have them
@@ -206,7 +200,8 @@ func gofmtMain() {
        initParserMode()
        initRewrite()
 
-       if flag.NArg() == 0 {
+       args := flag.Args()
+       if len(args) == 0 {
                if *write {
                        fmt.Fprintln(os.Stderr, "error: cannot use -w with standard input")
                        exitCode = 2
@@ -218,15 +213,18 @@ func gofmtMain() {
                return
        }
 
-       for i := 0; i < flag.NArg(); i++ {
-               path := flag.Arg(i)
-               switch dir, err := os.Stat(path); {
+       for _, arg := range args {
+               switch info, err := os.Stat(arg); {
                case err != nil:
                        report(err)
-               case dir.IsDir():
-                       walkDir(path)
+               case !info.IsDir():
+                       // Non-directory arguments are always formatted.
+                       if err := processFile(arg, nil, os.Stdout, false); err != nil {
+                               report(err)
+                       }
                default:
-                       if err := processFile(path, nil, os.Stdout, false); err != nil {
+                       // Directories are walked, ignoring non-Go files.
+                       if err := filepath.WalkDir(arg, visitFile); err != nil {
                                report(err)
                        }
                }
index bf2adfe64c52b1ef9362cd803cb04473b8ce0dae..f0d3f8780f40e135f2e86f8d21e1feb61dbfecbd 100644 (file)
@@ -49,12 +49,13 @@ func gofmtFlags(filename string, maxLines int) string {
                case scanner.EOF:
                        return ""
                }
-
        }
 
        return ""
 }
 
+var typeParamsEnabled = false
+
 func runTest(t *testing.T, in, out string) {
        // process flags
        *simplifyAST = false
@@ -77,6 +78,11 @@ func runTest(t *testing.T, in, out string) {
                case "-stdin":
                        // fake flag - pretend input is from stdin
                        stdin = true
+               case "-G":
+                       // fake flag - test is for generic code
+                       if !typeParamsEnabled {
+                               return
+                       }
                default:
                        t.Errorf("unrecognized flag name: %s", name)
                }
diff --git a/libgo/go/cmd/gofmt/gofmt_typeparams_test.go b/libgo/go/cmd/gofmt/gofmt_typeparams_test.go
new file mode 100644 (file)
index 0000000..10641a7
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build typeparams
+// +build typeparams
+
+package main
+
+func init() {
+       typeParamsEnabled = true
+}
index 3fd73f3c576b0f407ad462a550e80cdd04ea6aca..e41fc570b0894926a29ccd0736fb4199f53b0c6c 100644 (file)
@@ -8,6 +8,7 @@ import (
        "bytes"
        "flag"
        "fmt"
+       "internal/buildcfg"
        "io"
        "io/ioutil"
        "log"
@@ -91,16 +92,18 @@ func (versionFlag) Set(s string) error {
        name = name[strings.LastIndex(name, `\`)+1:]
        name = strings.TrimSuffix(name, ".exe")
 
-       // If there's an active experiment, include that,
-       // to distinguish go1.10.2 with an experiment
-       // from go1.10.2 without an experiment.
-       p := Expstring()
-       if p == DefaultExpstring() {
-               p = ""
-       }
-       sep := ""
-       if p != "" {
-               sep = " "
+       p := ""
+
+       if s == "goexperiment" {
+               // test/run.go uses this to discover the full set of
+               // experiment tags. Report everything.
+               p = " X:" + strings.Join(buildcfg.AllExperiments(), ",")
+       } else {
+               // If the enabled experiments differ from the defaults,
+               // include that difference.
+               if goexperiment := buildcfg.GOEXPERIMENT(); goexperiment != "" {
+                       p = " X:" + goexperiment
+               }
        }
 
        // The go command invokes -V=full to get a unique identifier
@@ -109,12 +112,12 @@ func (versionFlag) Set(s string) error {
        // build ID of the binary, so that if the compiler is changed and
        // rebuilt, we notice and rebuild all packages.
        if s == "full" {
-               if strings.HasPrefix(Version, "devel") {
+               if strings.HasPrefix(buildcfg.Version, "devel") {
                        p += " buildID=" + buildID
                }
        }
 
-       fmt.Printf("%s version %s%s%s\n", name, Version, sep, p)
+       fmt.Printf("%s version %s%s\n", name, buildcfg.Version, p)
        os.Exit(0)
        return nil
 }
index faa2863325d1ee79ea50da42e88edb324e2c44a2..4ff0ebe13d8dba777a742e6ac1f622a6508e933e 100644 (file)
@@ -20,6 +20,7 @@ const (
        FUNCDATA_StackObjects       = 2
        FUNCDATA_InlTree            = 3
        FUNCDATA_OpenCodedDeferInfo = 4
+       FUNCDATA_ArgInfo            = 5
 
        // ArgsSizeUnknown is set in Func.argsize to mark all functions
        // whose argument size is unknown (C vararg functions, and
index 1d098ee17251b379c354b01f840f53aef119c058..93ebd7be943205e9044d5f0fe66fb66f9bda8d82 100644 (file)
@@ -4,97 +4,90 @@
 
 package objabi
 
+import "strings"
+
+// A FuncFlag records bits about a function, passed to the runtime.
+type FuncFlag uint8
+
+// Note: This list must match the list in runtime/symtab.go.
+const (
+       FuncFlag_TOPFRAME = 1 << iota
+       FuncFlag_SPWRITE
+)
+
 // A FuncID identifies particular functions that need to be treated
 // specially by the runtime.
 // Note that in some situations involving plugins, there may be multiple
 // copies of a particular special runtime function.
-// Note: this list must match the list in runtime/symtab.go.
 type FuncID uint8
 
+// Note: this list must match the list in runtime/symtab.go.
 const (
        FuncID_normal FuncID = iota // not a special function
-       FuncID_runtime_main
+       FuncID_abort
+       FuncID_asmcgocall
+       FuncID_asyncPreempt
+       FuncID_cgocallback
+       FuncID_debugCallV2
+       FuncID_gcBgMarkWorker
        FuncID_goexit
+       FuncID_gogo
+       FuncID_gopanic
+       FuncID_handleAsyncEvent
        FuncID_jmpdefer
        FuncID_mcall
        FuncID_morestack
        FuncID_mstart
+       FuncID_panicwrap
        FuncID_rt0_go
-       FuncID_asmcgocall
-       FuncID_sigpanic
        FuncID_runfinq
-       FuncID_gcBgMarkWorker
-       FuncID_systemstack_switch
+       FuncID_runtime_main
+       FuncID_sigpanic
        FuncID_systemstack
-       FuncID_cgocallback
-       FuncID_gogo
-       FuncID_externalthreadhandler
-       FuncID_debugCallV1
-       FuncID_gopanic
-       FuncID_panicwrap
-       FuncID_handleAsyncEvent
-       FuncID_asyncPreempt
+       FuncID_systemstack_switch
        FuncID_wrapper // any autogenerated code (hash/eq algorithms, method wrappers, etc.)
 )
 
+var funcIDs = map[string]FuncID{
+       "abort":            FuncID_abort,
+       "asmcgocall":       FuncID_asmcgocall,
+       "asyncPreempt":     FuncID_asyncPreempt,
+       "cgocallback":      FuncID_cgocallback,
+       "debugCallV2":      FuncID_debugCallV2,
+       "gcBgMarkWorker":   FuncID_gcBgMarkWorker,
+       "go":               FuncID_rt0_go,
+       "goexit":           FuncID_goexit,
+       "gogo":             FuncID_gogo,
+       "gopanic":          FuncID_gopanic,
+       "handleAsyncEvent": FuncID_handleAsyncEvent,
+       "jmpdefer":         FuncID_jmpdefer,
+       "main":             FuncID_runtime_main,
+       "mcall":            FuncID_mcall,
+       "morestack":        FuncID_morestack,
+       "mstart":           FuncID_mstart,
+       "panicwrap":        FuncID_panicwrap,
+       "runfinq":          FuncID_runfinq,
+       "sigpanic":         FuncID_sigpanic,
+       "switch":           FuncID_systemstack_switch,
+       "systemstack":      FuncID_systemstack,
+
+       // Don't show in call stack but otherwise not special.
+       "deferreturn":       FuncID_wrapper,
+       "runOpenDeferFrame": FuncID_wrapper,
+       "reflectcallSave":   FuncID_wrapper,
+       "deferCallSave":     FuncID_wrapper,
+}
+
 // Get the function ID for the named function in the named file.
 // The function should be package-qualified.
 func GetFuncID(name string, isWrapper bool) FuncID {
        if isWrapper {
                return FuncID_wrapper
        }
-       switch name {
-       case "runtime.main":
-               return FuncID_runtime_main
-       case "runtime.goexit":
-               return FuncID_goexit
-       case "runtime.jmpdefer":
-               return FuncID_jmpdefer
-       case "runtime.mcall":
-               return FuncID_mcall
-       case "runtime.morestack":
-               return FuncID_morestack
-       case "runtime.mstart":
-               return FuncID_mstart
-       case "runtime.rt0_go":
-               return FuncID_rt0_go
-       case "runtime.asmcgocall":
-               return FuncID_asmcgocall
-       case "runtime.sigpanic":
-               return FuncID_sigpanic
-       case "runtime.runfinq":
-               return FuncID_runfinq
-       case "runtime.gcBgMarkWorker":
-               return FuncID_gcBgMarkWorker
-       case "runtime.systemstack_switch":
-               return FuncID_systemstack_switch
-       case "runtime.systemstack":
-               return FuncID_systemstack
-       case "runtime.cgocallback":
-               return FuncID_cgocallback
-       case "runtime.gogo":
-               return FuncID_gogo
-       case "runtime.externalthreadhandler":
-               return FuncID_externalthreadhandler
-       case "runtime.debugCallV1":
-               return FuncID_debugCallV1
-       case "runtime.gopanic":
-               return FuncID_gopanic
-       case "runtime.panicwrap":
-               return FuncID_panicwrap
-       case "runtime.handleAsyncEvent":
-               return FuncID_handleAsyncEvent
-       case "runtime.asyncPreempt":
-               return FuncID_asyncPreempt
-       case "runtime.deferreturn":
-               // Don't show in the call stack (used when invoking defer functions)
-               return FuncID_wrapper
-       case "runtime.runOpenDeferFrame":
-               // Don't show in the call stack (used when invoking defer functions)
-               return FuncID_wrapper
-       case "runtime.reflectcallSave":
-               // Don't show in the call stack (used when invoking defer functions)
-               return FuncID_wrapper
+       if strings.HasPrefix(name, "runtime.") {
+               if id, ok := funcIDs[name[len("runtime."):]]; ok {
+                       return id
+               }
        }
        return FuncID_normal
 }
index 0733b65138db50371baf7a3268d036bcc986f4f8..0b1e0bb181c4d3866d96a1a0077a1c678c942c08 100644 (file)
@@ -5,6 +5,7 @@
 package objabi
 
 import (
+       "internal/buildcfg"
        "os"
        "path/filepath"
        "strings"
@@ -38,8 +39,8 @@ func AbsFile(dir, file, rewrites string) string {
        }
 
        abs, rewritten := ApplyRewrites(abs, rewrites)
-       if !rewritten && hasPathPrefix(abs, GOROOT) {
-               abs = "$GOROOT" + abs[len(GOROOT):]
+       if !rewritten && hasPathPrefix(abs, buildcfg.GOROOT) {
+               abs = "$GOROOT" + abs[len(buildcfg.GOROOT):]
        }
 
        if abs == "" {
index fd1c9981c69d0f9b1220d7e37de1e08068d4584a..aacab9a0ca7fa920d980e5dd940a7669cf7ac61a 100644 (file)
@@ -47,6 +47,8 @@ func PathToPrefix(s string) string {
 // some cases need to be aware of when they are building such a
 // package, for example to enable features such as ABI selectors in
 // assembly sources.
+//
+// Keep in sync with cmd/dist/build.go:IsRuntimePackagePath.
 func IsRuntimePackagePath(pkgpath string) bool {
        rval := false
        switch pkgpath {
@@ -56,6 +58,8 @@ func IsRuntimePackagePath(pkgpath string) bool {
                rval = true
        case "syscall":
                rval = true
+       case "internal/bytealg":
+               rval = true
        default:
                rval = strings.HasPrefix(pkgpath, "runtime/internal")
        }
index 649f6901944f9876b4a30a6118786f4898766d60..52827a6deeec5c6a3bcc6606aef5201bdf785c12 100644 (file)
@@ -50,11 +50,6 @@ const (
        // R_ADDROFF resolves to a 32-bit offset from the beginning of the section
        // holding the data being relocated to the referenced symbol.
        R_ADDROFF
-       // R_WEAKADDROFF resolves just like R_ADDROFF but is a weak relocation.
-       // A weak relocation does not make the symbol it refers to reachable,
-       // and is only honored by the linker if the symbol is in some other way
-       // reachable.
-       R_WEAKADDROFF
        R_SIZE
        R_CALL
        R_CALLARM
@@ -106,6 +101,9 @@ const (
        // *rtype, and may be set to zero by the linker if it determines the method
        // text is unreachable by the linked program.
        R_METHODOFF
+       // R_KEEP tells the linker to keep the referred-to symbol in the final binary
+       // if the symbol containing the R_KEEP relocation is in the final binary.
+       R_KEEP
        R_POWER_TOC
        R_GOTPCREL
        // R_JMPMIPS (only used on mips64) resolves to non-PC-relative target address
@@ -172,8 +170,8 @@ const (
 
        // R_POWER_TLS_LE is used to implement the "local exec" model for tls
        // access. It resolves to the offset of the thread-local symbol from the
-       // thread pointer (R13) and inserts this value into the low 16 bits of an
-       // instruction word.
+       // thread pointer (R13) and is split against a pair of instructions to
+       // support a 32 bit displacement.
        R_POWER_TLS_LE
 
        // R_POWER_TLS_IE is used to implement the "initial exec" model for tls access. It
@@ -183,10 +181,12 @@ const (
        // symbol from the thread pointer (R13)).
        R_POWER_TLS_IE
 
-       // R_POWER_TLS marks an X-form instruction such as "MOVD 0(R13)(R31*1), g" as
-       // accessing a particular thread-local symbol. It does not affect code generation
-       // but is used by the system linker when relaxing "initial exec" model code to
-       // "local exec" model code.
+       // R_POWER_TLS marks an X-form instruction such as "ADD R3,R13,R4" as completing
+       // a sequence of GOT-relative relocations to compute a TLS address. This can be
+       // used by the system linker to to rewrite the GOT-relative TLS relocation into a
+       // simpler thread-pointer relative relocation. See table 3.26 and 3.28 in the
+       // ppc64 elfv2 1.4 ABI on this transformation.  Likewise, the second argument
+       // (usually called RB in X-form instructions) is assumed to be R13.
        R_POWER_TLS
 
        // R_ADDRPOWER_DS is similar to R_ADDRPOWER above, but assumes the second
@@ -256,6 +256,15 @@ const (
        // of a symbol. This isn't a real relocation, it can be placed in anywhere
        // in a symbol and target any symbols.
        R_XCOFFREF
+
+       // R_WEAK marks the relocation as a weak reference.
+       // A weak relocation does not make the symbol it refers to reachable,
+       // and is only honored by the linker if the symbol is in some other way
+       // reachable.
+       R_WEAK = -1 << 15
+
+       R_WEAKADDR    = R_WEAK | R_ADDR
+       R_WEAKADDROFF = R_WEAK | R_ADDROFF
 )
 
 // IsDirectCall reports whether r is a relocation for a direct call.
index 658a44f8b81bfa4bf3abefc43f4d23f5b4f46fd6..4638ef14d91f62b58be4b6e199d79432d573040b 100644 (file)
@@ -13,28 +13,28 @@ func _() {
        _ = x[R_ADDRARM64-3]
        _ = x[R_ADDRMIPS-4]
        _ = x[R_ADDROFF-5]
-       _ = x[R_WEAKADDROFF-6]
-       _ = x[R_SIZE-7]
-       _ = x[R_CALL-8]
-       _ = x[R_CALLARM-9]
-       _ = x[R_CALLARM64-10]
-       _ = x[R_CALLIND-11]
-       _ = x[R_CALLPOWER-12]
-       _ = x[R_CALLMIPS-13]
-       _ = x[R_CALLRISCV-14]
-       _ = x[R_CONST-15]
-       _ = x[R_PCREL-16]
-       _ = x[R_TLS_LE-17]
-       _ = x[R_TLS_IE-18]
-       _ = x[R_GOTOFF-19]
-       _ = x[R_PLT0-20]
-       _ = x[R_PLT1-21]
-       _ = x[R_PLT2-22]
-       _ = x[R_USEFIELD-23]
-       _ = x[R_USETYPE-24]
-       _ = x[R_USEIFACE-25]
-       _ = x[R_USEIFACEMETHOD-26]
-       _ = x[R_METHODOFF-27]
+       _ = x[R_SIZE-6]
+       _ = x[R_CALL-7]
+       _ = x[R_CALLARM-8]
+       _ = x[R_CALLARM64-9]
+       _ = x[R_CALLIND-10]
+       _ = x[R_CALLPOWER-11]
+       _ = x[R_CALLMIPS-12]
+       _ = x[R_CALLRISCV-13]
+       _ = x[R_CONST-14]
+       _ = x[R_PCREL-15]
+       _ = x[R_TLS_LE-16]
+       _ = x[R_TLS_IE-17]
+       _ = x[R_GOTOFF-18]
+       _ = x[R_PLT0-19]
+       _ = x[R_PLT1-20]
+       _ = x[R_PLT2-21]
+       _ = x[R_USEFIELD-22]
+       _ = x[R_USETYPE-23]
+       _ = x[R_USEIFACE-24]
+       _ = x[R_USEIFACEMETHOD-25]
+       _ = x[R_METHODOFF-26]
+       _ = x[R_KEEP-27]
        _ = x[R_POWER_TOC-28]
        _ = x[R_GOTPCREL-29]
        _ = x[R_JMPMIPS-30]
@@ -70,9 +70,9 @@ func _() {
        _ = x[R_XCOFFREF-60]
 }
 
-const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_WEAKADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CALLRISCVR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_METHODOFFR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IE_ITYPER_RISCV_TLS_IE_STYPER_PCRELDBLR_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREF"
+const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CALLRISCVR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_METHODOFFR_KEEPR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IE_ITYPER_RISCV_TLS_IE_STYPER_PCRELDBLR_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREF"
 
-var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 60, 66, 72, 81, 92, 101, 112, 122, 133, 140, 147, 155, 163, 171, 177, 183, 189, 199, 208, 218, 234, 245, 256, 266, 275, 288, 302, 316, 330, 346, 357, 370, 383, 397, 411, 425, 440, 454, 468, 479, 493, 508, 525, 543, 564, 583, 602, 622, 642, 652, 663, 676, 687, 699, 709}
+var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 120, 127, 134, 142, 150, 158, 164, 170, 176, 186, 195, 205, 221, 232, 238, 249, 259, 268, 281, 295, 309, 323, 339, 350, 363, 376, 390, 404, 418, 433, 447, 461, 472, 486, 501, 518, 536, 557, 576, 595, 615, 635, 645, 656, 669, 680, 692, 702}
 
 func (i RelocType) String() string {
        i -= 1
index 05a1d4a4b58caf1b36468b71e8ee9ecfa8b0ec42..0c82a7c6dd10e76285325776d3c0abdc2f6249b1 100644 (file)
@@ -4,6 +4,8 @@
 
 package objabi
 
+import "internal/buildcfg"
+
 // For the linkers. Must match Go definitions.
 
 const (
@@ -13,10 +15,6 @@ const (
        StackSmall  = 128
 )
 
-const (
-       StackPreempt = -1314 // 0xfff...fade
-)
-
 // Initialize StackGuard and StackLimit according to target system.
 var StackGuard = 928*stackGuardMultiplier() + StackSystem
 var StackLimit = StackGuard - StackSystem - StackSmall
@@ -26,7 +24,7 @@ var StackLimit = StackGuard - StackSystem - StackSmall
 // builds that have larger stack frames or for specific targets.
 func stackGuardMultiplier() int {
        // On AIX, a larger stack is needed for syscalls.
-       if GOOS == "aix" {
+       if buildcfg.GOOS == "aix" {
                return 2
        }
        return stackGuardMultiplierDefault
index d9cf4955f2ffbc691f806e92ea892642cb61d160..fcda97d515b3f711d1069149a71712f39af5d657 100644 (file)
@@ -6,196 +6,19 @@ package objabi
 
 import (
        "fmt"
-       "log"
-       "os"
+       "internal/buildcfg"
        "strings"
 )
 
-func envOr(key, value string) string {
-       if x := os.Getenv(key); x != "" {
-               return x
-       }
-       return value
-}
-
-var (
-       defaultGOROOT = defaultGOROOTValue()
-
-       GOROOT   = envOr("GOROOT", defaultGOROOT)
-       GOARCH   = envOr("GOARCH", defaultGOARCH)
-       GOOS     = envOr("GOOS", defaultGOOS)
-       GO386    = envOr("GO386", defaultGO386)
-       GOARM    = goarm()
-       GOMIPS   = gomips()
-       GOMIPS64 = gomips64()
-       GOPPC64  = goppc64()
-       GOWASM   = gowasm()
-       GO_LDSO  = defaultGO_LDSO
-       Version  = version
-)
-
 const (
        ElfRelocOffset   = 256
        MachoRelocOffset = 2048 // reserve enough space for ELF relocations
 )
 
-func goarm() int {
-       def := defaultGOARM
-       if GOOS == "android" && GOARCH == "arm" {
-               // Android arm devices always support GOARM=7.
-               def = "7"
-       }
-       switch v := envOr("GOARM", def); v {
-       case "5":
-               return 5
-       case "6":
-               return 6
-       case "7":
-               return 7
-       }
-       // Fail here, rather than validate at multiple call sites.
-       log.Fatalf("Invalid GOARM value. Must be 5, 6, or 7.")
-       panic("unreachable")
-}
-
-func gomips() string {
-       switch v := envOr("GOMIPS", defaultGOMIPS); v {
-       case "hardfloat", "softfloat":
-               return v
-       }
-       log.Fatalf("Invalid GOMIPS value. Must be hardfloat or softfloat.")
-       panic("unreachable")
-}
-
-func gomips64() string {
-       switch v := envOr("GOMIPS64", defaultGOMIPS64); v {
-       case "hardfloat", "softfloat":
-               return v
-       }
-       log.Fatalf("Invalid GOMIPS64 value. Must be hardfloat or softfloat.")
-       panic("unreachable")
-}
-
-func goppc64() int {
-       switch v := envOr("GOPPC64", defaultGOPPC64); v {
-       case "power8":
-               return 8
-       case "power9":
-               return 9
-       }
-       log.Fatalf("Invalid GOPPC64 value. Must be power8 or power9.")
-       panic("unreachable")
-}
-
-type gowasmFeatures struct {
-       SignExt bool
-       SatConv bool
-}
-
-func (f gowasmFeatures) String() string {
-       var flags []string
-       if f.SatConv {
-               flags = append(flags, "satconv")
-       }
-       if f.SignExt {
-               flags = append(flags, "signext")
-       }
-       return strings.Join(flags, ",")
-}
-
-func gowasm() (f gowasmFeatures) {
-       for _, opt := range strings.Split(envOr("GOWASM", ""), ",") {
-               switch opt {
-               case "satconv":
-                       f.SatConv = true
-               case "signext":
-                       f.SignExt = true
-               case "":
-                       // ignore
-               default:
-                       log.Fatalf("Invalid GOWASM value. No such feature: " + opt)
-               }
-       }
-       return
-}
-
-func Getgoextlinkenabled() string {
-       return envOr("GO_EXTLINK_ENABLED", defaultGO_EXTLINK_ENABLED)
-}
-
-func init() {
-       for _, f := range strings.Split(goexperiment, ",") {
-               if f != "" {
-                       addexp(f)
-               }
-       }
-
-       // regabi is only supported on amd64.
-       if GOARCH != "amd64" {
-               Regabi_enabled = 0
-       }
-}
-
-// Note: must agree with runtime.framepointer_enabled.
-var Framepointer_enabled = GOARCH == "amd64" || GOARCH == "arm64" && (GOOS == "linux" || GOOS == "darwin" || GOOS == "ios")
-
-func addexp(s string) {
-       // Could do general integer parsing here, but the runtime copy doesn't yet.
-       v := 1
-       name := s
-       if len(name) > 2 && name[:2] == "no" {
-               v = 0
-               name = name[2:]
-       }
-       for i := 0; i < len(exper); i++ {
-               if exper[i].name == name {
-                       if exper[i].val != nil {
-                               *exper[i].val = v
-                       }
-                       return
-               }
-       }
-
-       fmt.Printf("unknown experiment %s\n", s)
-       os.Exit(2)
-}
-
-var (
-       Fieldtrack_enabled        int
-       Preemptibleloops_enabled  int
-       Staticlockranking_enabled int
-       Regabi_enabled            int
-)
-
-// Toolchain experiments.
-// These are controlled by the GOEXPERIMENT environment
-// variable recorded when the toolchain is built.
-// This list is also known to cmd/gc.
-var exper = []struct {
-       name string
-       val  *int
-}{
-       {"fieldtrack", &Fieldtrack_enabled},
-       {"preemptibleloops", &Preemptibleloops_enabled},
-       {"staticlockranking", &Staticlockranking_enabled},
-       {"regabi", &Regabi_enabled},
-}
-
-var defaultExpstring = Expstring()
-
-func DefaultExpstring() string {
-       return defaultExpstring
-}
-
-func Expstring() string {
-       buf := "X"
-       for i := range exper {
-               if *exper[i].val != 0 {
-                       buf += "," + exper[i].name
-               }
-       }
-       if buf == "X" {
-               buf += ",none"
-       }
-       return "X:" + buf[2:]
+// HeaderString returns the toolchain configuration string written in
+// Go object headers. This string ensures we don't attempt to import
+// or link object files that are incompatible with each other. This
+// string always starts with "go object ".
+func HeaderString() string {
+       return fmt.Sprintf("go object %s %s %s X:%s\n", buildcfg.GOOS, buildcfg.GOARCH, buildcfg.Version, strings.Join(buildcfg.EnabledExperiments(), ","))
 }
index 60a3b3c8ecdc9ac5564f821557b56d68e54efdee..2029b7dd9e1b33121717565383622100bbba386b 100644 (file)
@@ -41,6 +41,12 @@ type Arch struct {
 
        // MinLC is the minimum length of an instruction code.
        MinLC int
+
+       // Alignment is maximum alignment required by the architecture
+       // for any (compiler-generated) load or store instruction.
+       // Loads or stores smaller than Alignment must be naturally aligned.
+       // Loads or stores larger than Alignment need only be Alignment-aligned.
+       Alignment int8
 }
 
 // InFamily reports whether a is a member of any of the specified
@@ -61,6 +67,7 @@ var Arch386 = &Arch{
        PtrSize:   4,
        RegSize:   4,
        MinLC:     1,
+       Alignment: 1,
 }
 
 var ArchAMD64 = &Arch{
@@ -70,6 +77,7 @@ var ArchAMD64 = &Arch{
        PtrSize:   8,
        RegSize:   8,
        MinLC:     1,
+       Alignment: 1,
 }
 
 var ArchARM = &Arch{
@@ -79,6 +87,7 @@ var ArchARM = &Arch{
        PtrSize:   4,
        RegSize:   4,
        MinLC:     4,
+       Alignment: 4, // TODO: just for arm5?
 }
 
 var ArchARM64 = &Arch{
@@ -88,6 +97,7 @@ var ArchARM64 = &Arch{
        PtrSize:   8,
        RegSize:   8,
        MinLC:     4,
+       Alignment: 1,
 }
 
 var ArchMIPS = &Arch{
@@ -97,6 +107,7 @@ var ArchMIPS = &Arch{
        PtrSize:   4,
        RegSize:   4,
        MinLC:     4,
+       Alignment: 4,
 }
 
 var ArchMIPSLE = &Arch{
@@ -106,6 +117,7 @@ var ArchMIPSLE = &Arch{
        PtrSize:   4,
        RegSize:   4,
        MinLC:     4,
+       Alignment: 4,
 }
 
 var ArchMIPS64 = &Arch{
@@ -115,6 +127,7 @@ var ArchMIPS64 = &Arch{
        PtrSize:   8,
        RegSize:   8,
        MinLC:     4,
+       Alignment: 8,
 }
 
 var ArchMIPS64LE = &Arch{
@@ -124,6 +137,7 @@ var ArchMIPS64LE = &Arch{
        PtrSize:   8,
        RegSize:   8,
        MinLC:     4,
+       Alignment: 8,
 }
 
 var ArchPPC64 = &Arch{
@@ -133,6 +147,7 @@ var ArchPPC64 = &Arch{
        PtrSize:   8,
        RegSize:   8,
        MinLC:     4,
+       Alignment: 1,
 }
 
 var ArchPPC64LE = &Arch{
@@ -142,6 +157,7 @@ var ArchPPC64LE = &Arch{
        PtrSize:   8,
        RegSize:   8,
        MinLC:     4,
+       Alignment: 1,
 }
 
 var ArchRISCV = &Arch{
@@ -160,6 +176,7 @@ var ArchRISCV64 = &Arch{
        PtrSize:   8,
        RegSize:   8,
        MinLC:     4,
+       Alignment: 8, // riscv unaligned loads work, but are really slow (trap + simulated by OS)
 }
 
 var ArchS390X = &Arch{
@@ -169,6 +186,7 @@ var ArchS390X = &Arch{
        PtrSize:   8,
        RegSize:   8,
        MinLC:     2,
+       Alignment: 1,
 }
 
 var ArchWasm = &Arch{
@@ -178,6 +196,7 @@ var ArchWasm = &Arch{
        PtrSize:   8,
        RegSize:   8,
        MinLC:     1,
+       Alignment: 1,
 }
 
 var Archs = [...]*Arch{
index ef7c017bd4abb37ba517dafdc2fd4f53193af97d..0d2bad961278f4392c3c27a1ecc4617ac2d9b74c 100644 (file)
@@ -15,7 +15,7 @@ func RaceDetectorSupported(goos, goarch string) bool {
                return goarch == "amd64" || goarch == "ppc64le" || goarch == "arm64"
        case "darwin":
                return goarch == "amd64" || goarch == "arm64"
-       case "freebsd", "netbsd", "windows":
+       case "freebsd", "netbsd", "openbsd", "windows":
                return goarch == "amd64"
        default:
                return false
@@ -23,7 +23,8 @@ func RaceDetectorSupported(goos, goarch string) bool {
 }
 
 // MSanSupported reports whether goos/goarch supports the memory
-// sanitizer option. There is a copy of this function in cmd/dist/test.go.
+// sanitizer option.
+// There is a copy of this function in misc/cgo/testsanitizers/cc_test.go.
 func MSanSupported(goos, goarch string) bool {
        switch goos {
        case "linux":
@@ -73,7 +74,7 @@ func BuildModeSupported(compiler, buildmode, goos, goarch string) bool {
                        "android/amd64", "android/arm", "android/arm64", "android/386",
                        "freebsd/amd64",
                        "darwin/amd64", "darwin/arm64",
-                       "windows/amd64", "windows/386":
+                       "windows/amd64", "windows/386", "windows/arm64":
                        return true
                }
                return false
index ae2c0a00cce90bcf8b8979b20600db080ec91a90..34dbdaf5dd3a74d28f40b28fb8d209ce1d6576bd 100644 (file)
@@ -1,5 +1,5 @@
-# github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2
-## explicit
+# github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a
+## explicit; go 1.14
 github.com/google/pprof/driver
 github.com/google/pprof/internal/binutils
 github.com/google/pprof/internal/driver
@@ -16,20 +16,20 @@ github.com/google/pprof/third_party/d3
 github.com/google/pprof/third_party/d3flamegraph
 github.com/google/pprof/third_party/svgpan
 # github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639
-github.com/ianlancetaylor/demangle
-# golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff
 ## explicit
+github.com/ianlancetaylor/demangle
+# golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e
+## explicit; go 1.17
 golang.org/x/arch/arm/armasm
 golang.org/x/arch/arm64/arm64asm
 golang.org/x/arch/ppc64/ppc64asm
 golang.org/x/arch/x86/x86asm
-# golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
-## explicit
+# golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e
+## explicit; go 1.17
 golang.org/x/crypto/ed25519
 golang.org/x/crypto/ed25519/internal/edwards25519
-golang.org/x/crypto/ssh/terminal
-# golang.org/x/mod v0.4.2-0.20210325185522-dbbbf8a3c6ea
-## explicit
+# golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a
+## explicit; go 1.17
 golang.org/x/mod/internal/lazyregexp
 golang.org/x/mod/modfile
 golang.org/x/mod/module
@@ -39,13 +39,18 @@ golang.org/x/mod/sumdb/dirhash
 golang.org/x/mod/sumdb/note
 golang.org/x/mod/sumdb/tlog
 golang.org/x/mod/zip
-# golang.org/x/sys v0.0.0-20201204225414-ed752295db88
-## explicit
+# golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744
+## explicit; go 1.17
 golang.org/x/sys/internal/unsafeheader
+golang.org/x/sys/plan9
 golang.org/x/sys/unix
 golang.org/x/sys/windows
-# golang.org/x/tools v0.0.0-20210107193943-4ed967dd8eff
-## explicit
+# golang.org/x/term v0.0.0-20210503060354-a79de5458b56
+## explicit; go 1.17
+golang.org/x/term
+# golang.org/x/tools v0.1.2-0.20210519160823-49064d2332f9
+## explicit; go 1.17
+golang.org/x/tools/cover
 golang.org/x/tools/go/analysis
 golang.org/x/tools/go/analysis/internal/analysisflags
 golang.org/x/tools/go/analysis/internal/facts
@@ -69,6 +74,7 @@ golang.org/x/tools/go/analysis/passes/lostcancel
 golang.org/x/tools/go/analysis/passes/nilfunc
 golang.org/x/tools/go/analysis/passes/printf
 golang.org/x/tools/go/analysis/passes/shift
+golang.org/x/tools/go/analysis/passes/sigchanyzer
 golang.org/x/tools/go/analysis/passes/stdmethods
 golang.org/x/tools/go/analysis/passes/stringintconv
 golang.org/x/tools/go/analysis/passes/structtag
@@ -87,5 +93,6 @@ golang.org/x/tools/go/types/typeutil
 golang.org/x/tools/internal/analysisinternal
 golang.org/x/tools/internal/lsp/fuzzy
 # golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
+## explicit; go 1.11
 golang.org/x/xerrors
 golang.org/x/xerrors/internal
index d50c45d691ee82fa64bb8cf110f68ed3f19c2380..7da8606eceb203bec50f60c076d7067a5fb87523 100644 (file)
@@ -1,3 +1,7 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 package main
 
 import (
@@ -22,6 +26,7 @@ import (
        "golang.org/x/tools/go/analysis/passes/nilfunc"
        "golang.org/x/tools/go/analysis/passes/printf"
        "golang.org/x/tools/go/analysis/passes/shift"
+       "golang.org/x/tools/go/analysis/passes/sigchanyzer"
        "golang.org/x/tools/go/analysis/passes/stdmethods"
        "golang.org/x/tools/go/analysis/passes/stringintconv"
        "golang.org/x/tools/go/analysis/passes/structtag"
@@ -54,6 +59,7 @@ func main() {
                nilfunc.Analyzer,
                printf.Analyzer,
                shift.Analyzer,
+               sigchanyzer.Analyzer,
                stdmethods.Analyzer,
                stringintconv.Analyzer,
                structtag.Analyzer,
index a5bb6dd0af8bbb2dc50f99315c7ac6e4996336f9..050c498d126741b141b1c6af91cd74738ef9110c 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build amd64
 // +build amd64
 
 TEXT ·arg1(SB),0,$0-2
index c2fd6aaaf2fa01deb087090a78756eabf2e365bb..7371e6ef6fd28a32c33d8cfee9706f866129c21b 100644 (file)
@@ -4,12 +4,14 @@
 
 // This file contains tests for the buildtag checker.
 
-// +builder // ERROR "possible malformed \+build comment"
+// ERRORNEXT "possible malformed [+]build comment"
+// +builder
 // +build !ignore
 
 package testdata
 
-// +build toolate // ERROR "build comment must appear before package clause and be followed by a blank line$"
+// ERRORNEXT "misplaced \+build comment"
+// +build toolate
 
 var _ = 3
 
diff --git a/libgo/go/cmd/vet/testdata/buildtag/buildtag2.go b/libgo/go/cmd/vet/testdata/buildtag/buildtag2.go
new file mode 100644 (file)
index 0000000..d8808dd
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests for the buildtag checker.
+
+// ERRORNEXT "possible malformed [+]build comment"
+// +builder
+// +build !ignore
+
+package testdata
+
+// ERRORNEXT "misplaced \+build comment"
+// +build toolate
+// ERRORNEXT "misplaced //go:build comment"
+//go:build toolate
+
+var _ = 3
+
+var _ = `
+// +build notacomment
+`
diff --git a/libgo/go/cmd/vet/testdata/buildtag/buildtag3.go b/libgo/go/cmd/vet/testdata/buildtag/buildtag3.go
new file mode 100644 (file)
index 0000000..241a7db
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests for the buildtag checker.
+
+//go:build good
+// ERRORNEXT "[+]build lines do not match //go:build condition"
+// +build bad
+
+package testdata
+
+var _ = `
+// +build notacomment
+`
diff --git a/libgo/go/cmd/vet/testdata/buildtag/buildtag4.go b/libgo/go/cmd/vet/testdata/buildtag/buildtag4.go
new file mode 100644 (file)
index 0000000..5b40d69
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests for the buildtag checker.
+
+//go:build !(bad || worse)
+// +build !bad
+// +build !worse
+
+package testdata
diff --git a/libgo/go/cmd/vet/testdata/buildtag/buildtag5.go b/libgo/go/cmd/vet/testdata/buildtag/buildtag5.go
new file mode 100644 (file)
index 0000000..12aeb82
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests for the buildtag checker.
+
+//go:build !(bad || worse)
+
+package testdata
+
+// +build other // ERROR "misplaced \+build comment"
similarity index 66%
rename from libgo/go/io/ioutil/export_test.go
rename to libgo/go/cmd/vet/testdata/buildtag/buildtag6.s
index dff55f07e26735ed81c551711db4e48503940850..40fe14c5d69afdf5193db1e30cbacde2d849d1bf 100644 (file)
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package ioutil
+#include "go_asm.h"
+
+// ok because we cannot parse assembly files.
+// +build no
 
-var ErrPatternHasSeparator = errPatternHasSeparator
diff --git a/libgo/go/cmd/vet/testdata/buildtag/buildtag7.s b/libgo/go/cmd/vet/testdata/buildtag/buildtag7.s
new file mode 100644 (file)
index 0000000..b622d48
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+#include "go_asm.h"
+
+// ok because we cannot parse assembly files
+// the assembler would complain if we did assemble this file.
+//go:build no
index 8079cf3248b785afbcf7b1097e509047e48c0a56..7cfafe64086ff2f8399a90079dd5325798a87f05 100644 (file)
@@ -1,3 +1,7 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 package copylock
 
 import "sync"
index 6141f6e06dce69cfbeaaf976b8d872bf71e1f3df..98e394a2715978823db82e8215bc10375986fb0a 100644 (file)
@@ -1,3 +1,7 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 package httpresponse
 
 import (
index 47fe3c80afe347edec1b8ed09c596997538b0e3a..2204524821605366916e945172595e8584d902b0 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build testtag
 // +build testtag
 
 package main
index 1f45efcbf2f43eeb99bb15955eb14c81f5953312..979b0d451daaa31a015ad6535e8f48832f806431 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !testtag
 // +build !testtag
 
 package main
index 69d29d3c6c65ef548cc4e2226ca19f16e072def0..8f4674d33c0ddcb08c67a84248ba0da9cabd387b 100644 (file)
@@ -1 +1,5 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 package testdata
index 09bb98d980ecd38e820d357211f454c12ba9c3d3..815dcc8a95f72a8e8cf52f991e1111eb5b2bc78b 100644 (file)
@@ -1,3 +1,7 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 package testdata
 
 func Example_BadSuffix() {} // ERROR "Example_BadSuffix has malformed example suffix: BadSuffix"
index 4c8dd3cc49632b9e28cccd3a60846ffcc8366857..4726da2ac95931217132dd572448b57a909d55cf 100644 (file)
@@ -338,8 +338,8 @@ type wantedError struct {
 }
 
 var (
-       errRx       = regexp.MustCompile(`// (?:GC_)?ERROR (.*)`)
-       errAutoRx   = regexp.MustCompile(`// (?:GC_)?ERRORAUTO (.*)`)
+       errRx       = regexp.MustCompile(`// (?:GC_)?ERROR(NEXT)? (.*)`)
+       errAutoRx   = regexp.MustCompile(`// (?:GC_)?ERRORAUTO(NEXT)? (.*)`)
        errQuotesRx = regexp.MustCompile(`"([^"]*)"`)
        lineRx      = regexp.MustCompile(`LINE(([+-])([0-9]+))?`)
 )
@@ -368,7 +368,10 @@ func wantedErrors(file, short string) (errs []wantedError) {
                if m == nil {
                        continue
                }
-               all := m[1]
+               if m[1] == "NEXT" {
+                       lineNum++
+               }
+               all := m[2]
                mm := errQuotesRx.FindAllStringSubmatch(all, -1)
                if mm == nil {
                        log.Fatalf("%s:%d: invalid errchk line: %s", file, lineNum, line)
index f08021190c2cfbb277bffe8d15d99746f8d56304..952870a56a2c9bc6d945e7e7b1560589fb805d04 100644 (file)
@@ -42,15 +42,15 @@ const (
        flushBuffer        = 1 << maxWidth
 )
 
-// decoder is the state from which the readXxx method converts a byte
-// stream into a code stream.
-type decoder struct {
+// Reader is an io.Reader which can be used to read compressed data in the
+// LZW format.
+type Reader struct {
        r        io.ByteReader
        bits     uint32
        nBits    uint
        width    uint
-       read     func(*decoder) (uint16, error) // readLSB or readMSB
-       litWidth int                            // width in bits of literal codes
+       read     func(*Reader) (uint16, error) // readLSB or readMSB
+       litWidth int                           // width in bits of literal codes
        err      error
 
        // The first 1<<litWidth codes are literal codes.
@@ -87,148 +87,158 @@ type decoder struct {
 }
 
 // readLSB returns the next code for "Least Significant Bits first" data.
-func (d *decoder) readLSB() (uint16, error) {
-       for d.nBits < d.width {
-               x, err := d.r.ReadByte()
+func (r *Reader) readLSB() (uint16, error) {
+       for r.nBits < r.width {
+               x, err := r.r.ReadByte()
                if err != nil {
                        return 0, err
                }
-               d.bits |= uint32(x) << d.nBits
-               d.nBits += 8
+               r.bits |= uint32(x) << r.nBits
+               r.nBits += 8
        }
-       code := uint16(d.bits & (1<<d.width - 1))
-       d.bits >>= d.width
-       d.nBits -= d.width
+       code := uint16(r.bits & (1<<r.width - 1))
+       r.bits >>= r.width
+       r.nBits -= r.width
        return code, nil
 }
 
 // readMSB returns the next code for "Most Significant Bits first" data.
-func (d *decoder) readMSB() (uint16, error) {
-       for d.nBits < d.width {
-               x, err := d.r.ReadByte()
+func (r *Reader) readMSB() (uint16, error) {
+       for r.nBits < r.width {
+               x, err := r.r.ReadByte()
                if err != nil {
                        return 0, err
                }
-               d.bits |= uint32(x) << (24 - d.nBits)
-               d.nBits += 8
+               r.bits |= uint32(x) << (24 - r.nBits)
+               r.nBits += 8
        }
-       code := uint16(d.bits >> (32 - d.width))
-       d.bits <<= d.width
-       d.nBits -= d.width
+       code := uint16(r.bits >> (32 - r.width))
+       r.bits <<= r.width
+       r.nBits -= r.width
        return code, nil
 }
 
-func (d *decoder) Read(b []byte) (int, error) {
+// Read implements io.Reader, reading uncompressed bytes from its underlying Reader.
+func (r *Reader) Read(b []byte) (int, error) {
        for {
-               if len(d.toRead) > 0 {
-                       n := copy(b, d.toRead)
-                       d.toRead = d.toRead[n:]
+               if len(r.toRead) > 0 {
+                       n := copy(b, r.toRead)
+                       r.toRead = r.toRead[n:]
                        return n, nil
                }
-               if d.err != nil {
-                       return 0, d.err
+               if r.err != nil {
+                       return 0, r.err
                }
-               d.decode()
+               r.decode()
        }
 }
 
 // decode decompresses bytes from r and leaves them in d.toRead.
 // read specifies how to decode bytes into codes.
 // litWidth is the width in bits of literal codes.
-func (d *decoder) decode() {
+func (r *Reader) decode() {
        // Loop over the code stream, converting codes into decompressed bytes.
 loop:
        for {
-               code, err := d.read(d)
+               code, err := r.read(r)
                if err != nil {
                        if err == io.EOF {
                                err = io.ErrUnexpectedEOF
                        }
-                       d.err = err
+                       r.err = err
                        break
                }
                switch {
-               case code < d.clear:
+               case code < r.clear:
                        // We have a literal code.
-                       d.output[d.o] = uint8(code)
-                       d.o++
-                       if d.last != decoderInvalidCode {
+                       r.output[r.o] = uint8(code)
+                       r.o++
+                       if r.last != decoderInvalidCode {
                                // Save what the hi code expands to.
-                               d.suffix[d.hi] = uint8(code)
-                               d.prefix[d.hi] = d.last
+                               r.suffix[r.hi] = uint8(code)
+                               r.prefix[r.hi] = r.last
                        }
-               case code == d.clear:
-                       d.width = 1 + uint(d.litWidth)
-                       d.hi = d.eof
-                       d.overflow = 1 << d.width
-                       d.last = decoderInvalidCode
+               case code == r.clear:
+                       r.width = 1 + uint(r.litWidth)
+                       r.hi = r.eof
+                       r.overflow = 1 << r.width
+                       r.last = decoderInvalidCode
                        continue
-               case code == d.eof:
-                       d.err = io.EOF
+               case code == r.eof:
+                       r.err = io.EOF
                        break loop
-               case code <= d.hi:
-                       c, i := code, len(d.output)-1
-                       if code == d.hi && d.last != decoderInvalidCode {
+               case code <= r.hi:
+                       c, i := code, len(r.output)-1
+                       if code == r.hi && r.last != decoderInvalidCode {
                                // code == hi is a special case which expands to the last expansion
                                // followed by the head of the last expansion. To find the head, we walk
                                // the prefix chain until we find a literal code.
-                               c = d.last
-                               for c >= d.clear {
-                                       c = d.prefix[c]
+                               c = r.last
+                               for c >= r.clear {
+                                       c = r.prefix[c]
                                }
-                               d.output[i] = uint8(c)
+                               r.output[i] = uint8(c)
                                i--
-                               c = d.last
+                               c = r.last
                        }
                        // Copy the suffix chain into output and then write that to w.
-                       for c >= d.clear {
-                               d.output[i] = d.suffix[c]
+                       for c >= r.clear {
+                               r.output[i] = r.suffix[c]
                                i--
-                               c = d.prefix[c]
+                               c = r.prefix[c]
                        }
-                       d.output[i] = uint8(c)
-                       d.o += copy(d.output[d.o:], d.output[i:])
-                       if d.last != decoderInvalidCode {
+                       r.output[i] = uint8(c)
+                       r.o += copy(r.output[r.o:], r.output[i:])
+                       if r.last != decoderInvalidCode {
                                // Save what the hi code expands to.
-                               d.suffix[d.hi] = uint8(c)
-                               d.prefix[d.hi] = d.last
+                               r.suffix[r.hi] = uint8(c)
+                               r.prefix[r.hi] = r.last
                        }
                default:
-                       d.err = errors.New("lzw: invalid code")
+                       r.err = errors.New("lzw: invalid code")
                        break loop
                }
-               d.last, d.hi = code, d.hi+1
-               if d.hi >= d.overflow {
-                       if d.hi > d.overflow {
+               r.last, r.hi = code, r.hi+1
+               if r.hi >= r.overflow {
+                       if r.hi > r.overflow {
                                panic("unreachable")
                        }
-                       if d.width == maxWidth {
-                               d.last = decoderInvalidCode
+                       if r.width == maxWidth {
+                               r.last = decoderInvalidCode
                                // Undo the d.hi++ a few lines above, so that (1) we maintain
                                // the invariant that d.hi < d.overflow, and (2) d.hi does not
                                // eventually overflow a uint16.
-                               d.hi--
+                               r.hi--
                        } else {
-                               d.width++
-                               d.overflow = 1 << d.width
+                               r.width++
+                               r.overflow = 1 << r.width
                        }
                }
-               if d.o >= flushBuffer {
+               if r.o >= flushBuffer {
                        break
                }
        }
        // Flush pending output.
-       d.toRead = d.output[:d.o]
-       d.o = 0
+       r.toRead = r.output[:r.o]
+       r.o = 0
 }
 
 var errClosed = errors.New("lzw: reader/writer is closed")
 
-func (d *decoder) Close() error {
-       d.err = errClosed // in case any Reads come along
+// Close closes the Reader and returns an error for any future read operation.
+// It does not close the underlying io.Reader.
+func (r *Reader) Close() error {
+       r.err = errClosed // in case any Reads come along
        return nil
 }
 
+// Reset clears the Reader's state and allows it to be reused again
+// as a new Reader.
+func (r *Reader) Reset(src io.Reader, order Order, litWidth int) {
+       *r = Reader{}
+       r.init(src, order, litWidth)
+}
+
 // NewReader creates a new io.ReadCloser.
 // Reads from the returned io.ReadCloser read and decompress data from r.
 // If r does not also implement io.ByteReader,
@@ -238,32 +248,43 @@ func (d *decoder) Close() error {
 // The number of bits to use for literal codes, litWidth, must be in the
 // range [2,8] and is typically 8. It must equal the litWidth
 // used during compression.
+//
+// It is guaranteed that the underlying type of the returned io.ReadCloser
+// is a *Reader.
 func NewReader(r io.Reader, order Order, litWidth int) io.ReadCloser {
-       d := new(decoder)
+       return newReader(r, order, litWidth)
+}
+
+func newReader(src io.Reader, order Order, litWidth int) *Reader {
+       r := new(Reader)
+       r.init(src, order, litWidth)
+       return r
+}
+
+func (r *Reader) init(src io.Reader, order Order, litWidth int) {
        switch order {
        case LSB:
-               d.read = (*decoder).readLSB
+               r.read = (*Reader).readLSB
        case MSB:
-               d.read = (*decoder).readMSB
+               r.read = (*Reader).readMSB
        default:
-               d.err = errors.New("lzw: unknown order")
-               return d
+               r.err = errors.New("lzw: unknown order")
+               return
        }
        if litWidth < 2 || 8 < litWidth {
-               d.err = fmt.Errorf("lzw: litWidth %d out of range", litWidth)
-               return d
+               r.err = fmt.Errorf("lzw: litWidth %d out of range", litWidth)
+               return
        }
-       if br, ok := r.(io.ByteReader); ok {
-               d.r = br
-       } else {
-               d.r = bufio.NewReader(r)
-       }
-       d.litWidth = litWidth
-       d.width = 1 + uint(litWidth)
-       d.clear = uint16(1) << uint(litWidth)
-       d.eof, d.hi = d.clear+1, d.clear+1
-       d.overflow = uint16(1) << d.width
-       d.last = decoderInvalidCode
 
-       return d
+       br, ok := src.(io.ByteReader)
+       if !ok && src != nil {
+               br = bufio.NewReader(src)
+       }
+       r.r = br
+       r.litWidth = litWidth
+       r.width = 1 + uint(litWidth)
+       r.clear = uint16(1) << uint(litWidth)
+       r.eof, r.hi = r.clear+1, r.clear+1
+       r.overflow = uint16(1) << r.width
+       r.last = decoderInvalidCode
 }
index d1eb76d04255ce9f3a06f59e7d086787bd3e5ccb..9a2a4773024a96bd307dc06109c52dae2fd45927 100644 (file)
@@ -120,6 +120,53 @@ func TestReader(t *testing.T) {
        }
 }
 
+func TestReaderReset(t *testing.T) {
+       var b bytes.Buffer
+       for _, tt := range lzwTests {
+               d := strings.Split(tt.desc, ";")
+               var order Order
+               switch d[1] {
+               case "LSB":
+                       order = LSB
+               case "MSB":
+                       order = MSB
+               default:
+                       t.Errorf("%s: bad order %q", tt.desc, d[1])
+               }
+               litWidth, _ := strconv.Atoi(d[2])
+               rc := NewReader(strings.NewReader(tt.compressed), order, litWidth)
+               defer rc.Close()
+               b.Reset()
+               n, err := io.Copy(&b, rc)
+               b1 := b.Bytes()
+               if err != nil {
+                       if err != tt.err {
+                               t.Errorf("%s: io.Copy: %v want %v", tt.desc, err, tt.err)
+                       }
+                       if err == io.ErrUnexpectedEOF {
+                               // Even if the input is truncated, we should still return the
+                               // partial decoded result.
+                               if n == 0 || !strings.HasPrefix(tt.raw, b.String()) {
+                                       t.Errorf("got %d bytes (%q), want a non-empty prefix of %q", n, b.String(), tt.raw)
+                               }
+                       }
+                       continue
+               }
+
+               b.Reset()
+               rc.(*Reader).Reset(strings.NewReader(tt.compressed), order, litWidth)
+               n, err = io.Copy(&b, rc)
+               b2 := b.Bytes()
+               if err != nil {
+                       t.Errorf("%s: io.Copy: %v want %v", tt.desc, err, nil)
+                       continue
+               }
+               if !bytes.Equal(b1, b2) {
+                       t.Errorf("bytes read were not the same")
+               }
+       }
+}
+
 type devZero struct{}
 
 func (devZero) Read(p []byte) (int, error) {
@@ -131,7 +178,7 @@ func (devZero) Read(p []byte) (int, error) {
 
 func TestHiCodeDoesNotOverflow(t *testing.T) {
        r := NewReader(devZero{}, LSB, 8)
-       d := r.(*decoder)
+       d := r.(*Reader)
        buf := make([]byte, 1024)
        oldHi := uint16(0)
        for i := 0; i < 100; i++ {
@@ -226,28 +273,43 @@ func BenchmarkDecoder(b *testing.B) {
                b.Fatalf("test file has no data")
        }
 
+       getInputBuf := func(buf []byte, n int) []byte {
+               compressed := new(bytes.Buffer)
+               w := NewWriter(compressed, LSB, 8)
+               for i := 0; i < n; i += len(buf) {
+                       if len(buf) > n-i {
+                               buf = buf[:n-i]
+                       }
+                       w.Write(buf)
+               }
+               w.Close()
+               return compressed.Bytes()
+       }
+
        for e := 4; e <= 6; e++ {
                n := int(math.Pow10(e))
                b.Run(fmt.Sprint("1e", e), func(b *testing.B) {
                        b.StopTimer()
                        b.SetBytes(int64(n))
-                       buf0 := buf
-                       compressed := new(bytes.Buffer)
-                       w := NewWriter(compressed, LSB, 8)
-                       for i := 0; i < n; i += len(buf0) {
-                               if len(buf0) > n-i {
-                                       buf0 = buf0[:n-i]
-                               }
-                               w.Write(buf0)
-                       }
-                       w.Close()
-                       buf1 := compressed.Bytes()
-                       buf0, compressed, w = nil, nil, nil
+                       buf1 := getInputBuf(buf, n)
                        runtime.GC()
                        b.StartTimer()
                        for i := 0; i < b.N; i++ {
                                io.Copy(io.Discard, NewReader(bytes.NewReader(buf1), LSB, 8))
                        }
                })
+               b.Run(fmt.Sprint("1e-Reuse", e), func(b *testing.B) {
+                       b.StopTimer()
+                       b.SetBytes(int64(n))
+                       buf1 := getInputBuf(buf, n)
+                       runtime.GC()
+                       b.StartTimer()
+                       r := NewReader(bytes.NewReader(buf1), LSB, 8)
+                       for i := 0; i < b.N; i++ {
+                               io.Copy(io.Discard, r)
+                               r.Close()
+                               r.(*Reader).Reset(bytes.NewReader(buf1), LSB, 8)
+                       }
+               })
        }
 }
index 6ddb335f31523ba7b3d2ec45a37490663fa9a9fc..552bdc2ce1746238bb066a2b1a15f1f4c48181b5 100644 (file)
@@ -17,19 +17,6 @@ type writer interface {
        Flush() error
 }
 
-// An errWriteCloser is an io.WriteCloser that always returns a given error.
-type errWriteCloser struct {
-       err error
-}
-
-func (e *errWriteCloser) Write([]byte) (int, error) {
-       return 0, e.err
-}
-
-func (e *errWriteCloser) Close() error {
-       return e.err
-}
-
 const (
        // A code is a 12 bit value, stored as a uint32 when encoding to avoid
        // type conversions when shifting bits.
@@ -44,14 +31,15 @@ const (
        invalidEntry = 0
 )
 
-// encoder is LZW compressor.
-type encoder struct {
+// Writer is an LZW compressor. It writes the compressed form of the data
+// to an underlying writer (see NewWriter).
+type Writer struct {
        // w is the writer that compressed bytes are written to.
        w writer
        // order, write, bits, nBits and width are the state for
        // converting a code stream into a byte stream.
        order Order
-       write func(*encoder, uint32) error
+       write func(*Writer, uint32) error
        bits  uint32
        nBits uint
        width uint
@@ -63,7 +51,7 @@ type encoder struct {
        // savedCode is the accumulated code at the end of the most recent Write
        // call. It is equal to invalidCode if there was no such call.
        savedCode uint32
-       // err is the first error encountered during writing. Closing the encoder
+       // err is the first error encountered during writing. Closing the writer
        // will make any future Write calls return errClosed
        err error
        // table is the hash table from 20-bit keys to 12-bit values. Each table
@@ -74,80 +62,80 @@ type encoder struct {
 }
 
 // writeLSB writes the code c for "Least Significant Bits first" data.
-func (e *encoder) writeLSB(c uint32) error {
-       e.bits |= c << e.nBits
-       e.nBits += e.width
-       for e.nBits >= 8 {
-               if err := e.w.WriteByte(uint8(e.bits)); err != nil {
+func (w *Writer) writeLSB(c uint32) error {
+       w.bits |= c << w.nBits
+       w.nBits += w.width
+       for w.nBits >= 8 {
+               if err := w.w.WriteByte(uint8(w.bits)); err != nil {
                        return err
                }
-               e.bits >>= 8
-               e.nBits -= 8
+               w.bits >>= 8
+               w.nBits -= 8
        }
        return nil
 }
 
 // writeMSB writes the code c for "Most Significant Bits first" data.
-func (e *encoder) writeMSB(c uint32) error {
-       e.bits |= c << (32 - e.width - e.nBits)
-       e.nBits += e.width
-       for e.nBits >= 8 {
-               if err := e.w.WriteByte(uint8(e.bits >> 24)); err != nil {
+func (w *Writer) writeMSB(c uint32) error {
+       w.bits |= c << (32 - w.width - w.nBits)
+       w.nBits += w.width
+       for w.nBits >= 8 {
+               if err := w.w.WriteByte(uint8(w.bits >> 24)); err != nil {
                        return err
                }
-               e.bits <<= 8
-               e.nBits -= 8
+               w.bits <<= 8
+               w.nBits -= 8
        }
        return nil
 }
 
-// errOutOfCodes is an internal error that means that the encoder has run out
+// errOutOfCodes is an internal error that means that the writer has run out
 // of unused codes and a clear code needs to be sent next.
 var errOutOfCodes = errors.New("lzw: out of codes")
 
 // incHi increments e.hi and checks for both overflow and running out of
 // unused codes. In the latter case, incHi sends a clear code, resets the
-// encoder state and returns errOutOfCodes.
-func (e *encoder) incHi() error {
-       e.hi++
-       if e.hi == e.overflow {
-               e.width++
-               e.overflow <<= 1
+// writer state and returns errOutOfCodes.
+func (w *Writer) incHi() error {
+       w.hi++
+       if w.hi == w.overflow {
+               w.width++
+               w.overflow <<= 1
        }
-       if e.hi == maxCode {
-               clear := uint32(1) << e.litWidth
-               if err := e.write(e, clear); err != nil {
+       if w.hi == maxCode {
+               clear := uint32(1) << w.litWidth
+               if err := w.write(w, clear); err != nil {
                        return err
                }
-               e.width = e.litWidth + 1
-               e.hi = clear + 1
-               e.overflow = clear << 1
-               for i := range e.table {
-                       e.table[i] = invalidEntry
+               w.width = w.litWidth + 1
+               w.hi = clear + 1
+               w.overflow = clear << 1
+               for i := range w.table {
+                       w.table[i] = invalidEntry
                }
                return errOutOfCodes
        }
        return nil
 }
 
-// Write writes a compressed representation of p to e's underlying writer.
-func (e *encoder) Write(p []byte) (n int, err error) {
-       if e.err != nil {
-               return 0, e.err
+// Write writes a compressed representation of p to w's underlying writer.
+func (w *Writer) Write(p []byte) (n int, err error) {
+       if w.err != nil {
+               return 0, w.err
        }
        if len(p) == 0 {
                return 0, nil
        }
-       if maxLit := uint8(1<<e.litWidth - 1); maxLit != 0xff {
+       if maxLit := uint8(1<<w.litWidth - 1); maxLit != 0xff {
                for _, x := range p {
                        if x > maxLit {
-                               e.err = errors.New("lzw: input byte too large for the litWidth")
-                               return 0, e.err
+                               w.err = errors.New("lzw: input byte too large for the litWidth")
+                               return 0, w.err
                        }
                }
        }
        n = len(p)
-       code := e.savedCode
+       code := w.savedCode
        if code == invalidCode {
                // The first code sent is always a literal code.
                code, p = uint32(p[0]), p[1:]
@@ -159,77 +147,84 @@ loop:
                // If there is a hash table hit for this key then we continue the loop
                // and do not emit a code yet.
                hash := (key>>12 ^ key) & tableMask
-               for h, t := hash, e.table[hash]; t != invalidEntry; {
+               for h, t := hash, w.table[hash]; t != invalidEntry; {
                        if key == t>>12 {
                                code = t & maxCode
                                continue loop
                        }
                        h = (h + 1) & tableMask
-                       t = e.table[h]
+                       t = w.table[h]
                }
                // Otherwise, write the current code, and literal becomes the start of
                // the next emitted code.
-               if e.err = e.write(e, code); e.err != nil {
-                       return 0, e.err
+               if w.err = w.write(w, code); w.err != nil {
+                       return 0, w.err
                }
                code = literal
                // Increment e.hi, the next implied code. If we run out of codes, reset
-               // the encoder state (including clearing the hash table) and continue.
-               if err1 := e.incHi(); err1 != nil {
+               // the writer state (including clearing the hash table) and continue.
+               if err1 := w.incHi(); err1 != nil {
                        if err1 == errOutOfCodes {
                                continue
                        }
-                       e.err = err1
-                       return 0, e.err
+                       w.err = err1
+                       return 0, w.err
                }
                // Otherwise, insert key -> e.hi into the map that e.table represents.
                for {
-                       if e.table[hash] == invalidEntry {
-                               e.table[hash] = (key << 12) | e.hi
+                       if w.table[hash] == invalidEntry {
+                               w.table[hash] = (key << 12) | w.hi
                                break
                        }
                        hash = (hash + 1) & tableMask
                }
        }
-       e.savedCode = code
+       w.savedCode = code
        return n, nil
 }
 
-// Close closes the encoder, flushing any pending output. It does not close or
-// flush e's underlying writer.
-func (e *encoder) Close() error {
-       if e.err != nil {
-               if e.err == errClosed {
+// Close closes the Writer, flushing any pending output. It does not close
+// w's underlying writer.
+func (w *Writer) Close() error {
+       if w.err != nil {
+               if w.err == errClosed {
                        return nil
                }
-               return e.err
+               return w.err
        }
        // Make any future calls to Write return errClosed.
-       e.err = errClosed
+       w.err = errClosed
        // Write the savedCode if valid.
-       if e.savedCode != invalidCode {
-               if err := e.write(e, e.savedCode); err != nil {
+       if w.savedCode != invalidCode {
+               if err := w.write(w, w.savedCode); err != nil {
                        return err
                }
-               if err := e.incHi(); err != nil && err != errOutOfCodes {
+               if err := w.incHi(); err != nil && err != errOutOfCodes {
                        return err
                }
        }
        // Write the eof code.
-       eof := uint32(1)<<e.litWidth + 1
-       if err := e.write(e, eof); err != nil {
+       eof := uint32(1)<<w.litWidth + 1
+       if err := w.write(w, eof); err != nil {
                return err
        }
        // Write the final bits.
-       if e.nBits > 0 {
-               if e.order == MSB {
-                       e.bits >>= 24
+       if w.nBits > 0 {
+               if w.order == MSB {
+                       w.bits >>= 24
                }
-               if err := e.w.WriteByte(uint8(e.bits)); err != nil {
+               if err := w.w.WriteByte(uint8(w.bits)); err != nil {
                        return err
                }
        }
-       return e.w.Flush()
+       return w.w.Flush()
+}
+
+// Reset clears the Writer's state and allows it to be reused again
+// as a new Writer.
+func (w *Writer) Reset(dst io.Writer, order Order, litWidth int) {
+       *w = Writer{}
+       w.init(dst, order, litWidth)
 }
 
 // NewWriter creates a new io.WriteCloser.
@@ -238,32 +233,43 @@ func (e *encoder) Close() error {
 // finished writing.
 // The number of bits to use for literal codes, litWidth, must be in the
 // range [2,8] and is typically 8. Input bytes must be less than 1<<litWidth.
+//
+// It is guaranteed that the underlying type of the returned io.WriteCloser
+// is a *Writer.
 func NewWriter(w io.Writer, order Order, litWidth int) io.WriteCloser {
-       var write func(*encoder, uint32) error
+       return newWriter(w, order, litWidth)
+}
+
+func newWriter(dst io.Writer, order Order, litWidth int) *Writer {
+       w := new(Writer)
+       w.init(dst, order, litWidth)
+       return w
+}
+
+func (w *Writer) init(dst io.Writer, order Order, litWidth int) {
        switch order {
        case LSB:
-               write = (*encoder).writeLSB
+               w.write = (*Writer).writeLSB
        case MSB:
-               write = (*encoder).writeMSB
+               w.write = (*Writer).writeMSB
        default:
-               return &errWriteCloser{errors.New("lzw: unknown order")}
+               w.err = errors.New("lzw: unknown order")
+               return
        }
        if litWidth < 2 || 8 < litWidth {
-               return &errWriteCloser{fmt.Errorf("lzw: litWidth %d out of range", litWidth)}
+               w.err = fmt.Errorf("lzw: litWidth %d out of range", litWidth)
+               return
        }
-       bw, ok := w.(writer)
-       if !ok {
-               bw = bufio.NewWriter(w)
+       bw, ok := dst.(writer)
+       if !ok && dst != nil {
+               bw = bufio.NewWriter(dst)
        }
+       w.w = bw
        lw := uint(litWidth)
-       return &encoder{
-               w:         bw,
-               order:     order,
-               write:     write,
-               width:     1 + lw,
-               litWidth:  lw,
-               hi:        1<<lw + 1,
-               overflow:  1 << (lw + 1),
-               savedCode: invalidCode,
-       }
+       w.order = order
+       w.width = 1 + lw
+       w.litWidth = lw
+       w.hi = 1<<lw + 1
+       w.overflow = 1 << (lw + 1)
+       w.savedCode = invalidCode
 }
index 1a5dbcae93f3bc6e0e65595ab3a9f0fd3bb6a0c6..9f59c8bb18a6946d042b5f28477326e9e176da66 100644 (file)
@@ -5,6 +5,7 @@
 package lzw
 
 import (
+       "bytes"
        "fmt"
        "internal/testenv"
        "io"
@@ -105,6 +106,50 @@ func TestWriter(t *testing.T) {
        }
 }
 
+func TestWriterReset(t *testing.T) {
+       for _, order := range [...]Order{LSB, MSB} {
+               t.Run(fmt.Sprintf("Order %d", order), func(t *testing.T) {
+                       for litWidth := 6; litWidth <= 8; litWidth++ {
+                               t.Run(fmt.Sprintf("LitWidth %d", litWidth), func(t *testing.T) {
+                                       var data []byte
+                                       if litWidth == 6 {
+                                               data = []byte{1, 2, 3}
+                                       } else {
+                                               data = []byte(`lorem ipsum dolor sit amet`)
+                                       }
+                                       var buf bytes.Buffer
+                                       w := NewWriter(&buf, order, litWidth)
+                                       if _, err := w.Write(data); err != nil {
+                                               t.Errorf("write: %v: %v", string(data), err)
+                                       }
+
+                                       if err := w.Close(); err != nil {
+                                               t.Errorf("close: %v", err)
+                                       }
+
+                                       b1 := buf.Bytes()
+                                       buf.Reset()
+
+                                       w.(*Writer).Reset(&buf, order, litWidth)
+
+                                       if _, err := w.Write(data); err != nil {
+                                               t.Errorf("write: %v: %v", string(data), err)
+                                       }
+
+                                       if err := w.Close(); err != nil {
+                                               t.Errorf("close: %v", err)
+                                       }
+                                       b2 := buf.Bytes()
+
+                                       if !bytes.Equal(b1, b2) {
+                                               t.Errorf("bytes written were not same")
+                                       }
+                               })
+                       }
+               })
+       }
+}
+
 func TestWriterReturnValues(t *testing.T) {
        w := NewWriter(io.Discard, LSB, 8)
        n, err := w.Write([]byte("asdf"))
@@ -152,5 +197,14 @@ func BenchmarkEncoder(b *testing.B) {
                                w.Close()
                        }
                })
+               b.Run(fmt.Sprint("1e-Reuse", e), func(b *testing.B) {
+                       b.SetBytes(int64(n))
+                       w := NewWriter(io.Discard, LSB, 8)
+                       for i := 0; i < b.N; i++ {
+                               w.Write(buf1)
+                               w.Close()
+                               w.(*Writer).Reset(io.Discard, LSB, 8)
+                       }
+               })
        }
 }
index 5d56863050a9adea7be7a724d47861737d13859e..69d75fff1866baa06362994adbc1ddadc647e226 100644 (file)
@@ -138,3 +138,17 @@ func BenchmarkCheckCanceled(b *testing.B) {
                }
        })
 }
+
+func BenchmarkContextCancelDone(b *testing.B) {
+       ctx, cancel := WithCancel(Background())
+       defer cancel()
+
+       b.RunParallel(func(pb *testing.PB) {
+               for pb.Next() {
+                       select {
+                       case <-ctx.Done():
+                       default:
+                       }
+               }
+       })
+}
index b3fdb8277afc37a6c2cdbc8fee9c1967f00ea6ca..733c5f56d9274d178923f7d452434bc8a379db7a 100644 (file)
@@ -303,10 +303,8 @@ func parentCancelCtx(parent Context) (*cancelCtx, bool) {
        if !ok {
                return nil, false
        }
-       p.mu.Lock()
-       ok = p.done == done
-       p.mu.Unlock()
-       if !ok {
+       pdone, _ := p.done.Load().(chan struct{})
+       if pdone != done {
                return nil, false
        }
        return p, true
@@ -345,7 +343,7 @@ type cancelCtx struct {
        Context
 
        mu       sync.Mutex            // protects following fields
-       done     chan struct{}         // created lazily, closed by first cancel call
+       done     atomic.Value          // of chan struct{}, created lazily, closed by first cancel call
        children map[canceler]struct{} // set to nil by the first cancel call
        err      error                 // set to non-nil by the first cancel call
 }
@@ -358,13 +356,18 @@ func (c *cancelCtx) Value(key interface{}) interface{} {
 }
 
 func (c *cancelCtx) Done() <-chan struct{} {
+       d := c.done.Load()
+       if d != nil {
+               return d.(chan struct{})
+       }
        c.mu.Lock()
-       if c.done == nil {
-               c.done = make(chan struct{})
+       defer c.mu.Unlock()
+       d = c.done.Load()
+       if d == nil {
+               d = make(chan struct{})
+               c.done.Store(d)
        }
-       d := c.done
-       c.mu.Unlock()
-       return d
+       return d.(chan struct{})
 }
 
 func (c *cancelCtx) Err() error {
@@ -401,10 +404,11 @@ func (c *cancelCtx) cancel(removeFromParent bool, err error) {
                return // already canceled
        }
        c.err = err
-       if c.done == nil {
-               c.done = closedchan
+       d, _ := c.done.Load().(chan struct{})
+       if d == nil {
+               c.done.Store(closedchan)
        } else {
-               close(c.done)
+               close(d)
        }
        for child := range c.children {
                // NOTE: acquiring the child's lock while holding parent's lock.
index 6b392a29da5ed3e4fa4ff2590431131e351caeb4..a2e2324a0eb2575ae6a179ac2da9298d09ff4d70 100644 (file)
@@ -525,7 +525,7 @@ func XTestInterlockedCancels(t testingT) {
        parent, cancelParent := WithCancel(Background())
        child, cancelChild := WithCancel(parent)
        go func() {
-               parent.Done()
+               <-parent.Done()
                cancelChild()
        }()
        cancelParent()
@@ -661,7 +661,7 @@ func XTestWithCancelCanceledParent(t testingT) {
                t.Errorf("child not done immediately upon construction")
        }
        if got, want := c.Err(), Canceled; got != want {
-               t.Errorf("child not cancelled; got = %v, want = %v", got, want)
+               t.Errorf("child not canceled; got = %v, want = %v", got, want)
        }
 }
 
@@ -779,7 +779,7 @@ func XTestCustomContextGoroutines(t testingT) {
        defer cancel6()
        checkNoGoroutine()
 
-       // Check applied to cancelled context.
+       // Check applied to canceled context.
        cancel6()
        cancel1()
        _, cancel7 := WithCancel(ctx5)
index 3888010025f018fa037d8ad3dbc2b70554ea3ae6..4b27615602c22116a53763ea16a131733414bdc1 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
-// -build amd64 arm64
 
 package aes
 
index dc4251acc3dfc1109315969cb4613297ff3cdcb8..ee7df2b2f27fec5bed2d5aa7a25ead22cce15e87 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build ignore_for_gccgo
-// +build amd64 arm64
+//go:build ignore
+// +build ignore
 
 package aes
 
index 19a930f09d87688d74c4b07634f0da8722abafc7..1630331f25d03d614773da393acf6837001bfaf5 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//-go:build !amd64 && !s390x && !ppc64le && !arm64
 // -build !amd64,!s390x,!ppc64le,!arm64
 
 package aes
index 707478c6d2e70d67cfc3e18b195fa70c7df72d13..232eae188bad16a2281ceef008bea0f8eafa4200 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
-// +build ppc64le
 
 package aes
 
index 90d0cd71385fb0ca88e2aab32748379b859dc1c1..eb02cd08c50deb39c6b0010ff12c6016a66943db 100644 (file)
@@ -7,28 +7,15 @@ package cipher_test
 import (
        "crypto/aes"
        "crypto/cipher"
+       "strconv"
        "testing"
 )
 
-func benchmarkAESGCMSign(b *testing.B, buf []byte) {
+func benchmarkAESGCMSeal(b *testing.B, buf []byte, keySize int) {
+       b.ReportAllocs()
        b.SetBytes(int64(len(buf)))
 
-       var key [16]byte
-       var nonce [12]byte
-       aes, _ := aes.NewCipher(key[:])
-       aesgcm, _ := cipher.NewGCM(aes)
-       var out []byte
-
-       b.ResetTimer()
-       for i := 0; i < b.N; i++ {
-               out = aesgcm.Seal(out[:0], nonce[:], nil, buf)
-       }
-}
-
-func benchmarkAESGCMSeal(b *testing.B, buf []byte) {
-       b.SetBytes(int64(len(buf)))
-
-       var key [16]byte
+       var key = make([]byte, keySize)
        var nonce [12]byte
        var ad [13]byte
        aes, _ := aes.NewCipher(key[:])
@@ -41,44 +28,41 @@ func benchmarkAESGCMSeal(b *testing.B, buf []byte) {
        }
 }
 
-func benchmarkAESGCMOpen(b *testing.B, buf []byte) {
+func benchmarkAESGCMOpen(b *testing.B, buf []byte, keySize int) {
+       b.ReportAllocs()
        b.SetBytes(int64(len(buf)))
 
-       var key [16]byte
+       var key = make([]byte, keySize)
        var nonce [12]byte
        var ad [13]byte
        aes, _ := aes.NewCipher(key[:])
        aesgcm, _ := cipher.NewGCM(aes)
        var out []byte
-       out = aesgcm.Seal(out[:0], nonce[:], buf, ad[:])
+
+       ct := aesgcm.Seal(nil, nonce[:], buf[:], ad[:])
 
        b.ResetTimer()
        for i := 0; i < b.N; i++ {
-               _, err := aesgcm.Open(buf[:0], nonce[:], out, ad[:])
-               if err != nil {
-                       b.Errorf("Open: %v", err)
-               }
+               out, _ = aesgcm.Open(out[:0], nonce[:], ct, ad[:])
        }
 }
 
-func BenchmarkAESGCMSeal1K(b *testing.B) {
-       benchmarkAESGCMSeal(b, make([]byte, 1024))
-}
-
-func BenchmarkAESGCMOpen1K(b *testing.B) {
-       benchmarkAESGCMOpen(b, make([]byte, 1024))
-}
-
-func BenchmarkAESGCMSign8K(b *testing.B) {
-       benchmarkAESGCMSign(b, make([]byte, 8*1024))
-}
-
-func BenchmarkAESGCMSeal8K(b *testing.B) {
-       benchmarkAESGCMSeal(b, make([]byte, 8*1024))
-}
-
-func BenchmarkAESGCMOpen8K(b *testing.B) {
-       benchmarkAESGCMOpen(b, make([]byte, 8*1024))
+func BenchmarkAESGCM(b *testing.B) {
+       for _, length := range []int{64, 1350, 8 * 1024} {
+               b.Run("Open-128-"+strconv.Itoa(length), func(b *testing.B) {
+                       benchmarkAESGCMOpen(b, make([]byte, length), 128/8)
+               })
+               b.Run("Seal-128-"+strconv.Itoa(length), func(b *testing.B) {
+                       benchmarkAESGCMSeal(b, make([]byte, length), 128/8)
+               })
+
+               b.Run("Open-256-"+strconv.Itoa(length), func(b *testing.B) {
+                       benchmarkAESGCMOpen(b, make([]byte, length), 256/8)
+               })
+               b.Run("Seal-256-"+strconv.Itoa(length), func(b *testing.B) {
+                       benchmarkAESGCMSeal(b, make([]byte, length), 256/8)
+               })
+       }
 }
 
 func benchmarkAESStream(b *testing.B, mode func(cipher.Block, []byte) cipher.Stream, buf []byte) {
index b80a1b90f56c0aa636c83bf28c0c2e3680ca6088..cddc8423e9ba425548241ff16a7ada513b1de4b6 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//-go:build !amd64 && !ppc64 && !ppc64le && !arm64
 // -build !amd64,!ppc64,!ppc64le,!arm64
 
 package cipher
index e7d67f423d57a5526f73713550ed8c5fed52da7d..097ea05065856943c7acce3b6241842ed80b51bd 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
-// +build ppc64 ppc64le
 
 package cipher
 
index ccce87385947f06dd30d813ee0998a35e3a8cd34..219436935f2c96f4bcf5c7943b173c7c90f06f44 100644 (file)
@@ -17,7 +17,7 @@
 //   [Coron]
 //     https://cs.nyu.edu/~dodis/ps/merkle.pdf
 //   [Larsson]
-//     https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf
+//     https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf
 package ecdsa
 
 // Further references:
index b7e73179cdef2fef86d4aad5b08e7df2b3fc1798..717e80de926da71b52454265787a91cdc465a6e0 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//-go:build !s390x
 // -build !s390x
 
 package ecdsa
index de51cabb6d751f0524010c2074511264e3f36a36..b43b82b1dd63f1a4cd714e6eb5063e6ced0e04dc 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore_for_gccgo
 // +build ignore_for_gccgo
 
 package ecdsa
@@ -23,12 +24,18 @@ import (
 //go:noescape
 func kdsa(fc uint64, params *[4096]byte) (errn uint64)
 
+// testingDisableKDSA forces the generic fallback path. It must only be set in tests.
+var testingDisableKDSA bool
+
 // canUseKDSA checks if KDSA instruction is available, and if it is, it checks
 // the name of the curve to see if it matches the curves supported(P-256, P-384, P-521).
 // Then, based on the curve name, a function code and a block size will be assigned.
 // If KDSA instruction is not available or if the curve is not supported, canUseKDSA
 // will set ok to false.
 func canUseKDSA(c elliptic.Curve) (functionCode uint64, blockSize int, ok bool) {
+       if testingDisableKDSA {
+               return 0, 0, false
+       }
        if !cpu.S390X.HasECDSA {
                return 0, 0, false
        }
index 4fc6dfbe2f9ea3ca0105f8267b260de40583c69d..6070afcff3155319b450f0857b8241c2eb67f78b 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build ignore_for_gccgo
-// +build s390x
+//go:build ignore
+// +build ignore
 
 package ecdsa
 
@@ -13,6 +13,9 @@ import (
 )
 
 func TestNoAsm(t *testing.T) {
+       testingDisableKDSA = true
+       defer func() { testingDisableKDSA = false }()
+
        curves := [...]elliptic.Curve{
                elliptic.P256(),
                elliptic.P384(),
@@ -20,15 +23,11 @@ func TestNoAsm(t *testing.T) {
        }
 
        for _, curve := range curves {
-               // override the name of the curve to stop the assembly path being taken
-               params := *curve.Params()
-               name := params.Name
-               params.Name = name + "_GENERIC_OVERRIDE"
-
-               testKeyGeneration(t, &params, name)
-               testSignAndVerify(t, &params, name)
-               testNonceSafety(t, &params, name)
-               testINDCCA(t, &params, name)
-               testNegativeInputs(t, &params, name)
+               name := curve.Params().Name
+               t.Run(name, func(t *testing.T) { testKeyGeneration(t, curve) })
+               t.Run(name, func(t *testing.T) { testSignAndVerify(t, curve) })
+               t.Run(name, func(t *testing.T) { testNonceSafety(t, curve) })
+               t.Run(name, func(t *testing.T) { testINDCCA(t, curve) })
+               t.Run(name, func(t *testing.T) { testNegativeInputs(t, curve) })
        }
 }
index 0c1ff6d2008b22688a8a9a8deba462d084a516ef..556818acf4d14ac411cfc3393746e8bb075dca56 100644 (file)
@@ -21,216 +21,148 @@ import (
        "testing"
 )
 
-func testKeyGeneration(t *testing.T, c elliptic.Curve, tag string) {
-       priv, err := GenerateKey(c, rand.Reader)
-       if err != nil {
-               t.Errorf("%s: error: %s", tag, err)
-               return
+func testAllCurves(t *testing.T, f func(*testing.T, elliptic.Curve)) {
+       tests := []struct {
+               name  string
+               curve elliptic.Curve
+       }{
+               {"P256", elliptic.P256()},
+               {"P224", elliptic.P224()},
+               {"P384", elliptic.P384()},
+               {"P521", elliptic.P521()},
        }
-       if !c.IsOnCurve(priv.PublicKey.X, priv.PublicKey.Y) {
-               t.Errorf("%s: public key invalid: %s", tag, err)
-       }
-}
-
-func TestKeyGeneration(t *testing.T) {
-       testKeyGeneration(t, elliptic.P224(), "p224")
        if testing.Short() {
-               return
+               tests = tests[:1]
+       }
+       for _, test := range tests {
+               curve := test.curve
+               t.Run(test.name, func(t *testing.T) {
+                       t.Parallel()
+                       f(t, curve)
+               })
        }
-       testKeyGeneration(t, elliptic.P256(), "p256")
-       testKeyGeneration(t, elliptic.P384(), "p384")
-       testKeyGeneration(t, elliptic.P521(), "p521")
-}
-
-func BenchmarkSignP256(b *testing.B) {
-       b.ResetTimer()
-       p256 := elliptic.P256()
-       hashed := []byte("testing")
-       priv, _ := GenerateKey(p256, rand.Reader)
-
-       b.ReportAllocs()
-       b.ResetTimer()
-       b.RunParallel(func(pb *testing.PB) {
-               for pb.Next() {
-                       _, _, _ = Sign(rand.Reader, priv, hashed)
-               }
-       })
 }
 
-func BenchmarkSignP384(b *testing.B) {
-       b.ResetTimer()
-       p384 := elliptic.P384()
-       hashed := []byte("testing")
-       priv, _ := GenerateKey(p384, rand.Reader)
-
-       b.ReportAllocs()
-       b.ResetTimer()
-       b.RunParallel(func(pb *testing.PB) {
-               for pb.Next() {
-                       _, _, _ = Sign(rand.Reader, priv, hashed)
-               }
-       })
+func TestKeyGeneration(t *testing.T) {
+       testAllCurves(t, testKeyGeneration)
 }
 
-func BenchmarkVerifyP256(b *testing.B) {
-       b.ResetTimer()
-       p256 := elliptic.P256()
-       hashed := []byte("testing")
-       priv, _ := GenerateKey(p256, rand.Reader)
-       r, s, _ := Sign(rand.Reader, priv, hashed)
-
-       b.ReportAllocs()
-       b.ResetTimer()
-       b.RunParallel(func(pb *testing.PB) {
-               for pb.Next() {
-                       Verify(&priv.PublicKey, hashed, r, s)
-               }
-       })
+func testKeyGeneration(t *testing.T, c elliptic.Curve) {
+       priv, err := GenerateKey(c, rand.Reader)
+       if err != nil {
+               t.Fatal(err)
+       }
+       if !c.IsOnCurve(priv.PublicKey.X, priv.PublicKey.Y) {
+               t.Errorf("public key invalid: %s", err)
+       }
 }
 
-func BenchmarkKeyGeneration(b *testing.B) {
-       b.ResetTimer()
-       p256 := elliptic.P256()
-
-       b.ReportAllocs()
-       b.ResetTimer()
-       b.RunParallel(func(pb *testing.PB) {
-               for pb.Next() {
-                       GenerateKey(p256, rand.Reader)
-               }
-       })
+func TestSignAndVerify(t *testing.T) {
+       testAllCurves(t, testSignAndVerify)
 }
 
-func testSignAndVerify(t *testing.T, c elliptic.Curve, tag string) {
+func testSignAndVerify(t *testing.T, c elliptic.Curve) {
        priv, _ := GenerateKey(c, rand.Reader)
 
        hashed := []byte("testing")
        r, s, err := Sign(rand.Reader, priv, hashed)
        if err != nil {
-               t.Errorf("%s: error signing: %s", tag, err)
+               t.Errorf("error signing: %s", err)
                return
        }
 
        if !Verify(&priv.PublicKey, hashed, r, s) {
-               t.Errorf("%s: Verify failed", tag)
+               t.Errorf("Verify failed")
        }
 
        hashed[0] ^= 0xff
        if Verify(&priv.PublicKey, hashed, r, s) {
-               t.Errorf("%s: Verify always works!", tag)
+               t.Errorf("Verify always works!")
        }
 }
 
-func TestSignAndVerify(t *testing.T) {
-       testSignAndVerify(t, elliptic.P224(), "p224")
-       if testing.Short() {
-               return
-       }
-       testSignAndVerify(t, elliptic.P256(), "p256")
-       testSignAndVerify(t, elliptic.P384(), "p384")
-       testSignAndVerify(t, elliptic.P521(), "p521")
+func TestSignAndVerifyASN1(t *testing.T) {
+       testAllCurves(t, testSignAndVerifyASN1)
 }
 
-func testSignAndVerifyASN1(t *testing.T, c elliptic.Curve, tag string) {
+func testSignAndVerifyASN1(t *testing.T, c elliptic.Curve) {
        priv, _ := GenerateKey(c, rand.Reader)
 
        hashed := []byte("testing")
        sig, err := SignASN1(rand.Reader, priv, hashed)
        if err != nil {
-               t.Errorf("%s: error signing: %s", tag, err)
+               t.Errorf("error signing: %s", err)
                return
        }
 
        if !VerifyASN1(&priv.PublicKey, hashed, sig) {
-               t.Errorf("%s: VerifyASN1 failed", tag)
+               t.Errorf("VerifyASN1 failed")
        }
 
        hashed[0] ^= 0xff
        if VerifyASN1(&priv.PublicKey, hashed, sig) {
-               t.Errorf("%s: VerifyASN1 always works!", tag)
+               t.Errorf("VerifyASN1 always works!")
        }
 }
 
-func TestSignAndVerifyASN1(t *testing.T) {
-       testSignAndVerifyASN1(t, elliptic.P224(), "p224")
-       if testing.Short() {
-               return
-       }
-       testSignAndVerifyASN1(t, elliptic.P256(), "p256")
-       testSignAndVerifyASN1(t, elliptic.P384(), "p384")
-       testSignAndVerifyASN1(t, elliptic.P521(), "p521")
+func TestNonceSafety(t *testing.T) {
+       testAllCurves(t, testNonceSafety)
 }
 
-func testNonceSafety(t *testing.T, c elliptic.Curve, tag string) {
+func testNonceSafety(t *testing.T, c elliptic.Curve) {
        priv, _ := GenerateKey(c, rand.Reader)
 
        hashed := []byte("testing")
        r0, s0, err := Sign(zeroReader, priv, hashed)
        if err != nil {
-               t.Errorf("%s: error signing: %s", tag, err)
+               t.Errorf("error signing: %s", err)
                return
        }
 
        hashed = []byte("testing...")
        r1, s1, err := Sign(zeroReader, priv, hashed)
        if err != nil {
-               t.Errorf("%s: error signing: %s", tag, err)
+               t.Errorf("error signing: %s", err)
                return
        }
 
        if s0.Cmp(s1) == 0 {
                // This should never happen.
-               t.Errorf("%s: the signatures on two different messages were the same", tag)
+               t.Errorf("the signatures on two different messages were the same")
        }
 
        if r0.Cmp(r1) == 0 {
-               t.Errorf("%s: the nonce used for two different messages was the same", tag)
+               t.Errorf("the nonce used for two different messages was the same")
        }
 }
 
-func TestNonceSafety(t *testing.T) {
-       testNonceSafety(t, elliptic.P224(), "p224")
-       if testing.Short() {
-               return
-       }
-       testNonceSafety(t, elliptic.P256(), "p256")
-       testNonceSafety(t, elliptic.P384(), "p384")
-       testNonceSafety(t, elliptic.P521(), "p521")
+func TestINDCCA(t *testing.T) {
+       testAllCurves(t, testINDCCA)
 }
 
-func testINDCCA(t *testing.T, c elliptic.Curve, tag string) {
+func testINDCCA(t *testing.T, c elliptic.Curve) {
        priv, _ := GenerateKey(c, rand.Reader)
 
        hashed := []byte("testing")
        r0, s0, err := Sign(rand.Reader, priv, hashed)
        if err != nil {
-               t.Errorf("%s: error signing: %s", tag, err)
+               t.Errorf("error signing: %s", err)
                return
        }
 
        r1, s1, err := Sign(rand.Reader, priv, hashed)
        if err != nil {
-               t.Errorf("%s: error signing: %s", tag, err)
+               t.Errorf("error signing: %s", err)
                return
        }
 
        if s0.Cmp(s1) == 0 {
-               t.Errorf("%s: two signatures of the same message produced the same result", tag)
+               t.Errorf("two signatures of the same message produced the same result")
        }
 
        if r0.Cmp(r1) == 0 {
-               t.Errorf("%s: two signatures of the same message produced the same nonce", tag)
-       }
-}
-
-func TestINDCCA(t *testing.T) {
-       testINDCCA(t, elliptic.P224(), "p224")
-       if testing.Short() {
-               return
+               t.Errorf("two signatures of the same message produced the same nonce")
        }
-       testINDCCA(t, elliptic.P256(), "p256")
-       testINDCCA(t, elliptic.P384(), "p384")
-       testINDCCA(t, elliptic.P521(), "p521")
 }
 
 func fromHex(s string) *big.Int {
@@ -351,10 +283,14 @@ func TestVectors(t *testing.T) {
        }
 }
 
-func testNegativeInputs(t *testing.T, curve elliptic.Curve, tag string) {
+func TestNegativeInputs(t *testing.T) {
+       testAllCurves(t, testNegativeInputs)
+}
+
+func testNegativeInputs(t *testing.T, curve elliptic.Curve) {
        key, err := GenerateKey(curve, rand.Reader)
        if err != nil {
-               t.Errorf("failed to generate key for %q", tag)
+               t.Errorf("failed to generate key")
        }
 
        var hash [32]byte
@@ -363,35 +299,103 @@ func testNegativeInputs(t *testing.T, curve elliptic.Curve, tag string) {
        r.Neg(r)
 
        if Verify(&key.PublicKey, hash[:], r, r) {
-               t.Errorf("bogus signature accepted for %q", tag)
+               t.Errorf("bogus signature accepted")
        }
 }
 
-func TestNegativeInputs(t *testing.T) {
-       testNegativeInputs(t, elliptic.P224(), "p224")
-       testNegativeInputs(t, elliptic.P256(), "p256")
-       testNegativeInputs(t, elliptic.P384(), "p384")
-       testNegativeInputs(t, elliptic.P521(), "p521")
+func TestZeroHashSignature(t *testing.T) {
+       testAllCurves(t, testZeroHashSignature)
 }
 
-func TestZeroHashSignature(t *testing.T) {
+func testZeroHashSignature(t *testing.T, curve elliptic.Curve) {
        zeroHash := make([]byte, 64)
 
-       for _, curve := range []elliptic.Curve{elliptic.P224(), elliptic.P256(), elliptic.P384(), elliptic.P521()} {
-               privKey, err := GenerateKey(curve, rand.Reader)
+       privKey, err := GenerateKey(curve, rand.Reader)
+       if err != nil {
+               panic(err)
+       }
+
+       // Sign a hash consisting of all zeros.
+       r, s, err := Sign(rand.Reader, privKey, zeroHash)
+       if err != nil {
+               panic(err)
+       }
+
+       // Confirm that it can be verified.
+       if !Verify(&privKey.PublicKey, zeroHash, r, s) {
+               t.Errorf("zero hash signature verify failed for %T", curve)
+       }
+}
+
+func benchmarkAllCurves(t *testing.B, f func(*testing.B, elliptic.Curve)) {
+       tests := []struct {
+               name  string
+               curve elliptic.Curve
+       }{
+               {"P256", elliptic.P256()},
+               {"P224", elliptic.P224()},
+               {"P384", elliptic.P384()},
+               {"P521", elliptic.P521()},
+       }
+       for _, test := range tests {
+               curve := test.curve
+               t.Run(test.name, func(t *testing.B) {
+                       f(t, curve)
+               })
+       }
+}
+
+func BenchmarkSign(b *testing.B) {
+       benchmarkAllCurves(b, func(b *testing.B, curve elliptic.Curve) {
+               priv, err := GenerateKey(curve, rand.Reader)
                if err != nil {
-                       panic(err)
+                       b.Fatal(err)
                }
+               hashed := []byte("testing")
+
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       sig, err := SignASN1(rand.Reader, priv, hashed)
+                       if err != nil {
+                               b.Fatal(err)
+                       }
+                       // Prevent the compiler from optimizing out the operation.
+                       hashed[0] = sig[0]
+               }
+       })
+}
 
-               // Sign a hash consisting of all zeros.
-               r, s, err := Sign(rand.Reader, privKey, zeroHash)
+func BenchmarkVerify(b *testing.B) {
+       benchmarkAllCurves(b, func(b *testing.B, curve elliptic.Curve) {
+               priv, err := GenerateKey(curve, rand.Reader)
+               if err != nil {
+                       b.Fatal(err)
+               }
+               hashed := []byte("testing")
+               r, s, err := Sign(rand.Reader, priv, hashed)
                if err != nil {
-                       panic(err)
+                       b.Fatal(err)
                }
 
-               // Confirm that it can be verified.
-               if !Verify(&privKey.PublicKey, zeroHash, r, s) {
-                       t.Errorf("zero hash signature verify failed for %T", curve)
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       if !Verify(&priv.PublicKey, hashed, r, s) {
+                               b.Fatal("verify failed")
+                       }
                }
-       }
+       })
+}
+
+func BenchmarkGenerateKey(b *testing.B) {
+       benchmarkAllCurves(b, func(b *testing.B, curve elliptic.Curve) {
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       if _, err := GenerateKey(curve, rand.Reader); err != nil {
+                               b.Fatal(err)
+                       }
+               }
+       })
 }
index 6f59bb5cffbe9d2632cb96549cfe7903789a10fb..09c5269d0c6a033047011c82d073a1fb65d145f9 100644 (file)
@@ -12,9 +12,6 @@
 // 8032 private key as the “seed”.
 package ed25519
 
-// This code is a port of the public domain, “ref10” implementation of ed25519
-// from SUPERCOP.
-
 import (
        "bytes"
        "crypto"
@@ -128,20 +125,14 @@ func newKeyFromSeed(privateKey, seed []byte) {
                panic("ed25519: bad seed length: " + strconv.Itoa(l))
        }
 
-       digest := sha512.Sum512(seed)
-       digest[0] &= 248
-       digest[31] &= 127
-       digest[31] |= 64
+       h := sha512.Sum512(seed)
+       s := edwards25519.NewScalar().SetBytesWithClamping(h[:32])
+       A := (&edwards25519.Point{}).ScalarBaseMult(s)
 
-       var A edwards25519.ExtendedGroupElement
-       var hBytes [32]byte
-       copy(hBytes[:], digest[:])
-       edwards25519.GeScalarMultBase(&A, &hBytes)
-       var publicKeyBytes [32]byte
-       A.ToBytes(&publicKeyBytes)
+       publicKey := A.Bytes()
 
        copy(privateKey, seed)
-       copy(privateKey[32:], publicKeyBytes[:])
+       copy(privateKey[32:], publicKey)
 }
 
 // Sign signs the message with privateKey and returns a signature. It will
@@ -158,44 +149,33 @@ func sign(signature, privateKey, message []byte) {
        if l := len(privateKey); l != PrivateKeySize {
                panic("ed25519: bad private key length: " + strconv.Itoa(l))
        }
+       seed, publicKey := privateKey[:SeedSize], privateKey[SeedSize:]
+
+       h := sha512.Sum512(seed)
+       s := edwards25519.NewScalar().SetBytesWithClamping(h[:32])
+       prefix := h[32:]
+
+       mh := sha512.New()
+       mh.Write(prefix)
+       mh.Write(message)
+       messageDigest := make([]byte, 0, sha512.Size)
+       messageDigest = mh.Sum(messageDigest)
+       r := edwards25519.NewScalar().SetUniformBytes(messageDigest)
+
+       R := (&edwards25519.Point{}).ScalarBaseMult(r)
 
-       h := sha512.New()
-       h.Write(privateKey[:32])
-
-       var digest1, messageDigest, hramDigest [64]byte
-       var expandedSecretKey [32]byte
-       h.Sum(digest1[:0])
-       copy(expandedSecretKey[:], digest1[:])
-       expandedSecretKey[0] &= 248
-       expandedSecretKey[31] &= 63
-       expandedSecretKey[31] |= 64
-
-       h.Reset()
-       h.Write(digest1[32:])
-       h.Write(message)
-       h.Sum(messageDigest[:0])
-
-       var messageDigestReduced [32]byte
-       edwards25519.ScReduce(&messageDigestReduced, &messageDigest)
-       var R edwards25519.ExtendedGroupElement
-       edwards25519.GeScalarMultBase(&R, &messageDigestReduced)
-
-       var encodedR [32]byte
-       R.ToBytes(&encodedR)
-
-       h.Reset()
-       h.Write(encodedR[:])
-       h.Write(privateKey[32:])
-       h.Write(message)
-       h.Sum(hramDigest[:0])
-       var hramDigestReduced [32]byte
-       edwards25519.ScReduce(&hramDigestReduced, &hramDigest)
-
-       var s [32]byte
-       edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced)
-
-       copy(signature[:], encodedR[:])
-       copy(signature[32:], s[:])
+       kh := sha512.New()
+       kh.Write(R.Bytes())
+       kh.Write(publicKey)
+       kh.Write(message)
+       hramDigest := make([]byte, 0, sha512.Size)
+       hramDigest = kh.Sum(hramDigest)
+       k := edwards25519.NewScalar().SetUniformBytes(hramDigest)
+
+       S := edwards25519.NewScalar().MultiplyAdd(k, s, r)
+
+       copy(signature[:32], R.Bytes())
+       copy(signature[32:], S.Bytes())
 }
 
 // Verify reports whether sig is a valid signature of message by publicKey. It
@@ -209,38 +189,27 @@ func Verify(publicKey PublicKey, message, sig []byte) bool {
                return false
        }
 
-       var A edwards25519.ExtendedGroupElement
-       var publicKeyBytes [32]byte
-       copy(publicKeyBytes[:], publicKey)
-       if !A.FromBytes(&publicKeyBytes) {
+       A, err := (&edwards25519.Point{}).SetBytes(publicKey)
+       if err != nil {
                return false
        }
-       edwards25519.FeNeg(&A.X, &A.X)
-       edwards25519.FeNeg(&A.T, &A.T)
-
-       h := sha512.New()
-       h.Write(sig[:32])
-       h.Write(publicKey[:])
-       h.Write(message)
-       var digest [64]byte
-       h.Sum(digest[:0])
-
-       var hReduced [32]byte
-       edwards25519.ScReduce(&hReduced, &digest)
-
-       var R edwards25519.ProjectiveGroupElement
-       var s [32]byte
-       copy(s[:], sig[32:])
-
-       // https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in
-       // the range [0, order) in order to prevent signature malleability.
-       if !edwards25519.ScMinimal(&s) {
+
+       kh := sha512.New()
+       kh.Write(sig[:32])
+       kh.Write(publicKey)
+       kh.Write(message)
+       hramDigest := make([]byte, 0, sha512.Size)
+       hramDigest = kh.Sum(hramDigest)
+       k := edwards25519.NewScalar().SetUniformBytes(hramDigest)
+
+       S, err := edwards25519.NewScalar().SetCanonicalBytes(sig[32:])
+       if err != nil {
                return false
        }
 
-       edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &s)
+       // [S]B = R + [k]A --> [k](-A) + [S]B = R
+       minusA := (&edwards25519.Point{}).Negate(A)
+       R := (&edwards25519.Point{}).VarTimeDoubleScalarBaseMult(k, minusA, S)
 
-       var checkR [32]byte
-       R.ToBytes(&checkR)
-       return bytes.Equal(sig[:32], checkR[:])
+       return bytes.Equal(sig[:32], R.Bytes())
 }
index adb09e409a502c58a4f7910c4308a18708e5f9cc..26e1b3397ab5ae0369e3eb1f8ec10b8720999619 100644 (file)
@@ -9,10 +9,10 @@ import (
        "bytes"
        "compress/gzip"
        "crypto"
-       "crypto/ed25519/internal/edwards25519"
        "crypto/rand"
        "encoding/hex"
        "os"
+       "runtime"
        "strings"
        "testing"
 )
@@ -26,24 +26,6 @@ func (zeroReader) Read(buf []byte) (int, error) {
        return len(buf), nil
 }
 
-func TestUnmarshalMarshal(t *testing.T) {
-       pub, _, _ := GenerateKey(rand.Reader)
-
-       var A edwards25519.ExtendedGroupElement
-       var pubBytes [32]byte
-       copy(pubBytes[:], pub)
-       if !A.FromBytes(&pubBytes) {
-               t.Fatalf("ExtendedGroupElement.FromBytes failed")
-       }
-
-       var pub2 [32]byte
-       A.ToBytes(&pub2)
-
-       if pubBytes != pub2 {
-               t.Errorf("FromBytes(%v)->ToBytes does not round-trip, got %x\n", pubBytes, pub2)
-       }
-}
-
 func TestSignVerify(t *testing.T) {
        var zero zeroReader
        public, private, _ := GenerateKey(zero)
@@ -204,6 +186,27 @@ func TestMalleability(t *testing.T) {
        }
 }
 
+func TestAllocations(t *testing.T) {
+       if runtime.Compiler == "gccgo" {
+               t.Skip("gofronted escape analysis not good enough")
+       }
+       if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-noopt") {
+               t.Skip("skipping allocations test without relevant optimizations")
+       }
+       if allocs := testing.AllocsPerRun(100, func() {
+               seed := make([]byte, SeedSize)
+               message := []byte("Hello, world!")
+               priv := NewKeyFromSeed(seed)
+               pub := priv.Public().(PublicKey)
+               signature := Sign(priv, message)
+               if !Verify(pub, message, signature) {
+                       t.Fatal("signature didn't verify")
+               }
+       }); allocs > 0 {
+               t.Errorf("expected zero allocations, got %0.1v", allocs)
+       }
+}
+
 func BenchmarkKeyGeneration(b *testing.B) {
        var zero zeroReader
        for i := 0; i < b.N; i++ {
@@ -215,7 +218,6 @@ func BenchmarkKeyGeneration(b *testing.B) {
 
 func BenchmarkNewKeyFromSeed(b *testing.B) {
        seed := make([]byte, SeedSize)
-       b.ReportAllocs()
        for i := 0; i < b.N; i++ {
                _ = NewKeyFromSeed(seed)
        }
@@ -228,7 +230,6 @@ func BenchmarkSigning(b *testing.B) {
                b.Fatal(err)
        }
        message := []byte("Hello, world!")
-       b.ReportAllocs()
        b.ResetTimer()
        for i := 0; i < b.N; i++ {
                Sign(priv, message)
diff --git a/libgo/go/crypto/ed25519/ed25519vectors_test.go b/libgo/go/crypto/ed25519/ed25519vectors_test.go
new file mode 100644 (file)
index 0000000..74fcdcd
--- /dev/null
@@ -0,0 +1,109 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ed25519_test
+
+import (
+       "crypto/ed25519"
+       "encoding/hex"
+       "encoding/json"
+       "internal/testenv"
+       "os"
+       "os/exec"
+       "path/filepath"
+       "testing"
+)
+
+// TestEd25519Vectors runs a very large set of test vectors that exercise all
+// combinations of low-order points, low-order components, and non-canonical
+// encodings. These vectors lock in unspecified and spec-divergent behaviors in
+// edge cases that are not security relevant in most contexts, but that can
+// cause issues in consensus applications if changed.
+//
+// Our behavior matches the "classic" unwritten verification rules of the
+// "ref10" reference implementation.
+//
+// Note that although we test for these edge cases, they are not covered by the
+// Go 1 Compatibility Promise. Applications that need stable verification rules
+// should use github.com/hdevalence/ed25519consensus.
+//
+// See https://hdevalence.ca/blog/2020-10-04-its-25519am for more details.
+func TestEd25519Vectors(t *testing.T) {
+       jsonVectors := downloadEd25519Vectors(t)
+       var vectors []struct {
+               A, R, S, M string
+               Flags      []string
+       }
+       if err := json.Unmarshal(jsonVectors, &vectors); err != nil {
+               t.Fatal(err)
+       }
+       for i, v := range vectors {
+               expectedToVerify := true
+               for _, f := range v.Flags {
+                       switch f {
+                       // We use the simplified verification formula that doesn't multiply
+                       // by the cofactor, so any low order residue will cause the
+                       // signature not to verify.
+                       //
+                       // This is allowed, but not required, by RFC 8032.
+                       case "LowOrderResidue":
+                               expectedToVerify = false
+                       // Our point decoding allows non-canonical encodings (in violation
+                       // of RFC 8032) but R is not decoded: instead, R is recomputed and
+                       // compared bytewise against the canonical encoding.
+                       case "NonCanonicalR":
+                               expectedToVerify = false
+                       }
+               }
+
+               publicKey := decodeHex(t, v.A)
+               signature := append(decodeHex(t, v.R), decodeHex(t, v.S)...)
+               message := []byte(v.M)
+
+               didVerify := ed25519.Verify(publicKey, message, signature)
+               if didVerify && !expectedToVerify {
+                       t.Errorf("#%d: vector with flags %s unexpectedly verified", i, v.Flags)
+               }
+               if !didVerify && expectedToVerify {
+                       t.Errorf("#%d: vector with flags %s unexpectedly rejected", i, v.Flags)
+               }
+       }
+}
+
+func downloadEd25519Vectors(t *testing.T) []byte {
+       testenv.MustHaveExternalNetwork(t)
+
+       // Download the JSON test file from the GOPROXY with `go mod download`,
+       // pinning the version so test and module caching works as expected.
+       goTool := testenv.GoToolPath(t)
+       path := "filippo.io/mostly-harmless/ed25519vectors@v0.0.0-20210322192420-30a2d7243a94"
+       cmd := exec.Command(goTool, "mod", "download", "-json", path)
+       // TODO: enable the sumdb once the TryBots proxy supports it.
+       cmd.Env = append(os.Environ(), "GONOSUMDB=*")
+       output, err := cmd.Output()
+       if err != nil {
+               t.Fatalf("failed to run `go mod download -json %s`, output: %s", path, output)
+       }
+       var dm struct {
+               Dir string // absolute path to cached source root directory
+       }
+       if err := json.Unmarshal(output, &dm); err != nil {
+               t.Fatal(err)
+       }
+
+       jsonVectors, err := os.ReadFile(filepath.Join(dm.Dir, "ed25519vectors.json"))
+       if err != nil {
+               t.Fatalf("failed to read ed25519vectors.json: %v", err)
+       }
+       return jsonVectors
+}
+
+func decodeHex(t *testing.T, s string) []byte {
+       t.Helper()
+       b, err := hex.DecodeString(s)
+       if err != nil {
+               t.Errorf("invalid hex: %v", err)
+       }
+       return b
+}
diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/const.go b/libgo/go/crypto/ed25519/internal/edwards25519/const.go
deleted file mode 100644 (file)
index e39f086..0000000
+++ /dev/null
@@ -1,1422 +0,0 @@
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package edwards25519
-
-// These values are from the public domain, “ref10” implementation of ed25519
-// from SUPERCOP.
-
-// d is a constant in the Edwards curve equation.
-var d = FieldElement{
-       -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116,
-}
-
-// d2 is 2*d.
-var d2 = FieldElement{
-       -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199,
-}
-
-// SqrtM1 is the square-root of -1 in the field.
-var SqrtM1 = FieldElement{
-       -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482,
-}
-
-// A is a constant in the Montgomery-form of curve25519.
-var A = FieldElement{
-       486662, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-}
-
-// bi contains precomputed multiples of the base-point. See the Ed25519 paper
-// for a discussion about how these values are used.
-var bi = [8]PreComputedGroupElement{
-       {
-               FieldElement{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605},
-               FieldElement{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378},
-               FieldElement{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546},
-       },
-       {
-               FieldElement{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024},
-               FieldElement{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574},
-               FieldElement{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357},
-       },
-       {
-               FieldElement{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380},
-               FieldElement{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306},
-               FieldElement{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942},
-       },
-       {
-               FieldElement{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766},
-               FieldElement{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701},
-               FieldElement{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300},
-       },
-       {
-               FieldElement{-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877},
-               FieldElement{-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951},
-               FieldElement{4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784},
-       },
-       {
-               FieldElement{-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436},
-               FieldElement{25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918},
-               FieldElement{23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877},
-       },
-       {
-               FieldElement{-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800},
-               FieldElement{-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305},
-               FieldElement{-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300},
-       },
-       {
-               FieldElement{-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876},
-               FieldElement{-24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619},
-               FieldElement{-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683},
-       },
-}
-
-// base contains precomputed multiples of the base-point. See the Ed25519 paper
-// for a discussion about how these values are used.
-var base = [32][8]PreComputedGroupElement{
-       {
-               {
-                       FieldElement{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605},
-                       FieldElement{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378},
-                       FieldElement{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546},
-               },
-               {
-                       FieldElement{-12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303},
-                       FieldElement{-21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081},
-                       FieldElement{26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697},
-               },
-               {
-                       FieldElement{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024},
-                       FieldElement{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574},
-                       FieldElement{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357},
-               },
-               {
-                       FieldElement{-17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540},
-                       FieldElement{23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397},
-                       FieldElement{7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325},
-               },
-               {
-                       FieldElement{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380},
-                       FieldElement{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306},
-                       FieldElement{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942},
-               },
-               {
-                       FieldElement{-15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777},
-                       FieldElement{-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737},
-                       FieldElement{-18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652},
-               },
-               {
-                       FieldElement{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766},
-                       FieldElement{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701},
-                       FieldElement{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300},
-               },
-               {
-                       FieldElement{14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726},
-                       FieldElement{-7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955},
-                       FieldElement{27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425},
-               },
-       },
-       {
-               {
-                       FieldElement{-13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171},
-                       FieldElement{27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510},
-                       FieldElement{17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660},
-               },
-               {
-                       FieldElement{-10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639},
-                       FieldElement{29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963},
-                       FieldElement{5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950},
-               },
-               {
-                       FieldElement{-27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568},
-                       FieldElement{12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335},
-                       FieldElement{25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628},
-               },
-               {
-                       FieldElement{-26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007},
-                       FieldElement{-2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772},
-                       FieldElement{-22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653},
-               },
-               {
-                       FieldElement{2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567},
-                       FieldElement{13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686},
-                       FieldElement{21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372},
-               },
-               {
-                       FieldElement{-13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887},
-                       FieldElement{-23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954},
-                       FieldElement{-29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953},
-               },
-               {
-                       FieldElement{24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833},
-                       FieldElement{-16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532},
-                       FieldElement{-22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876},
-               },
-               {
-                       FieldElement{2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268},
-                       FieldElement{33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214},
-                       FieldElement{1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038},
-               },
-       },
-       {
-               {
-                       FieldElement{6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800},
-                       FieldElement{4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645},
-                       FieldElement{-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664},
-               },
-               {
-                       FieldElement{1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933},
-                       FieldElement{-25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182},
-                       FieldElement{-17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222},
-               },
-               {
-                       FieldElement{-18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991},
-                       FieldElement{20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880},
-                       FieldElement{9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092},
-               },
-               {
-                       FieldElement{-16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295},
-                       FieldElement{19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788},
-                       FieldElement{8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553},
-               },
-               {
-                       FieldElement{-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026},
-                       FieldElement{11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347},
-                       FieldElement{-18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033},
-               },
-               {
-                       FieldElement{-23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395},
-                       FieldElement{-27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278},
-                       FieldElement{1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890},
-               },
-               {
-                       FieldElement{32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995},
-                       FieldElement{-30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596},
-                       FieldElement{-11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891},
-               },
-               {
-                       FieldElement{31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060},
-                       FieldElement{11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608},
-                       FieldElement{-20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606},
-               },
-       },
-       {
-               {
-                       FieldElement{7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389},
-                       FieldElement{-19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016},
-                       FieldElement{-11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341},
-               },
-               {
-                       FieldElement{-22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505},
-                       FieldElement{14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553},
-                       FieldElement{-28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655},
-               },
-               {
-                       FieldElement{15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220},
-                       FieldElement{12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631},
-                       FieldElement{-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099},
-               },
-               {
-                       FieldElement{26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556},
-                       FieldElement{14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749},
-                       FieldElement{236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930},
-               },
-               {
-                       FieldElement{1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391},
-                       FieldElement{5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253},
-                       FieldElement{20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066},
-               },
-               {
-                       FieldElement{24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958},
-                       FieldElement{-11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082},
-                       FieldElement{-28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383},
-               },
-               {
-                       FieldElement{-30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521},
-                       FieldElement{-11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807},
-                       FieldElement{23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948},
-               },
-               {
-                       FieldElement{9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134},
-                       FieldElement{-32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455},
-                       FieldElement{27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629},
-               },
-       },
-       {
-               {
-                       FieldElement{-8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069},
-                       FieldElement{-32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746},
-                       FieldElement{24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919},
-               },
-               {
-                       FieldElement{11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837},
-                       FieldElement{8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906},
-                       FieldElement{-28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771},
-               },
-               {
-                       FieldElement{-25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817},
-                       FieldElement{10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098},
-                       FieldElement{10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409},
-               },
-               {
-                       FieldElement{-12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504},
-                       FieldElement{-26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727},
-                       FieldElement{28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420},
-               },
-               {
-                       FieldElement{-32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003},
-                       FieldElement{-1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605},
-                       FieldElement{-30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384},
-               },
-               {
-                       FieldElement{-26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701},
-                       FieldElement{-23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683},
-                       FieldElement{29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708},
-               },
-               {
-                       FieldElement{-3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563},
-                       FieldElement{-19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260},
-                       FieldElement{-5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387},
-               },
-               {
-                       FieldElement{-19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672},
-                       FieldElement{23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686},
-                       FieldElement{-24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665},
-               },
-       },
-       {
-               {
-                       FieldElement{11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182},
-                       FieldElement{-31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277},
-                       FieldElement{14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628},
-               },
-               {
-                       FieldElement{-4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474},
-                       FieldElement{-26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539},
-                       FieldElement{-25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822},
-               },
-               {
-                       FieldElement{-10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970},
-                       FieldElement{19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756},
-                       FieldElement{-24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508},
-               },
-               {
-                       FieldElement{-26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683},
-                       FieldElement{-10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655},
-                       FieldElement{-20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158},
-               },
-               {
-                       FieldElement{-4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125},
-                       FieldElement{-15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839},
-                       FieldElement{-20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664},
-               },
-               {
-                       FieldElement{27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294},
-                       FieldElement{-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899},
-                       FieldElement{-11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070},
-               },
-               {
-                       FieldElement{3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294},
-                       FieldElement{-15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949},
-                       FieldElement{-21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083},
-               },
-               {
-                       FieldElement{31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420},
-                       FieldElement{-5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940},
-                       FieldElement{29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396},
-               },
-       },
-       {
-               {
-                       FieldElement{-12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567},
-                       FieldElement{20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127},
-                       FieldElement{-16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294},
-               },
-               {
-                       FieldElement{-12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887},
-                       FieldElement{22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964},
-                       FieldElement{16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195},
-               },
-               {
-                       FieldElement{9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244},
-                       FieldElement{24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999},
-                       FieldElement{-1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762},
-               },
-               {
-                       FieldElement{-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274},
-                       FieldElement{-33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236},
-                       FieldElement{-16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605},
-               },
-               {
-                       FieldElement{-13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761},
-                       FieldElement{-22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884},
-                       FieldElement{-6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482},
-               },
-               {
-                       FieldElement{-24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638},
-                       FieldElement{-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490},
-                       FieldElement{-32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170},
-               },
-               {
-                       FieldElement{5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736},
-                       FieldElement{10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124},
-                       FieldElement{-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392},
-               },
-               {
-                       FieldElement{8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029},
-                       FieldElement{6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048},
-                       FieldElement{28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958},
-               },
-       },
-       {
-               {
-                       FieldElement{24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593},
-                       FieldElement{26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071},
-                       FieldElement{-11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692},
-               },
-               {
-                       FieldElement{11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687},
-                       FieldElement{-160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441},
-                       FieldElement{-20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001},
-               },
-               {
-                       FieldElement{-938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460},
-                       FieldElement{-19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007},
-                       FieldElement{-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762},
-               },
-               {
-                       FieldElement{15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005},
-                       FieldElement{-9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674},
-                       FieldElement{4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035},
-               },
-               {
-                       FieldElement{7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590},
-                       FieldElement{-2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957},
-                       FieldElement{-30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812},
-               },
-               {
-                       FieldElement{33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740},
-                       FieldElement{-18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122},
-                       FieldElement{-27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158},
-               },
-               {
-                       FieldElement{8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885},
-                       FieldElement{26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140},
-                       FieldElement{19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857},
-               },
-               {
-                       FieldElement{801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155},
-                       FieldElement{19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260},
-                       FieldElement{19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483},
-               },
-       },
-       {
-               {
-                       FieldElement{-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677},
-                       FieldElement{32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815},
-                       FieldElement{22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751},
-               },
-               {
-                       FieldElement{-16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203},
-                       FieldElement{-11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208},
-                       FieldElement{1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230},
-               },
-               {
-                       FieldElement{16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850},
-                       FieldElement{-21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389},
-                       FieldElement{-9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968},
-               },
-               {
-                       FieldElement{-11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689},
-                       FieldElement{14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880},
-                       FieldElement{5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304},
-               },
-               {
-                       FieldElement{30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632},
-                       FieldElement{-3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412},
-                       FieldElement{20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566},
-               },
-               {
-                       FieldElement{-20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038},
-                       FieldElement{-26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232},
-                       FieldElement{-1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943},
-               },
-               {
-                       FieldElement{17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856},
-                       FieldElement{23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738},
-                       FieldElement{15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971},
-               },
-               {
-                       FieldElement{-27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718},
-                       FieldElement{-13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697},
-                       FieldElement{-11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883},
-               },
-       },
-       {
-               {
-                       FieldElement{5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912},
-                       FieldElement{-26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358},
-                       FieldElement{3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849},
-               },
-               {
-                       FieldElement{29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307},
-                       FieldElement{-14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977},
-                       FieldElement{-6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335},
-               },
-               {
-                       FieldElement{-29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644},
-                       FieldElement{-22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616},
-                       FieldElement{-27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735},
-               },
-               {
-                       FieldElement{-21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099},
-                       FieldElement{29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341},
-                       FieldElement{-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336},
-               },
-               {
-                       FieldElement{-23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646},
-                       FieldElement{31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425},
-                       FieldElement{-17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388},
-               },
-               {
-                       FieldElement{-31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743},
-                       FieldElement{-16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822},
-                       FieldElement{-8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462},
-               },
-               {
-                       FieldElement{18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985},
-                       FieldElement{9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702},
-                       FieldElement{-22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797},
-               },
-               {
-                       FieldElement{21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293},
-                       FieldElement{27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100},
-                       FieldElement{19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688},
-               },
-       },
-       {
-               {
-                       FieldElement{12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186},
-                       FieldElement{2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610},
-                       FieldElement{-2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707},
-               },
-               {
-                       FieldElement{7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220},
-                       FieldElement{915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025},
-                       FieldElement{32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044},
-               },
-               {
-                       FieldElement{32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992},
-                       FieldElement{-4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027},
-                       FieldElement{21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197},
-               },
-               {
-                       FieldElement{8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901},
-                       FieldElement{31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952},
-                       FieldElement{19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878},
-               },
-               {
-                       FieldElement{-28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390},
-                       FieldElement{32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730},
-                       FieldElement{2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730},
-               },
-               {
-                       FieldElement{-19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180},
-                       FieldElement{-30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272},
-                       FieldElement{-15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715},
-               },
-               {
-                       FieldElement{-22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970},
-                       FieldElement{-31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772},
-                       FieldElement{-17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865},
-               },
-               {
-                       FieldElement{15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750},
-                       FieldElement{20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373},
-                       FieldElement{32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348},
-               },
-       },
-       {
-               {
-                       FieldElement{9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144},
-                       FieldElement{-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195},
-                       FieldElement{5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086},
-               },
-               {
-                       FieldElement{-13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684},
-                       FieldElement{-8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518},
-                       FieldElement{-2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233},
-               },
-               {
-                       FieldElement{-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793},
-                       FieldElement{-2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794},
-                       FieldElement{580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435},
-               },
-               {
-                       FieldElement{23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921},
-                       FieldElement{13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518},
-                       FieldElement{2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563},
-               },
-               {
-                       FieldElement{14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278},
-                       FieldElement{-27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024},
-                       FieldElement{4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030},
-               },
-               {
-                       FieldElement{10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783},
-                       FieldElement{27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717},
-                       FieldElement{6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844},
-               },
-               {
-                       FieldElement{14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333},
-                       FieldElement{16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048},
-                       FieldElement{22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760},
-               },
-               {
-                       FieldElement{-4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760},
-                       FieldElement{-15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757},
-                       FieldElement{-2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112},
-               },
-       },
-       {
-               {
-                       FieldElement{-19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468},
-                       FieldElement{3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184},
-                       FieldElement{10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289},
-               },
-               {
-                       FieldElement{15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066},
-                       FieldElement{24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882},
-                       FieldElement{13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226},
-               },
-               {
-                       FieldElement{16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101},
-                       FieldElement{29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279},
-                       FieldElement{-6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811},
-               },
-               {
-                       FieldElement{27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709},
-                       FieldElement{20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714},
-                       FieldElement{-2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121},
-               },
-               {
-                       FieldElement{9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464},
-                       FieldElement{12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847},
-                       FieldElement{13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400},
-               },
-               {
-                       FieldElement{4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414},
-                       FieldElement{-15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158},
-                       FieldElement{17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045},
-               },
-               {
-                       FieldElement{-461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415},
-                       FieldElement{-5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459},
-                       FieldElement{-31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079},
-               },
-               {
-                       FieldElement{21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412},
-                       FieldElement{-20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743},
-                       FieldElement{-14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836},
-               },
-       },
-       {
-               {
-                       FieldElement{12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022},
-                       FieldElement{18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429},
-                       FieldElement{-6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065},
-               },
-               {
-                       FieldElement{30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861},
-                       FieldElement{10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000},
-                       FieldElement{-33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101},
-               },
-               {
-                       FieldElement{32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815},
-                       FieldElement{29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642},
-                       FieldElement{10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966},
-               },
-               {
-                       FieldElement{25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574},
-                       FieldElement{-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742},
-                       FieldElement{-18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689},
-               },
-               {
-                       FieldElement{12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020},
-                       FieldElement{-10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772},
-                       FieldElement{3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982},
-               },
-               {
-                       FieldElement{-14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953},
-                       FieldElement{-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218},
-                       FieldElement{-17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265},
-               },
-               {
-                       FieldElement{29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073},
-                       FieldElement{-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325},
-                       FieldElement{-11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798},
-               },
-               {
-                       FieldElement{-4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870},
-                       FieldElement{-7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863},
-                       FieldElement{-13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927},
-               },
-       },
-       {
-               {
-                       FieldElement{-2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267},
-                       FieldElement{-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663},
-                       FieldElement{22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862},
-               },
-               {
-                       FieldElement{-25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673},
-                       FieldElement{15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943},
-                       FieldElement{15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020},
-               },
-               {
-                       FieldElement{-4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238},
-                       FieldElement{11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064},
-                       FieldElement{14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795},
-               },
-               {
-                       FieldElement{15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052},
-                       FieldElement{-10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904},
-                       FieldElement{29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531},
-               },
-               {
-                       FieldElement{-13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979},
-                       FieldElement{-5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841},
-                       FieldElement{10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431},
-               },
-               {
-                       FieldElement{10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324},
-                       FieldElement{-31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940},
-                       FieldElement{10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320},
-               },
-               {
-                       FieldElement{-15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184},
-                       FieldElement{14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114},
-                       FieldElement{30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878},
-               },
-               {
-                       FieldElement{12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784},
-                       FieldElement{-2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091},
-                       FieldElement{-16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585},
-               },
-       },
-       {
-               {
-                       FieldElement{-8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208},
-                       FieldElement{10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864},
-                       FieldElement{17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661},
-               },
-               {
-                       FieldElement{7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233},
-                       FieldElement{26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212},
-                       FieldElement{-12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525},
-               },
-               {
-                       FieldElement{-24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068},
-                       FieldElement{9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397},
-                       FieldElement{-8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988},
-               },
-               {
-                       FieldElement{5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889},
-                       FieldElement{32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038},
-                       FieldElement{14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697},
-               },
-               {
-                       FieldElement{20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875},
-                       FieldElement{-25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905},
-                       FieldElement{-25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656},
-               },
-               {
-                       FieldElement{11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818},
-                       FieldElement{27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714},
-                       FieldElement{10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203},
-               },
-               {
-                       FieldElement{20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931},
-                       FieldElement{-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024},
-                       FieldElement{-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084},
-               },
-               {
-                       FieldElement{-1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204},
-                       FieldElement{20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817},
-                       FieldElement{27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667},
-               },
-       },
-       {
-               {
-                       FieldElement{11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504},
-                       FieldElement{-12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768},
-                       FieldElement{-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255},
-               },
-               {
-                       FieldElement{6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790},
-                       FieldElement{1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438},
-                       FieldElement{-22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333},
-               },
-               {
-                       FieldElement{17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971},
-                       FieldElement{31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905},
-                       FieldElement{29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409},
-               },
-               {
-                       FieldElement{12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409},
-                       FieldElement{6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499},
-                       FieldElement{-8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363},
-               },
-               {
-                       FieldElement{28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664},
-                       FieldElement{-11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324},
-                       FieldElement{-21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940},
-               },
-               {
-                       FieldElement{13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990},
-                       FieldElement{-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914},
-                       FieldElement{-25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290},
-               },
-               {
-                       FieldElement{24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257},
-                       FieldElement{-6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433},
-                       FieldElement{-16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236},
-               },
-               {
-                       FieldElement{-12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045},
-                       FieldElement{11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093},
-                       FieldElement{-1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347},
-               },
-       },
-       {
-               {
-                       FieldElement{-28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191},
-                       FieldElement{-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507},
-                       FieldElement{-12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906},
-               },
-               {
-                       FieldElement{3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018},
-                       FieldElement{-16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109},
-                       FieldElement{-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926},
-               },
-               {
-                       FieldElement{-24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528},
-                       FieldElement{8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625},
-                       FieldElement{-32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286},
-               },
-               {
-                       FieldElement{2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033},
-                       FieldElement{27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866},
-                       FieldElement{21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896},
-               },
-               {
-                       FieldElement{30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075},
-                       FieldElement{26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347},
-                       FieldElement{-22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437},
-               },
-               {
-                       FieldElement{-5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165},
-                       FieldElement{-18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588},
-                       FieldElement{-32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193},
-               },
-               {
-                       FieldElement{-19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017},
-                       FieldElement{-28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883},
-                       FieldElement{21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961},
-               },
-               {
-                       FieldElement{8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043},
-                       FieldElement{29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663},
-                       FieldElement{-20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362},
-               },
-       },
-       {
-               {
-                       FieldElement{-33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860},
-                       FieldElement{2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466},
-                       FieldElement{-24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063},
-               },
-               {
-                       FieldElement{-26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997},
-                       FieldElement{-1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295},
-                       FieldElement{-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369},
-               },
-               {
-                       FieldElement{9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385},
-                       FieldElement{18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109},
-                       FieldElement{2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906},
-               },
-               {
-                       FieldElement{4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424},
-                       FieldElement{-19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185},
-                       FieldElement{7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962},
-               },
-               {
-                       FieldElement{-7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325},
-                       FieldElement{10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593},
-                       FieldElement{696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404},
-               },
-               {
-                       FieldElement{-11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644},
-                       FieldElement{17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801},
-                       FieldElement{26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804},
-               },
-               {
-                       FieldElement{-31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884},
-                       FieldElement{-586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577},
-                       FieldElement{-9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849},
-               },
-               {
-                       FieldElement{32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473},
-                       FieldElement{-8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644},
-                       FieldElement{-2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319},
-               },
-       },
-       {
-               {
-                       FieldElement{-11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599},
-                       FieldElement{-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768},
-                       FieldElement{-27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084},
-               },
-               {
-                       FieldElement{-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328},
-                       FieldElement{-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369},
-                       FieldElement{20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920},
-               },
-               {
-                       FieldElement{12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815},
-                       FieldElement{-32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025},
-                       FieldElement{-21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397},
-               },
-               {
-                       FieldElement{-20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448},
-                       FieldElement{6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981},
-                       FieldElement{30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165},
-               },
-               {
-                       FieldElement{32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501},
-                       FieldElement{17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073},
-                       FieldElement{-1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861},
-               },
-               {
-                       FieldElement{14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845},
-                       FieldElement{-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211},
-                       FieldElement{18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870},
-               },
-               {
-                       FieldElement{10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096},
-                       FieldElement{33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803},
-                       FieldElement{-32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168},
-               },
-               {
-                       FieldElement{30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965},
-                       FieldElement{-14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505},
-                       FieldElement{18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598},
-               },
-       },
-       {
-               {
-                       FieldElement{5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782},
-                       FieldElement{5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900},
-                       FieldElement{-31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479},
-               },
-               {
-                       FieldElement{-12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208},
-                       FieldElement{8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232},
-                       FieldElement{17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719},
-               },
-               {
-                       FieldElement{16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271},
-                       FieldElement{-4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326},
-                       FieldElement{-8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132},
-               },
-               {
-                       FieldElement{14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300},
-                       FieldElement{8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570},
-                       FieldElement{15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670},
-               },
-               {
-                       FieldElement{-2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994},
-                       FieldElement{-12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913},
-                       FieldElement{31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317},
-               },
-               {
-                       FieldElement{-25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730},
-                       FieldElement{842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096},
-                       FieldElement{-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078},
-               },
-               {
-                       FieldElement{-15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411},
-                       FieldElement{-19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905},
-                       FieldElement{-9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654},
-               },
-               {
-                       FieldElement{-28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870},
-                       FieldElement{-23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498},
-                       FieldElement{12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579},
-               },
-       },
-       {
-               {
-                       FieldElement{14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677},
-                       FieldElement{10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647},
-                       FieldElement{-2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743},
-               },
-               {
-                       FieldElement{-25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468},
-                       FieldElement{21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375},
-                       FieldElement{-25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155},
-               },
-               {
-                       FieldElement{6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725},
-                       FieldElement{-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612},
-                       FieldElement{-10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943},
-               },
-               {
-                       FieldElement{-30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944},
-                       FieldElement{30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928},
-                       FieldElement{9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406},
-               },
-               {
-                       FieldElement{22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139},
-                       FieldElement{-8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963},
-                       FieldElement{-31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693},
-               },
-               {
-                       FieldElement{1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734},
-                       FieldElement{-448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680},
-                       FieldElement{-24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410},
-               },
-               {
-                       FieldElement{-9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931},
-                       FieldElement{-16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654},
-                       FieldElement{22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710},
-               },
-               {
-                       FieldElement{29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180},
-                       FieldElement{-26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684},
-                       FieldElement{-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895},
-               },
-       },
-       {
-               {
-                       FieldElement{22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501},
-                       FieldElement{-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413},
-                       FieldElement{6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880},
-               },
-               {
-                       FieldElement{-8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874},
-                       FieldElement{22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962},
-                       FieldElement{-7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899},
-               },
-               {
-                       FieldElement{21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152},
-                       FieldElement{9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063},
-                       FieldElement{7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080},
-               },
-               {
-                       FieldElement{-9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146},
-                       FieldElement{-17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183},
-                       FieldElement{-19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133},
-               },
-               {
-                       FieldElement{-32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421},
-                       FieldElement{-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622},
-                       FieldElement{-4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197},
-               },
-               {
-                       FieldElement{2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663},
-                       FieldElement{31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753},
-                       FieldElement{4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755},
-               },
-               {
-                       FieldElement{-9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862},
-                       FieldElement{-26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118},
-                       FieldElement{26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171},
-               },
-               {
-                       FieldElement{15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380},
-                       FieldElement{16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824},
-                       FieldElement{28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270},
-               },
-       },
-       {
-               {
-                       FieldElement{-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438},
-                       FieldElement{-31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584},
-                       FieldElement{-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562},
-               },
-               {
-                       FieldElement{30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471},
-                       FieldElement{18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610},
-                       FieldElement{19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269},
-               },
-               {
-                       FieldElement{-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650},
-                       FieldElement{14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369},
-                       FieldElement{19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461},
-               },
-               {
-                       FieldElement{30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462},
-                       FieldElement{-5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793},
-                       FieldElement{-2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218},
-               },
-               {
-                       FieldElement{-24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226},
-                       FieldElement{18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019},
-                       FieldElement{-15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037},
-               },
-               {
-                       FieldElement{31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171},
-                       FieldElement{-17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132},
-                       FieldElement{-28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841},
-               },
-               {
-                       FieldElement{21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181},
-                       FieldElement{-33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210},
-                       FieldElement{-1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040},
-               },
-               {
-                       FieldElement{3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935},
-                       FieldElement{24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105},
-                       FieldElement{-28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814},
-               },
-       },
-       {
-               {
-                       FieldElement{793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852},
-                       FieldElement{5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581},
-                       FieldElement{-4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646},
-               },
-               {
-                       FieldElement{10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844},
-                       FieldElement{10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025},
-                       FieldElement{27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453},
-               },
-               {
-                       FieldElement{-23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068},
-                       FieldElement{4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192},
-                       FieldElement{-17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921},
-               },
-               {
-                       FieldElement{-9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259},
-                       FieldElement{-12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426},
-                       FieldElement{-5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072},
-               },
-               {
-                       FieldElement{-17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305},
-                       FieldElement{13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832},
-                       FieldElement{28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943},
-               },
-               {
-                       FieldElement{-16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011},
-                       FieldElement{24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447},
-                       FieldElement{17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494},
-               },
-               {
-                       FieldElement{-28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245},
-                       FieldElement{-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859},
-                       FieldElement{28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915},
-               },
-               {
-                       FieldElement{16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707},
-                       FieldElement{10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848},
-                       FieldElement{-11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224},
-               },
-       },
-       {
-               {
-                       FieldElement{-25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391},
-                       FieldElement{15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215},
-                       FieldElement{-23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101},
-               },
-               {
-                       FieldElement{23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713},
-                       FieldElement{21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849},
-                       FieldElement{-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930},
-               },
-               {
-                       FieldElement{-29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940},
-                       FieldElement{-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031},
-                       FieldElement{-17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404},
-               },
-               {
-                       FieldElement{-25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243},
-                       FieldElement{-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116},
-                       FieldElement{-24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525},
-               },
-               {
-                       FieldElement{-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509},
-                       FieldElement{-10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883},
-                       FieldElement{15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865},
-               },
-               {
-                       FieldElement{-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660},
-                       FieldElement{4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273},
-                       FieldElement{-28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138},
-               },
-               {
-                       FieldElement{-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560},
-                       FieldElement{-10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135},
-                       FieldElement{2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941},
-               },
-               {
-                       FieldElement{-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739},
-                       FieldElement{18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756},
-                       FieldElement{-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819},
-               },
-       },
-       {
-               {
-                       FieldElement{-6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347},
-                       FieldElement{-27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028},
-                       FieldElement{21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075},
-               },
-               {
-                       FieldElement{16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799},
-                       FieldElement{-2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609},
-                       FieldElement{-25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817},
-               },
-               {
-                       FieldElement{-23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989},
-                       FieldElement{-30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523},
-                       FieldElement{4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278},
-               },
-               {
-                       FieldElement{31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045},
-                       FieldElement{19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377},
-                       FieldElement{24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480},
-               },
-               {
-                       FieldElement{17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016},
-                       FieldElement{510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426},
-                       FieldElement{18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525},
-               },
-               {
-                       FieldElement{13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396},
-                       FieldElement{9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080},
-                       FieldElement{12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892},
-               },
-               {
-                       FieldElement{15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275},
-                       FieldElement{11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074},
-                       FieldElement{20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140},
-               },
-               {
-                       FieldElement{-16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717},
-                       FieldElement{-1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101},
-                       FieldElement{24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127},
-               },
-       },
-       {
-               {
-                       FieldElement{-12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632},
-                       FieldElement{-26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415},
-                       FieldElement{-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160},
-               },
-               {
-                       FieldElement{31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876},
-                       FieldElement{22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625},
-                       FieldElement{-15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478},
-               },
-               {
-                       FieldElement{27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164},
-                       FieldElement{26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595},
-                       FieldElement{-7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248},
-               },
-               {
-                       FieldElement{-16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858},
-                       FieldElement{15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193},
-                       FieldElement{8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184},
-               },
-               {
-                       FieldElement{-18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942},
-                       FieldElement{-1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635},
-                       FieldElement{21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948},
-               },
-               {
-                       FieldElement{11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935},
-                       FieldElement{-25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415},
-                       FieldElement{-15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416},
-               },
-               {
-                       FieldElement{-7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018},
-                       FieldElement{4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778},
-                       FieldElement{366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659},
-               },
-               {
-                       FieldElement{-24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385},
-                       FieldElement{18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503},
-                       FieldElement{476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329},
-               },
-       },
-       {
-               {
-                       FieldElement{20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056},
-                       FieldElement{-13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838},
-                       FieldElement{24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948},
-               },
-               {
-                       FieldElement{-3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691},
-                       FieldElement{-15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118},
-                       FieldElement{-23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517},
-               },
-               {
-                       FieldElement{-20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269},
-                       FieldElement{-6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904},
-                       FieldElement{-23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589},
-               },
-               {
-                       FieldElement{-28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193},
-                       FieldElement{-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910},
-                       FieldElement{-30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930},
-               },
-               {
-                       FieldElement{-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667},
-                       FieldElement{25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481},
-                       FieldElement{-9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876},
-               },
-               {
-                       FieldElement{22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640},
-                       FieldElement{-8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278},
-                       FieldElement{-21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112},
-               },
-               {
-                       FieldElement{26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272},
-                       FieldElement{17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012},
-                       FieldElement{-10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221},
-               },
-               {
-                       FieldElement{30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046},
-                       FieldElement{13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345},
-                       FieldElement{-19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310},
-               },
-       },
-       {
-               {
-                       FieldElement{19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937},
-                       FieldElement{31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636},
-                       FieldElement{-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008},
-               },
-               {
-                       FieldElement{-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429},
-                       FieldElement{-15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576},
-                       FieldElement{31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066},
-               },
-               {
-                       FieldElement{-9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490},
-                       FieldElement{-12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104},
-                       FieldElement{33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053},
-               },
-               {
-                       FieldElement{31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275},
-                       FieldElement{-20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511},
-                       FieldElement{22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095},
-               },
-               {
-                       FieldElement{-28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439},
-                       FieldElement{23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939},
-                       FieldElement{-23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424},
-               },
-               {
-                       FieldElement{2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310},
-                       FieldElement{3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608},
-                       FieldElement{-32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079},
-               },
-               {
-                       FieldElement{-23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101},
-                       FieldElement{21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418},
-                       FieldElement{18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576},
-               },
-               {
-                       FieldElement{30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356},
-                       FieldElement{9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996},
-                       FieldElement{-26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099},
-               },
-       },
-       {
-               {
-                       FieldElement{-26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728},
-                       FieldElement{-13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658},
-                       FieldElement{-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242},
-               },
-               {
-                       FieldElement{-21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001},
-                       FieldElement{-4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766},
-                       FieldElement{18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373},
-               },
-               {
-                       FieldElement{26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458},
-                       FieldElement{-17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628},
-                       FieldElement{-13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657},
-               },
-               {
-                       FieldElement{-23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062},
-                       FieldElement{25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616},
-                       FieldElement{31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014},
-               },
-               {
-                       FieldElement{24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383},
-                       FieldElement{-25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814},
-                       FieldElement{-20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718},
-               },
-               {
-                       FieldElement{30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417},
-                       FieldElement{2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222},
-                       FieldElement{33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444},
-               },
-               {
-                       FieldElement{-20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597},
-                       FieldElement{23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970},
-                       FieldElement{1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799},
-               },
-               {
-                       FieldElement{-5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647},
-                       FieldElement{13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511},
-                       FieldElement{-29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032},
-               },
-       },
-       {
-               {
-                       FieldElement{9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834},
-                       FieldElement{-23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461},
-                       FieldElement{29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062},
-               },
-               {
-                       FieldElement{-25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516},
-                       FieldElement{-20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547},
-                       FieldElement{-24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240},
-               },
-               {
-                       FieldElement{-17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038},
-                       FieldElement{-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741},
-                       FieldElement{16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103},
-               },
-               {
-                       FieldElement{-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747},
-                       FieldElement{-1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323},
-                       FieldElement{31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016},
-               },
-               {
-                       FieldElement{-14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373},
-                       FieldElement{15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228},
-                       FieldElement{-2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141},
-               },
-               {
-                       FieldElement{16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399},
-                       FieldElement{11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831},
-                       FieldElement{-185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376},
-               },
-               {
-                       FieldElement{-32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313},
-                       FieldElement{-18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958},
-                       FieldElement{-6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577},
-               },
-               {
-                       FieldElement{-22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743},
-                       FieldElement{29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684},
-                       FieldElement{-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476},
-               },
-       },
-}
diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/doc.go b/libgo/go/crypto/ed25519/internal/edwards25519/doc.go
new file mode 100644 (file)
index 0000000..ff31cd2
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright (c) 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package edwards25519 implements group logic for the twisted Edwards curve
+//
+//     -x^2 + y^2 = 1 + -(121665/121666)*x^2*y^2
+//
+// This is better known as the Edwards curve equivalent to Curve25519, and is
+// the curve used by the Ed25519 signature scheme.
+//
+// Most users don't need this package, and should instead use crypto/ed25519 for
+// signatures, golang.org/x/crypto/curve25519 for Diffie-Hellman, or
+// github.com/gtank/ristretto255 for prime order group logic.
+//
+// However, developers who do need to interact with low-level edwards25519
+// operations can use filippo.io/edwards25519, an extended version of this
+// package repackaged as an importable module.
+//
+// (Note that filippo.io/edwards25519 and github.com/gtank/ristretto255 are not
+// maintained by the Go team and are not covered by the Go 1 Compatibility Promise.)
+package edwards25519
index b091481b7734d4f6b5916caa3c00a2acee241733..313e6c281cb74dacc732e49b73b2dbdef180eb0f 100644 (file)
-// Copyright 2016 The Go Authors. All rights reserved.
+// Copyright (c) 2017 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
 package edwards25519
 
-import "encoding/binary"
+import (
+       "crypto/ed25519/internal/edwards25519/field"
+       "errors"
+)
 
-// This code is a port of the public domain, “ref10” implementation of ed25519
-// from SUPERCOP.
+// Point types.
 
-// FieldElement represents an element of the field GF(2^255 - 19).  An element
-// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
-// t[3]+2^102 t[4]+...+2^230 t[9].  Bounds on each t[i] vary depending on
-// context.
-type FieldElement [10]int32
-
-var zero FieldElement
-
-func FeZero(fe *FieldElement) {
-       copy(fe[:], zero[:])
+type projP1xP1 struct {
+       X, Y, Z, T field.Element
 }
 
-func FeOne(fe *FieldElement) {
-       FeZero(fe)
-       fe[0] = 1
+type projP2 struct {
+       X, Y, Z field.Element
 }
 
-func FeAdd(dst, a, b *FieldElement) {
-       dst[0] = a[0] + b[0]
-       dst[1] = a[1] + b[1]
-       dst[2] = a[2] + b[2]
-       dst[3] = a[3] + b[3]
-       dst[4] = a[4] + b[4]
-       dst[5] = a[5] + b[5]
-       dst[6] = a[6] + b[6]
-       dst[7] = a[7] + b[7]
-       dst[8] = a[8] + b[8]
-       dst[9] = a[9] + b[9]
-}
+// Point represents a point on the edwards25519 curve.
+//
+// This type works similarly to math/big.Int, and all arguments and receivers
+// are allowed to alias.
+//
+// The zero value is NOT valid, and it may be used only as a receiver.
+type Point struct {
+       // The point is internally represented in extended coordinates (X, Y, Z, T)
+       // where x = X/Z, y = Y/Z, and xy = T/Z per https://eprint.iacr.org/2008/522.
+       x, y, z, t field.Element
 
-func FeSub(dst, a, b *FieldElement) {
-       dst[0] = a[0] - b[0]
-       dst[1] = a[1] - b[1]
-       dst[2] = a[2] - b[2]
-       dst[3] = a[3] - b[3]
-       dst[4] = a[4] - b[4]
-       dst[5] = a[5] - b[5]
-       dst[6] = a[6] - b[6]
-       dst[7] = a[7] - b[7]
-       dst[8] = a[8] - b[8]
-       dst[9] = a[9] - b[9]
+       // Make the type not comparable (i.e. used with == or as a map key), as
+       // equivalent points can be represented by different Go values.
+       _ incomparable
 }
 
-func FeCopy(dst, src *FieldElement) {
-       copy(dst[:], src[:])
-}
+type incomparable [0]func()
 
-// Replace (f,g) with (g,g) if b == 1;
-// replace (f,g) with (f,g) if b == 0.
-//
-// Preconditions: b in {0,1}.
-func FeCMove(f, g *FieldElement, b int32) {
-       b = -b
-       f[0] ^= b & (f[0] ^ g[0])
-       f[1] ^= b & (f[1] ^ g[1])
-       f[2] ^= b & (f[2] ^ g[2])
-       f[3] ^= b & (f[3] ^ g[3])
-       f[4] ^= b & (f[4] ^ g[4])
-       f[5] ^= b & (f[5] ^ g[5])
-       f[6] ^= b & (f[6] ^ g[6])
-       f[7] ^= b & (f[7] ^ g[7])
-       f[8] ^= b & (f[8] ^ g[8])
-       f[9] ^= b & (f[9] ^ g[9])
+func checkInitialized(points ...*Point) {
+       for _, p := range points {
+               if p.x == (field.Element{}) && p.y == (field.Element{}) {
+                       panic("edwards25519: use of uninitialized Point")
+               }
+       }
 }
 
-func load3(in []byte) int64 {
-       var r int64
-       r = int64(in[0])
-       r |= int64(in[1]) << 8
-       r |= int64(in[2]) << 16
-       return r
+type projCached struct {
+       YplusX, YminusX, Z, T2d field.Element
 }
 
-func load4(in []byte) int64 {
-       var r int64
-       r = int64(in[0])
-       r |= int64(in[1]) << 8
-       r |= int64(in[2]) << 16
-       r |= int64(in[3]) << 24
-       return r
+type affineCached struct {
+       YplusX, YminusX, T2d field.Element
 }
 
-func FeFromBytes(dst *FieldElement, src *[32]byte) {
-       h0 := load4(src[:])
-       h1 := load3(src[4:]) << 6
-       h2 := load3(src[7:]) << 5
-       h3 := load3(src[10:]) << 3
-       h4 := load3(src[13:]) << 2
-       h5 := load4(src[16:])
-       h6 := load3(src[20:]) << 7
-       h7 := load3(src[23:]) << 5
-       h8 := load3(src[26:]) << 4
-       h9 := (load3(src[29:]) & 8388607) << 2
-
-       FeCombine(dst, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9)
-}
+// Constructors.
 
-// FeToBytes marshals h to s.
-// Preconditions:
-//   |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
-//
-// Write p=2^255-19; q=floor(h/p).
-// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
-//
-// Proof:
-//   Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
-//   Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4.
-//
-//   Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
-//   Then 0<y<1.
-//
-//   Write r=h-pq.
-//   Have 0<=r<=p-1=2^255-20.
-//   Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
-//
-//   Write x=r+19(2^-255)r+y.
-//   Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
-//
-//   Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
-//   so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q.
-func FeToBytes(s *[32]byte, h *FieldElement) {
-       var carry [10]int32
-
-       q := (19*h[9] + (1 << 24)) >> 25
-       q = (h[0] + q) >> 26
-       q = (h[1] + q) >> 25
-       q = (h[2] + q) >> 26
-       q = (h[3] + q) >> 25
-       q = (h[4] + q) >> 26
-       q = (h[5] + q) >> 25
-       q = (h[6] + q) >> 26
-       q = (h[7] + q) >> 25
-       q = (h[8] + q) >> 26
-       q = (h[9] + q) >> 25
-
-       // Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20.
-       h[0] += 19 * q
-       // Goal: Output h-2^255 q, which is between 0 and 2^255-20.
-
-       carry[0] = h[0] >> 26
-       h[1] += carry[0]
-       h[0] -= carry[0] << 26
-       carry[1] = h[1] >> 25
-       h[2] += carry[1]
-       h[1] -= carry[1] << 25
-       carry[2] = h[2] >> 26
-       h[3] += carry[2]
-       h[2] -= carry[2] << 26
-       carry[3] = h[3] >> 25
-       h[4] += carry[3]
-       h[3] -= carry[3] << 25
-       carry[4] = h[4] >> 26
-       h[5] += carry[4]
-       h[4] -= carry[4] << 26
-       carry[5] = h[5] >> 25
-       h[6] += carry[5]
-       h[5] -= carry[5] << 25
-       carry[6] = h[6] >> 26
-       h[7] += carry[6]
-       h[6] -= carry[6] << 26
-       carry[7] = h[7] >> 25
-       h[8] += carry[7]
-       h[7] -= carry[7] << 25
-       carry[8] = h[8] >> 26
-       h[9] += carry[8]
-       h[8] -= carry[8] << 26
-       carry[9] = h[9] >> 25
-       h[9] -= carry[9] << 25
-       // h10 = carry9
-
-       // Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
-       // Have h[0]+...+2^230 h[9] between 0 and 2^255-1;
-       // evidently 2^255 h10-2^255 q = 0.
-       // Goal: Output h[0]+...+2^230 h[9].
-
-       s[0] = byte(h[0] >> 0)
-       s[1] = byte(h[0] >> 8)
-       s[2] = byte(h[0] >> 16)
-       s[3] = byte((h[0] >> 24) | (h[1] << 2))
-       s[4] = byte(h[1] >> 6)
-       s[5] = byte(h[1] >> 14)
-       s[6] = byte((h[1] >> 22) | (h[2] << 3))
-       s[7] = byte(h[2] >> 5)
-       s[8] = byte(h[2] >> 13)
-       s[9] = byte((h[2] >> 21) | (h[3] << 5))
-       s[10] = byte(h[3] >> 3)
-       s[11] = byte(h[3] >> 11)
-       s[12] = byte((h[3] >> 19) | (h[4] << 6))
-       s[13] = byte(h[4] >> 2)
-       s[14] = byte(h[4] >> 10)
-       s[15] = byte(h[4] >> 18)
-       s[16] = byte(h[5] >> 0)
-       s[17] = byte(h[5] >> 8)
-       s[18] = byte(h[5] >> 16)
-       s[19] = byte((h[5] >> 24) | (h[6] << 1))
-       s[20] = byte(h[6] >> 7)
-       s[21] = byte(h[6] >> 15)
-       s[22] = byte((h[6] >> 23) | (h[7] << 3))
-       s[23] = byte(h[7] >> 5)
-       s[24] = byte(h[7] >> 13)
-       s[25] = byte((h[7] >> 21) | (h[8] << 4))
-       s[26] = byte(h[8] >> 4)
-       s[27] = byte(h[8] >> 12)
-       s[28] = byte((h[8] >> 20) | (h[9] << 6))
-       s[29] = byte(h[9] >> 2)
-       s[30] = byte(h[9] >> 10)
-       s[31] = byte(h[9] >> 18)
+func (v *projP2) Zero() *projP2 {
+       v.X.Zero()
+       v.Y.One()
+       v.Z.One()
+       return v
 }
 
-func FeIsNegative(f *FieldElement) byte {
-       var s [32]byte
-       FeToBytes(&s, f)
-       return s[0] & 1
-}
+// identity is the point at infinity.
+var identity, _ = new(Point).SetBytes([]byte{
+       1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})
 
-func FeIsNonZero(f *FieldElement) int32 {
-       var s [32]byte
-       FeToBytes(&s, f)
-       var x uint8
-       for _, b := range s {
-               x |= b
-       }
-       x |= x >> 4
-       x |= x >> 2
-       x |= x >> 1
-       return int32(x & 1)
+// NewIdentityPoint returns a new Point set to the identity.
+func NewIdentityPoint() *Point {
+       return new(Point).Set(identity)
 }
 
-// FeNeg sets h = -f
-//
-// Preconditions:
-//    |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
-//
-// Postconditions:
-//    |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
-func FeNeg(h, f *FieldElement) {
-       h[0] = -f[0]
-       h[1] = -f[1]
-       h[2] = -f[2]
-       h[3] = -f[3]
-       h[4] = -f[4]
-       h[5] = -f[5]
-       h[6] = -f[6]
-       h[7] = -f[7]
-       h[8] = -f[8]
-       h[9] = -f[9]
-}
+// generator is the canonical curve basepoint. See TestGenerator for the
+// correspondence of this encoding with the values in RFC 8032.
+var generator, _ = new(Point).SetBytes([]byte{
+       0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+       0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+       0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+       0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66})
 
-func FeCombine(h *FieldElement, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) {
-       var c0, c1, c2, c3, c4, c5, c6, c7, c8, c9 int64
-
-       /*
-         |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38))
-           i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8
-         |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19))
-           i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9
-       */
-
-       c0 = (h0 + (1 << 25)) >> 26
-       h1 += c0
-       h0 -= c0 << 26
-       c4 = (h4 + (1 << 25)) >> 26
-       h5 += c4
-       h4 -= c4 << 26
-       /* |h0| <= 2^25 */
-       /* |h4| <= 2^25 */
-       /* |h1| <= 1.51*2^58 */
-       /* |h5| <= 1.51*2^58 */
-
-       c1 = (h1 + (1 << 24)) >> 25
-       h2 += c1
-       h1 -= c1 << 25
-       c5 = (h5 + (1 << 24)) >> 25
-       h6 += c5
-       h5 -= c5 << 25
-       /* |h1| <= 2^24; from now on fits into int32 */
-       /* |h5| <= 2^24; from now on fits into int32 */
-       /* |h2| <= 1.21*2^59 */
-       /* |h6| <= 1.21*2^59 */
-
-       c2 = (h2 + (1 << 25)) >> 26
-       h3 += c2
-       h2 -= c2 << 26
-       c6 = (h6 + (1 << 25)) >> 26
-       h7 += c6
-       h6 -= c6 << 26
-       /* |h2| <= 2^25; from now on fits into int32 unchanged */
-       /* |h6| <= 2^25; from now on fits into int32 unchanged */
-       /* |h3| <= 1.51*2^58 */
-       /* |h7| <= 1.51*2^58 */
-
-       c3 = (h3 + (1 << 24)) >> 25
-       h4 += c3
-       h3 -= c3 << 25
-       c7 = (h7 + (1 << 24)) >> 25
-       h8 += c7
-       h7 -= c7 << 25
-       /* |h3| <= 2^24; from now on fits into int32 unchanged */
-       /* |h7| <= 2^24; from now on fits into int32 unchanged */
-       /* |h4| <= 1.52*2^33 */
-       /* |h8| <= 1.52*2^33 */
-
-       c4 = (h4 + (1 << 25)) >> 26
-       h5 += c4
-       h4 -= c4 << 26
-       c8 = (h8 + (1 << 25)) >> 26
-       h9 += c8
-       h8 -= c8 << 26
-       /* |h4| <= 2^25; from now on fits into int32 unchanged */
-       /* |h8| <= 2^25; from now on fits into int32 unchanged */
-       /* |h5| <= 1.01*2^24 */
-       /* |h9| <= 1.51*2^58 */
-
-       c9 = (h9 + (1 << 24)) >> 25
-       h0 += c9 * 19
-       h9 -= c9 << 25
-       /* |h9| <= 2^24; from now on fits into int32 unchanged */
-       /* |h0| <= 1.8*2^37 */
-
-       c0 = (h0 + (1 << 25)) >> 26
-       h1 += c0
-       h0 -= c0 << 26
-       /* |h0| <= 2^25; from now on fits into int32 unchanged */
-       /* |h1| <= 1.01*2^24 */
-
-       h[0] = int32(h0)
-       h[1] = int32(h1)
-       h[2] = int32(h2)
-       h[3] = int32(h3)
-       h[4] = int32(h4)
-       h[5] = int32(h5)
-       h[6] = int32(h6)
-       h[7] = int32(h7)
-       h[8] = int32(h8)
-       h[9] = int32(h9)
+// NewGeneratorPoint returns a new Point set to the canonical generator.
+func NewGeneratorPoint() *Point {
+       return new(Point).Set(generator)
 }
 
-// FeMul calculates h = f * g
-// Can overlap h with f or g.
-//
-// Preconditions:
-//    |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
-//    |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
-//
-// Postconditions:
-//    |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
-//
-// Notes on implementation strategy:
-//
-// Using schoolbook multiplication.
-// Karatsuba would save a little in some cost models.
-//
-// Most multiplications by 2 and 19 are 32-bit precomputations;
-// cheaper than 64-bit postcomputations.
-//
-// There is one remaining multiplication by 19 in the carry chain;
-// one *19 precomputation can be merged into this,
-// but the resulting data flow is considerably less clean.
-//
-// There are 12 carries below.
-// 10 of them are 2-way parallelizable and vectorizable.
-// Can get away with 11 carries, but then data flow is much deeper.
-//
-// With tighter constraints on inputs, can squeeze carries into int32.
-func FeMul(h, f, g *FieldElement) {
-       f0 := int64(f[0])
-       f1 := int64(f[1])
-       f2 := int64(f[2])
-       f3 := int64(f[3])
-       f4 := int64(f[4])
-       f5 := int64(f[5])
-       f6 := int64(f[6])
-       f7 := int64(f[7])
-       f8 := int64(f[8])
-       f9 := int64(f[9])
-
-       f1_2 := int64(2 * f[1])
-       f3_2 := int64(2 * f[3])
-       f5_2 := int64(2 * f[5])
-       f7_2 := int64(2 * f[7])
-       f9_2 := int64(2 * f[9])
-
-       g0 := int64(g[0])
-       g1 := int64(g[1])
-       g2 := int64(g[2])
-       g3 := int64(g[3])
-       g4 := int64(g[4])
-       g5 := int64(g[5])
-       g6 := int64(g[6])
-       g7 := int64(g[7])
-       g8 := int64(g[8])
-       g9 := int64(g[9])
-
-       g1_19 := int64(19 * g[1]) /* 1.4*2^29 */
-       g2_19 := int64(19 * g[2]) /* 1.4*2^30; still ok */
-       g3_19 := int64(19 * g[3])
-       g4_19 := int64(19 * g[4])
-       g5_19 := int64(19 * g[5])
-       g6_19 := int64(19 * g[6])
-       g7_19 := int64(19 * g[7])
-       g8_19 := int64(19 * g[8])
-       g9_19 := int64(19 * g[9])
-
-       h0 := f0*g0 + f1_2*g9_19 + f2*g8_19 + f3_2*g7_19 + f4*g6_19 + f5_2*g5_19 + f6*g4_19 + f7_2*g3_19 + f8*g2_19 + f9_2*g1_19
-       h1 := f0*g1 + f1*g0 + f2*g9_19 + f3*g8_19 + f4*g7_19 + f5*g6_19 + f6*g5_19 + f7*g4_19 + f8*g3_19 + f9*g2_19
-       h2 := f0*g2 + f1_2*g1 + f2*g0 + f3_2*g9_19 + f4*g8_19 + f5_2*g7_19 + f6*g6_19 + f7_2*g5_19 + f8*g4_19 + f9_2*g3_19
-       h3 := f0*g3 + f1*g2 + f2*g1 + f3*g0 + f4*g9_19 + f5*g8_19 + f6*g7_19 + f7*g6_19 + f8*g5_19 + f9*g4_19
-       h4 := f0*g4 + f1_2*g3 + f2*g2 + f3_2*g1 + f4*g0 + f5_2*g9_19 + f6*g8_19 + f7_2*g7_19 + f8*g6_19 + f9_2*g5_19
-       h5 := f0*g5 + f1*g4 + f2*g3 + f3*g2 + f4*g1 + f5*g0 + f6*g9_19 + f7*g8_19 + f8*g7_19 + f9*g6_19
-       h6 := f0*g6 + f1_2*g5 + f2*g4 + f3_2*g3 + f4*g2 + f5_2*g1 + f6*g0 + f7_2*g9_19 + f8*g8_19 + f9_2*g7_19
-       h7 := f0*g7 + f1*g6 + f2*g5 + f3*g4 + f4*g3 + f5*g2 + f6*g1 + f7*g0 + f8*g9_19 + f9*g8_19
-       h8 := f0*g8 + f1_2*g7 + f2*g6 + f3_2*g5 + f4*g4 + f5_2*g3 + f6*g2 + f7_2*g1 + f8*g0 + f9_2*g9_19
-       h9 := f0*g9 + f1*g8 + f2*g7 + f3*g6 + f4*g5 + f5*g4 + f6*g3 + f7*g2 + f8*g1 + f9*g0
-
-       FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9)
+func (v *projCached) Zero() *projCached {
+       v.YplusX.One()
+       v.YminusX.One()
+       v.Z.One()
+       v.T2d.Zero()
+       return v
 }
 
-func feSquare(f *FieldElement) (h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) {
-       f0 := int64(f[0])
-       f1 := int64(f[1])
-       f2 := int64(f[2])
-       f3 := int64(f[3])
-       f4 := int64(f[4])
-       f5 := int64(f[5])
-       f6 := int64(f[6])
-       f7 := int64(f[7])
-       f8 := int64(f[8])
-       f9 := int64(f[9])
-       f0_2 := int64(2 * f[0])
-       f1_2 := int64(2 * f[1])
-       f2_2 := int64(2 * f[2])
-       f3_2 := int64(2 * f[3])
-       f4_2 := int64(2 * f[4])
-       f5_2 := int64(2 * f[5])
-       f6_2 := int64(2 * f[6])
-       f7_2 := int64(2 * f[7])
-       f5_38 := 38 * f5 // 1.31*2^30
-       f6_19 := 19 * f6 // 1.31*2^30
-       f7_38 := 38 * f7 // 1.31*2^30
-       f8_19 := 19 * f8 // 1.31*2^30
-       f9_38 := 38 * f9 // 1.31*2^30
-
-       h0 = f0*f0 + f1_2*f9_38 + f2_2*f8_19 + f3_2*f7_38 + f4_2*f6_19 + f5*f5_38
-       h1 = f0_2*f1 + f2*f9_38 + f3_2*f8_19 + f4*f7_38 + f5_2*f6_19
-       h2 = f0_2*f2 + f1_2*f1 + f3_2*f9_38 + f4_2*f8_19 + f5_2*f7_38 + f6*f6_19
-       h3 = f0_2*f3 + f1_2*f2 + f4*f9_38 + f5_2*f8_19 + f6*f7_38
-       h4 = f0_2*f4 + f1_2*f3_2 + f2*f2 + f5_2*f9_38 + f6_2*f8_19 + f7*f7_38
-       h5 = f0_2*f5 + f1_2*f4 + f2_2*f3 + f6*f9_38 + f7_2*f8_19
-       h6 = f0_2*f6 + f1_2*f5_2 + f2_2*f4 + f3_2*f3 + f7_2*f9_38 + f8*f8_19
-       h7 = f0_2*f7 + f1_2*f6 + f2_2*f5 + f3_2*f4 + f8*f9_38
-       h8 = f0_2*f8 + f1_2*f7_2 + f2_2*f6 + f3_2*f5_2 + f4*f4 + f9*f9_38
-       h9 = f0_2*f9 + f1_2*f8 + f2_2*f7 + f3_2*f6 + f4_2*f5
-
-       return
+func (v *affineCached) Zero() *affineCached {
+       v.YplusX.One()
+       v.YminusX.One()
+       v.T2d.Zero()
+       return v
 }
 
-// FeSquare calculates h = f*f. Can overlap h with f.
-//
-// Preconditions:
-//    |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
-//
-// Postconditions:
-//    |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
-func FeSquare(h, f *FieldElement) {
-       h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := feSquare(f)
-       FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9)
+// Assignments.
+
+// Set sets v = u, and returns v.
+func (v *Point) Set(u *Point) *Point {
+       *v = *u
+       return v
 }
 
-// FeSquare2 sets h = 2 * f * f
-//
-// Can overlap h with f.
-//
-// Preconditions:
-//    |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
-//
-// Postconditions:
-//    |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
-// See fe_mul.c for discussion of implementation strategy.
-func FeSquare2(h, f *FieldElement) {
-       h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := feSquare(f)
-
-       h0 += h0
-       h1 += h1
-       h2 += h2
-       h3 += h3
-       h4 += h4
-       h5 += h5
-       h6 += h6
-       h7 += h7
-       h8 += h8
-       h9 += h9
-
-       FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9)
+// Encoding.
+
+// Bytes returns the canonical 32-byte encoding of v, according to RFC 8032,
+// Section 5.1.2.
+func (v *Point) Bytes() []byte {
+       // This function is outlined to make the allocations inline in the caller
+       // rather than happen on the heap.
+       var buf [32]byte
+       return v.bytes(&buf)
 }
 
-func FeInvert(out, z *FieldElement) {
-       var t0, t1, t2, t3 FieldElement
-       var i int
+func (v *Point) bytes(buf *[32]byte) []byte {
+       checkInitialized(v)
 
-       FeSquare(&t0, z)        // 2^1
-       FeSquare(&t1, &t0)      // 2^2
-       for i = 1; i < 2; i++ { // 2^3
-               FeSquare(&t1, &t1)
-       }
-       FeMul(&t1, z, &t1)      // 2^3 + 2^0
-       FeMul(&t0, &t0, &t1)    // 2^3 + 2^1 + 2^0
-       FeSquare(&t2, &t0)      // 2^4 + 2^2 + 2^1
-       FeMul(&t1, &t1, &t2)    // 2^4 + 2^3 + 2^2 + 2^1 + 2^0
-       FeSquare(&t2, &t1)      // 5,4,3,2,1
-       for i = 1; i < 5; i++ { // 9,8,7,6,5
-               FeSquare(&t2, &t2)
-       }
-       FeMul(&t1, &t2, &t1)     // 9,8,7,6,5,4,3,2,1,0
-       FeSquare(&t2, &t1)       // 10..1
-       for i = 1; i < 10; i++ { // 19..10
-               FeSquare(&t2, &t2)
-       }
-       FeMul(&t2, &t2, &t1)     // 19..0
-       FeSquare(&t3, &t2)       // 20..1
-       for i = 1; i < 20; i++ { // 39..20
-               FeSquare(&t3, &t3)
-       }
-       FeMul(&t2, &t3, &t2)     // 39..0
-       FeSquare(&t2, &t2)       // 40..1
-       for i = 1; i < 10; i++ { // 49..10
-               FeSquare(&t2, &t2)
-       }
-       FeMul(&t1, &t2, &t1)     // 49..0
-       FeSquare(&t2, &t1)       // 50..1
-       for i = 1; i < 50; i++ { // 99..50
-               FeSquare(&t2, &t2)
-       }
-       FeMul(&t2, &t2, &t1)      // 99..0
-       FeSquare(&t3, &t2)        // 100..1
-       for i = 1; i < 100; i++ { // 199..100
-               FeSquare(&t3, &t3)
-       }
-       FeMul(&t2, &t3, &t2)     // 199..0
-       FeSquare(&t2, &t2)       // 200..1
-       for i = 1; i < 50; i++ { // 249..50
-               FeSquare(&t2, &t2)
-       }
-       FeMul(&t1, &t2, &t1)    // 249..0
-       FeSquare(&t1, &t1)      // 250..1
-       for i = 1; i < 5; i++ { // 254..5
-               FeSquare(&t1, &t1)
-       }
-       FeMul(out, &t1, &t0) // 254..5,3,1,0
+       var zInv, x, y field.Element
+       zInv.Invert(&v.z)       // zInv = 1 / Z
+       x.Multiply(&v.x, &zInv) // x = X / Z
+       y.Multiply(&v.y, &zInv) // y = Y / Z
+
+       out := copyFieldElement(buf, &y)
+       out[31] |= byte(x.IsNegative() << 7)
+       return out
 }
 
-func fePow22523(out, z *FieldElement) {
-       var t0, t1, t2 FieldElement
-       var i int
+var feOne = new(field.Element).One()
 
-       FeSquare(&t0, z)
-       for i = 1; i < 1; i++ {
-               FeSquare(&t0, &t0)
-       }
-       FeSquare(&t1, &t0)
-       for i = 1; i < 2; i++ {
-               FeSquare(&t1, &t1)
-       }
-       FeMul(&t1, z, &t1)
-       FeMul(&t0, &t0, &t1)
-       FeSquare(&t0, &t0)
-       for i = 1; i < 1; i++ {
-               FeSquare(&t0, &t0)
-       }
-       FeMul(&t0, &t1, &t0)
-       FeSquare(&t1, &t0)
-       for i = 1; i < 5; i++ {
-               FeSquare(&t1, &t1)
-       }
-       FeMul(&t0, &t1, &t0)
-       FeSquare(&t1, &t0)
-       for i = 1; i < 10; i++ {
-               FeSquare(&t1, &t1)
-       }
-       FeMul(&t1, &t1, &t0)
-       FeSquare(&t2, &t1)
-       for i = 1; i < 20; i++ {
-               FeSquare(&t2, &t2)
-       }
-       FeMul(&t1, &t2, &t1)
-       FeSquare(&t1, &t1)
-       for i = 1; i < 10; i++ {
-               FeSquare(&t1, &t1)
-       }
-       FeMul(&t0, &t1, &t0)
-       FeSquare(&t1, &t0)
-       for i = 1; i < 50; i++ {
-               FeSquare(&t1, &t1)
-       }
-       FeMul(&t1, &t1, &t0)
-       FeSquare(&t2, &t1)
-       for i = 1; i < 100; i++ {
-               FeSquare(&t2, &t2)
-       }
-       FeMul(&t1, &t2, &t1)
-       FeSquare(&t1, &t1)
-       for i = 1; i < 50; i++ {
-               FeSquare(&t1, &t1)
+// SetBytes sets v = x, where x is a 32-byte encoding of v. If x does not
+// represent a valid point on the curve, SetBytes returns nil and an error and
+// the receiver is unchanged. Otherwise, SetBytes returns v.
+//
+// Note that SetBytes accepts all non-canonical encodings of valid points.
+// That is, it follows decoding rules that match most implementations in
+// the ecosystem rather than RFC 8032.
+func (v *Point) SetBytes(x []byte) (*Point, error) {
+       // Specifically, the non-canonical encodings that are accepted are
+       //   1) the ones where the field element is not reduced (see the
+       //      (*field.Element).SetBytes docs) and
+       //   2) the ones where the x-coordinate is zero and the sign bit is set.
+       //
+       // This is consistent with crypto/ed25519/internal/edwards25519. Read more
+       // at https://hdevalence.ca/blog/2020-10-04-its-25519am, specifically the
+       // "Canonical A, R" section.
+
+       if len(x) != 32 {
+               return nil, errors.New("edwards25519: invalid point encoding length")
        }
-       FeMul(&t0, &t1, &t0)
-       FeSquare(&t0, &t0)
-       for i = 1; i < 2; i++ {
-               FeSquare(&t0, &t0)
+       y := new(field.Element).SetBytes(x)
+
+       // -x² + y² = 1 + dx²y²
+       // x² + dx²y² = x²(dy² + 1) = y² - 1
+       // x² = (y² - 1) / (dy² + 1)
+
+       // u = y² - 1
+       y2 := new(field.Element).Square(y)
+       u := new(field.Element).Subtract(y2, feOne)
+
+       // v = dy² + 1
+       vv := new(field.Element).Multiply(y2, d)
+       vv = vv.Add(vv, feOne)
+
+       // x = +√(u/v)
+       xx, wasSquare := new(field.Element).SqrtRatio(u, vv)
+       if wasSquare == 0 {
+               return nil, errors.New("edwards25519: invalid point encoding")
        }
-       FeMul(out, &t0, z)
-}
 
-// Group elements are members of the elliptic curve -x^2 + y^2 = 1 + d * x^2 *
-// y^2 where d = -121665/121666.
-//
-// Several representations are used:
-//   ProjectiveGroupElement: (X:Y:Z) satisfying x=X/Z, y=Y/Z
-//   ExtendedGroupElement: (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
-//   CompletedGroupElement: ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
-//   PreComputedGroupElement: (y+x,y-x,2dxy)
-
-type ProjectiveGroupElement struct {
-       X, Y, Z FieldElement
-}
+       // Select the negative square root if the sign bit is set.
+       xxNeg := new(field.Element).Negate(xx)
+       xx = xx.Select(xxNeg, xx, int(x[31]>>7))
 
-type ExtendedGroupElement struct {
-       X, Y, Z, T FieldElement
+       v.x.Set(xx)
+       v.y.Set(y)
+       v.z.One()
+       v.t.Multiply(xx, y) // xy = T / Z
+
+       return v, nil
 }
 
-type CompletedGroupElement struct {
-       X, Y, Z, T FieldElement
+func copyFieldElement(buf *[32]byte, v *field.Element) []byte {
+       copy(buf[:], v.Bytes())
+       return buf[:]
 }
 
-type PreComputedGroupElement struct {
-       yPlusX, yMinusX, xy2d FieldElement
+// Conversions.
+
+func (v *projP2) FromP1xP1(p *projP1xP1) *projP2 {
+       v.X.Multiply(&p.X, &p.T)
+       v.Y.Multiply(&p.Y, &p.Z)
+       v.Z.Multiply(&p.Z, &p.T)
+       return v
 }
 
-type CachedGroupElement struct {
-       yPlusX, yMinusX, Z, T2d FieldElement
+func (v *projP2) FromP3(p *Point) *projP2 {
+       v.X.Set(&p.x)
+       v.Y.Set(&p.y)
+       v.Z.Set(&p.z)
+       return v
 }
 
-func (p *ProjectiveGroupElement) Zero() {
-       FeZero(&p.X)
-       FeOne(&p.Y)
-       FeOne(&p.Z)
+func (v *Point) fromP1xP1(p *projP1xP1) *Point {
+       v.x.Multiply(&p.X, &p.T)
+       v.y.Multiply(&p.Y, &p.Z)
+       v.z.Multiply(&p.Z, &p.T)
+       v.t.Multiply(&p.X, &p.Y)
+       return v
 }
 
-func (p *ProjectiveGroupElement) Double(r *CompletedGroupElement) {
-       var t0 FieldElement
-
-       FeSquare(&r.X, &p.X)
-       FeSquare(&r.Z, &p.Y)
-       FeSquare2(&r.T, &p.Z)
-       FeAdd(&r.Y, &p.X, &p.Y)
-       FeSquare(&t0, &r.Y)
-       FeAdd(&r.Y, &r.Z, &r.X)
-       FeSub(&r.Z, &r.Z, &r.X)
-       FeSub(&r.X, &t0, &r.Y)
-       FeSub(&r.T, &r.T, &r.Z)
+func (v *Point) fromP2(p *projP2) *Point {
+       v.x.Multiply(&p.X, &p.Z)
+       v.y.Multiply(&p.Y, &p.Z)
+       v.z.Square(&p.Z)
+       v.t.Multiply(&p.X, &p.Y)
+       return v
 }
 
-func (p *ProjectiveGroupElement) ToBytes(s *[32]byte) {
-       var recip, x, y FieldElement
+// d is a constant in the curve equation.
+var d = new(field.Element).SetBytes([]byte{
+       0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75,
+       0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00,
+       0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c,
+       0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52})
+var d2 = new(field.Element).Add(d, d)
 
-       FeInvert(&recip, &p.Z)
-       FeMul(&x, &p.X, &recip)
-       FeMul(&y, &p.Y, &recip)
-       FeToBytes(s, &y)
-       s[31] ^= FeIsNegative(&x) << 7
+func (v *projCached) FromP3(p *Point) *projCached {
+       v.YplusX.Add(&p.y, &p.x)
+       v.YminusX.Subtract(&p.y, &p.x)
+       v.Z.Set(&p.z)
+       v.T2d.Multiply(&p.t, d2)
+       return v
 }
 
-func (p *ExtendedGroupElement) Zero() {
-       FeZero(&p.X)
-       FeOne(&p.Y)
-       FeOne(&p.Z)
-       FeZero(&p.T)
-}
+func (v *affineCached) FromP3(p *Point) *affineCached {
+       v.YplusX.Add(&p.y, &p.x)
+       v.YminusX.Subtract(&p.y, &p.x)
+       v.T2d.Multiply(&p.t, d2)
 
-func (p *ExtendedGroupElement) Double(r *CompletedGroupElement) {
-       var q ProjectiveGroupElement
-       p.ToProjective(&q)
-       q.Double(r)
+       var invZ field.Element
+       invZ.Invert(&p.z)
+       v.YplusX.Multiply(&v.YplusX, &invZ)
+       v.YminusX.Multiply(&v.YminusX, &invZ)
+       v.T2d.Multiply(&v.T2d, &invZ)
+       return v
 }
 
-func (p *ExtendedGroupElement) ToCached(r *CachedGroupElement) {
-       FeAdd(&r.yPlusX, &p.Y, &p.X)
-       FeSub(&r.yMinusX, &p.Y, &p.X)
-       FeCopy(&r.Z, &p.Z)
-       FeMul(&r.T2d, &p.T, &d2)
-}
+// (Re)addition and subtraction.
 
-func (p *ExtendedGroupElement) ToProjective(r *ProjectiveGroupElement) {
-       FeCopy(&r.X, &p.X)
-       FeCopy(&r.Y, &p.Y)
-       FeCopy(&r.Z, &p.Z)
+// Add sets v = p + q, and returns v.
+func (v *Point) Add(p, q *Point) *Point {
+       checkInitialized(p, q)
+       qCached := new(projCached).FromP3(q)
+       result := new(projP1xP1).Add(p, qCached)
+       return v.fromP1xP1(result)
 }
 
-func (p *ExtendedGroupElement) ToBytes(s *[32]byte) {
-       var recip, x, y FieldElement
-
-       FeInvert(&recip, &p.Z)
-       FeMul(&x, &p.X, &recip)
-       FeMul(&y, &p.Y, &recip)
-       FeToBytes(s, &y)
-       s[31] ^= FeIsNegative(&x) << 7
+// Subtract sets v = p - q, and returns v.
+func (v *Point) Subtract(p, q *Point) *Point {
+       checkInitialized(p, q)
+       qCached := new(projCached).FromP3(q)
+       result := new(projP1xP1).Sub(p, qCached)
+       return v.fromP1xP1(result)
 }
 
-func (p *ExtendedGroupElement) FromBytes(s *[32]byte) bool {
-       var u, v, v3, vxx, check FieldElement
-
-       FeFromBytes(&p.Y, s)
-       FeOne(&p.Z)
-       FeSquare(&u, &p.Y)
-       FeMul(&v, &u, &d)
-       FeSub(&u, &u, &p.Z) // u = y^2-1
-       FeAdd(&v, &v, &p.Z) // v = dy^2+1
-
-       FeSquare(&v3, &v)
-       FeMul(&v3, &v3, &v) // v3 = v^3
-       FeSquare(&p.X, &v3)
-       FeMul(&p.X, &p.X, &v)
-       FeMul(&p.X, &p.X, &u) // x = uv^7
-
-       fePow22523(&p.X, &p.X) // x = (uv^7)^((q-5)/8)
-       FeMul(&p.X, &p.X, &v3)
-       FeMul(&p.X, &p.X, &u) // x = uv^3(uv^7)^((q-5)/8)
-
-       var tmpX, tmp2 [32]byte
-
-       FeSquare(&vxx, &p.X)
-       FeMul(&vxx, &vxx, &v)
-       FeSub(&check, &vxx, &u) // vx^2-u
-       if FeIsNonZero(&check) == 1 {
-               FeAdd(&check, &vxx, &u) // vx^2+u
-               if FeIsNonZero(&check) == 1 {
-                       return false
-               }
-               FeMul(&p.X, &p.X, &SqrtM1)
+func (v *projP1xP1) Add(p *Point, q *projCached) *projP1xP1 {
+       var YplusX, YminusX, PP, MM, TT2d, ZZ2 field.Element
 
-               FeToBytes(&tmpX, &p.X)
-               for i, v := range tmpX {
-                       tmp2[31-i] = v
-               }
-       }
+       YplusX.Add(&p.y, &p.x)
+       YminusX.Subtract(&p.y, &p.x)
 
-       if FeIsNegative(&p.X) != (s[31] >> 7) {
-               FeNeg(&p.X, &p.X)
-       }
+       PP.Multiply(&YplusX, &q.YplusX)
+       MM.Multiply(&YminusX, &q.YminusX)
+       TT2d.Multiply(&p.t, &q.T2d)
+       ZZ2.Multiply(&p.z, &q.Z)
 
-       FeMul(&p.T, &p.X, &p.Y)
-       return true
-}
+       ZZ2.Add(&ZZ2, &ZZ2)
 
-func (p *CompletedGroupElement) ToProjective(r *ProjectiveGroupElement) {
-       FeMul(&r.X, &p.X, &p.T)
-       FeMul(&r.Y, &p.Y, &p.Z)
-       FeMul(&r.Z, &p.Z, &p.T)
+       v.X.Subtract(&PP, &MM)
+       v.Y.Add(&PP, &MM)
+       v.Z.Add(&ZZ2, &TT2d)
+       v.T.Subtract(&ZZ2, &TT2d)
+       return v
 }
 
-func (p *CompletedGroupElement) ToExtended(r *ExtendedGroupElement) {
-       FeMul(&r.X, &p.X, &p.T)
-       FeMul(&r.Y, &p.Y, &p.Z)
-       FeMul(&r.Z, &p.Z, &p.T)
-       FeMul(&r.T, &p.X, &p.Y)
-}
+func (v *projP1xP1) Sub(p *Point, q *projCached) *projP1xP1 {
+       var YplusX, YminusX, PP, MM, TT2d, ZZ2 field.Element
 
-func (p *PreComputedGroupElement) Zero() {
-       FeOne(&p.yPlusX)
-       FeOne(&p.yMinusX)
-       FeZero(&p.xy2d)
-}
+       YplusX.Add(&p.y, &p.x)
+       YminusX.Subtract(&p.y, &p.x)
 
-func geAdd(r *CompletedGroupElement, p *ExtendedGroupElement, q *CachedGroupElement) {
-       var t0 FieldElement
-
-       FeAdd(&r.X, &p.Y, &p.X)
-       FeSub(&r.Y, &p.Y, &p.X)
-       FeMul(&r.Z, &r.X, &q.yPlusX)
-       FeMul(&r.Y, &r.Y, &q.yMinusX)
-       FeMul(&r.T, &q.T2d, &p.T)
-       FeMul(&r.X, &p.Z, &q.Z)
-       FeAdd(&t0, &r.X, &r.X)
-       FeSub(&r.X, &r.Z, &r.Y)
-       FeAdd(&r.Y, &r.Z, &r.Y)
-       FeAdd(&r.Z, &t0, &r.T)
-       FeSub(&r.T, &t0, &r.T)
-}
+       PP.Multiply(&YplusX, &q.YminusX) // flipped sign
+       MM.Multiply(&YminusX, &q.YplusX) // flipped sign
+       TT2d.Multiply(&p.t, &q.T2d)
+       ZZ2.Multiply(&p.z, &q.Z)
 
-func geSub(r *CompletedGroupElement, p *ExtendedGroupElement, q *CachedGroupElement) {
-       var t0 FieldElement
-
-       FeAdd(&r.X, &p.Y, &p.X)
-       FeSub(&r.Y, &p.Y, &p.X)
-       FeMul(&r.Z, &r.X, &q.yMinusX)
-       FeMul(&r.Y, &r.Y, &q.yPlusX)
-       FeMul(&r.T, &q.T2d, &p.T)
-       FeMul(&r.X, &p.Z, &q.Z)
-       FeAdd(&t0, &r.X, &r.X)
-       FeSub(&r.X, &r.Z, &r.Y)
-       FeAdd(&r.Y, &r.Z, &r.Y)
-       FeSub(&r.Z, &t0, &r.T)
-       FeAdd(&r.T, &t0, &r.T)
-}
+       ZZ2.Add(&ZZ2, &ZZ2)
 
-func geMixedAdd(r *CompletedGroupElement, p *ExtendedGroupElement, q *PreComputedGroupElement) {
-       var t0 FieldElement
-
-       FeAdd(&r.X, &p.Y, &p.X)
-       FeSub(&r.Y, &p.Y, &p.X)
-       FeMul(&r.Z, &r.X, &q.yPlusX)
-       FeMul(&r.Y, &r.Y, &q.yMinusX)
-       FeMul(&r.T, &q.xy2d, &p.T)
-       FeAdd(&t0, &p.Z, &p.Z)
-       FeSub(&r.X, &r.Z, &r.Y)
-       FeAdd(&r.Y, &r.Z, &r.Y)
-       FeAdd(&r.Z, &t0, &r.T)
-       FeSub(&r.T, &t0, &r.T)
+       v.X.Subtract(&PP, &MM)
+       v.Y.Add(&PP, &MM)
+       v.Z.Subtract(&ZZ2, &TT2d) // flipped sign
+       v.T.Add(&ZZ2, &TT2d)      // flipped sign
+       return v
 }
 
-func geMixedSub(r *CompletedGroupElement, p *ExtendedGroupElement, q *PreComputedGroupElement) {
-       var t0 FieldElement
-
-       FeAdd(&r.X, &p.Y, &p.X)
-       FeSub(&r.Y, &p.Y, &p.X)
-       FeMul(&r.Z, &r.X, &q.yMinusX)
-       FeMul(&r.Y, &r.Y, &q.yPlusX)
-       FeMul(&r.T, &q.xy2d, &p.T)
-       FeAdd(&t0, &p.Z, &p.Z)
-       FeSub(&r.X, &r.Z, &r.Y)
-       FeAdd(&r.Y, &r.Z, &r.Y)
-       FeSub(&r.Z, &t0, &r.T)
-       FeAdd(&r.T, &t0, &r.T)
-}
+func (v *projP1xP1) AddAffine(p *Point, q *affineCached) *projP1xP1 {
+       var YplusX, YminusX, PP, MM, TT2d, Z2 field.Element
 
-func slide(r *[256]int8, a *[32]byte) {
-       for i := range r {
-               r[i] = int8(1 & (a[i>>3] >> uint(i&7)))
-       }
+       YplusX.Add(&p.y, &p.x)
+       YminusX.Subtract(&p.y, &p.x)
 
-       for i := range r {
-               if r[i] != 0 {
-                       for b := 1; b <= 6 && i+b < 256; b++ {
-                               if r[i+b] != 0 {
-                                       if r[i]+(r[i+b]<<uint(b)) <= 15 {
-                                               r[i] += r[i+b] << uint(b)
-                                               r[i+b] = 0
-                                       } else if r[i]-(r[i+b]<<uint(b)) >= -15 {
-                                               r[i] -= r[i+b] << uint(b)
-                                               for k := i + b; k < 256; k++ {
-                                                       if r[k] == 0 {
-                                                               r[k] = 1
-                                                               break
-                                                       }
-                                                       r[k] = 0
-                                               }
-                                       } else {
-                                               break
-                                       }
-                               }
-                       }
-               }
-       }
-}
+       PP.Multiply(&YplusX, &q.YplusX)
+       MM.Multiply(&YminusX, &q.YminusX)
+       TT2d.Multiply(&p.t, &q.T2d)
 
-// GeDoubleScalarMultVartime sets r = a*A + b*B
-// where a = a[0]+256*a[1]+...+256^31 a[31].
-// and b = b[0]+256*b[1]+...+256^31 b[31].
-// B is the Ed25519 base point (x,4/5) with x positive.
-func GeDoubleScalarMultVartime(r *ProjectiveGroupElement, a *[32]byte, A *ExtendedGroupElement, b *[32]byte) {
-       var aSlide, bSlide [256]int8
-       var Ai [8]CachedGroupElement // A,3A,5A,7A,9A,11A,13A,15A
-       var t CompletedGroupElement
-       var u, A2 ExtendedGroupElement
-       var i int
-
-       slide(&aSlide, a)
-       slide(&bSlide, b)
-
-       A.ToCached(&Ai[0])
-       A.Double(&t)
-       t.ToExtended(&A2)
-
-       for i := 0; i < 7; i++ {
-               geAdd(&t, &A2, &Ai[i])
-               t.ToExtended(&u)
-               u.ToCached(&Ai[i+1])
-       }
+       Z2.Add(&p.z, &p.z)
 
-       r.Zero()
+       v.X.Subtract(&PP, &MM)
+       v.Y.Add(&PP, &MM)
+       v.Z.Add(&Z2, &TT2d)
+       v.T.Subtract(&Z2, &TT2d)
+       return v
+}
 
-       for i = 255; i >= 0; i-- {
-               if aSlide[i] != 0 || bSlide[i] != 0 {
-                       break
-               }
-       }
+func (v *projP1xP1) SubAffine(p *Point, q *affineCached) *projP1xP1 {
+       var YplusX, YminusX, PP, MM, TT2d, Z2 field.Element
 
-       for ; i >= 0; i-- {
-               r.Double(&t)
+       YplusX.Add(&p.y, &p.x)
+       YminusX.Subtract(&p.y, &p.x)
 
-               if aSlide[i] > 0 {
-                       t.ToExtended(&u)
-                       geAdd(&t, &u, &Ai[aSlide[i]/2])
-               } else if aSlide[i] < 0 {
-                       t.ToExtended(&u)
-                       geSub(&t, &u, &Ai[(-aSlide[i])/2])
-               }
+       PP.Multiply(&YplusX, &q.YminusX) // flipped sign
+       MM.Multiply(&YminusX, &q.YplusX) // flipped sign
+       TT2d.Multiply(&p.t, &q.T2d)
 
-               if bSlide[i] > 0 {
-                       t.ToExtended(&u)
-                       geMixedAdd(&t, &u, &bi[bSlide[i]/2])
-               } else if bSlide[i] < 0 {
-                       t.ToExtended(&u)
-                       geMixedSub(&t, &u, &bi[(-bSlide[i])/2])
-               }
+       Z2.Add(&p.z, &p.z)
 
-               t.ToProjective(r)
-       }
+       v.X.Subtract(&PP, &MM)
+       v.Y.Add(&PP, &MM)
+       v.Z.Subtract(&Z2, &TT2d) // flipped sign
+       v.T.Add(&Z2, &TT2d)      // flipped sign
+       return v
 }
 
-// equal returns 1 if b == c and 0 otherwise, assuming that b and c are
-// non-negative.
-func equal(b, c int32) int32 {
-       x := uint32(b ^ c)
-       x--
-       return int32(x >> 31)
-}
+// Doubling.
 
-// negative returns 1 if b < 0 and 0 otherwise.
-func negative(b int32) int32 {
-       return (b >> 31) & 1
-}
+func (v *projP1xP1) Double(p *projP2) *projP1xP1 {
+       var XX, YY, ZZ2, XplusYsq field.Element
 
-func PreComputedGroupElementCMove(t, u *PreComputedGroupElement, b int32) {
-       FeCMove(&t.yPlusX, &u.yPlusX, b)
-       FeCMove(&t.yMinusX, &u.yMinusX, b)
-       FeCMove(&t.xy2d, &u.xy2d, b)
-}
+       XX.Square(&p.X)
+       YY.Square(&p.Y)
+       ZZ2.Square(&p.Z)
+       ZZ2.Add(&ZZ2, &ZZ2)
+       XplusYsq.Add(&p.X, &p.Y)
+       XplusYsq.Square(&XplusYsq)
 
-func selectPoint(t *PreComputedGroupElement, pos int32, b int32) {
-       var minusT PreComputedGroupElement
-       bNegative := negative(b)
-       bAbs := b - (((-bNegative) & b) << 1)
+       v.Y.Add(&YY, &XX)
+       v.Z.Subtract(&YY, &XX)
 
-       t.Zero()
-       for i := int32(0); i < 8; i++ {
-               PreComputedGroupElementCMove(t, &base[pos][i], equal(bAbs, i+1))
-       }
-       FeCopy(&minusT.yPlusX, &t.yMinusX)
-       FeCopy(&minusT.yMinusX, &t.yPlusX)
-       FeNeg(&minusT.xy2d, &t.xy2d)
-       PreComputedGroupElementCMove(t, &minusT, bNegative)
+       v.X.Subtract(&XplusYsq, &v.Y)
+       v.T.Subtract(&ZZ2, &v.Z)
+       return v
 }
 
-// GeScalarMultBase computes h = a*B, where
-//   a = a[0]+256*a[1]+...+256^31 a[31]
-//   B is the Ed25519 base point (x,4/5) with x positive.
-//
-// Preconditions:
-//   a[31] <= 127
-func GeScalarMultBase(h *ExtendedGroupElement, a *[32]byte) {
-       var e [64]int8
-
-       for i, v := range a {
-               e[2*i] = int8(v & 15)
-               e[2*i+1] = int8((v >> 4) & 15)
-       }
+// Negation.
 
-       // each e[i] is between 0 and 15 and e[63] is between 0 and 7.
+// Negate sets v = -p, and returns v.
+func (v *Point) Negate(p *Point) *Point {
+       checkInitialized(p)
+       v.x.Negate(&p.x)
+       v.y.Set(&p.y)
+       v.z.Set(&p.z)
+       v.t.Negate(&p.t)
+       return v
+}
 
-       carry := int8(0)
-       for i := 0; i < 63; i++ {
-               e[i] += carry
-               carry = (e[i] + 8) >> 4
-               e[i] -= carry << 4
-       }
-       e[63] += carry
-       // each e[i] is between -8 and 8.
-
-       h.Zero()
-       var t PreComputedGroupElement
-       var r CompletedGroupElement
-       for i := int32(1); i < 64; i += 2 {
-               selectPoint(&t, i/2, int32(e[i]))
-               geMixedAdd(&r, h, &t)
-               r.ToExtended(h)
-       }
+// Equal returns 1 if v is equivalent to u, and 0 otherwise.
+func (v *Point) Equal(u *Point) int {
+       checkInitialized(v, u)
 
-       var s ProjectiveGroupElement
-
-       h.Double(&r)
-       r.ToProjective(&s)
-       s.Double(&r)
-       r.ToProjective(&s)
-       s.Double(&r)
-       r.ToProjective(&s)
-       s.Double(&r)
-       r.ToExtended(h)
-
-       for i := int32(0); i < 64; i += 2 {
-               selectPoint(&t, i/2, int32(e[i]))
-               geMixedAdd(&r, h, &t)
-               r.ToExtended(h)
-       }
+       var t1, t2, t3, t4 field.Element
+       t1.Multiply(&v.x, &u.z)
+       t2.Multiply(&u.x, &v.z)
+       t3.Multiply(&v.y, &u.z)
+       t4.Multiply(&u.y, &v.z)
+
+       return t1.Equal(&t2) & t3.Equal(&t4)
 }
 
-// The scalars are GF(2^252 + 27742317777372353535851937790883648493).
+// Constant-time operations
 
-// Input:
-//   a[0]+256*a[1]+...+256^31*a[31] = a
-//   b[0]+256*b[1]+...+256^31*b[31] = b
-//   c[0]+256*c[1]+...+256^31*c[31] = c
-//
-// Output:
-//   s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
-//   where l = 2^252 + 27742317777372353535851937790883648493.
-func ScMulAdd(s, a, b, c *[32]byte) {
-       a0 := 2097151 & load3(a[:])
-       a1 := 2097151 & (load4(a[2:]) >> 5)
-       a2 := 2097151 & (load3(a[5:]) >> 2)
-       a3 := 2097151 & (load4(a[7:]) >> 7)
-       a4 := 2097151 & (load4(a[10:]) >> 4)
-       a5 := 2097151 & (load3(a[13:]) >> 1)
-       a6 := 2097151 & (load4(a[15:]) >> 6)
-       a7 := 2097151 & (load3(a[18:]) >> 3)
-       a8 := 2097151 & load3(a[21:])
-       a9 := 2097151 & (load4(a[23:]) >> 5)
-       a10 := 2097151 & (load3(a[26:]) >> 2)
-       a11 := (load4(a[28:]) >> 7)
-       b0 := 2097151 & load3(b[:])
-       b1 := 2097151 & (load4(b[2:]) >> 5)
-       b2 := 2097151 & (load3(b[5:]) >> 2)
-       b3 := 2097151 & (load4(b[7:]) >> 7)
-       b4 := 2097151 & (load4(b[10:]) >> 4)
-       b5 := 2097151 & (load3(b[13:]) >> 1)
-       b6 := 2097151 & (load4(b[15:]) >> 6)
-       b7 := 2097151 & (load3(b[18:]) >> 3)
-       b8 := 2097151 & load3(b[21:])
-       b9 := 2097151 & (load4(b[23:]) >> 5)
-       b10 := 2097151 & (load3(b[26:]) >> 2)
-       b11 := (load4(b[28:]) >> 7)
-       c0 := 2097151 & load3(c[:])
-       c1 := 2097151 & (load4(c[2:]) >> 5)
-       c2 := 2097151 & (load3(c[5:]) >> 2)
-       c3 := 2097151 & (load4(c[7:]) >> 7)
-       c4 := 2097151 & (load4(c[10:]) >> 4)
-       c5 := 2097151 & (load3(c[13:]) >> 1)
-       c6 := 2097151 & (load4(c[15:]) >> 6)
-       c7 := 2097151 & (load3(c[18:]) >> 3)
-       c8 := 2097151 & load3(c[21:])
-       c9 := 2097151 & (load4(c[23:]) >> 5)
-       c10 := 2097151 & (load3(c[26:]) >> 2)
-       c11 := (load4(c[28:]) >> 7)
-       var carry [23]int64
-
-       s0 := c0 + a0*b0
-       s1 := c1 + a0*b1 + a1*b0
-       s2 := c2 + a0*b2 + a1*b1 + a2*b0
-       s3 := c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0
-       s4 := c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0
-       s5 := c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0
-       s6 := c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0
-       s7 := c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0
-       s8 := c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0
-       s9 := c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0
-       s10 := c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0
-       s11 := c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0
-       s12 := a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1
-       s13 := a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2
-       s14 := a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3
-       s15 := a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4
-       s16 := a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5
-       s17 := a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6
-       s18 := a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7
-       s19 := a8*b11 + a9*b10 + a10*b9 + a11*b8
-       s20 := a9*b11 + a10*b10 + a11*b9
-       s21 := a10*b11 + a11*b10
-       s22 := a11 * b11
-       s23 := int64(0)
-
-       carry[0] = (s0 + (1 << 20)) >> 21
-       s1 += carry[0]
-       s0 -= carry[0] << 21
-       carry[2] = (s2 + (1 << 20)) >> 21
-       s3 += carry[2]
-       s2 -= carry[2] << 21
-       carry[4] = (s4 + (1 << 20)) >> 21
-       s5 += carry[4]
-       s4 -= carry[4] << 21
-       carry[6] = (s6 + (1 << 20)) >> 21
-       s7 += carry[6]
-       s6 -= carry[6] << 21
-       carry[8] = (s8 + (1 << 20)) >> 21
-       s9 += carry[8]
-       s8 -= carry[8] << 21
-       carry[10] = (s10 + (1 << 20)) >> 21
-       s11 += carry[10]
-       s10 -= carry[10] << 21
-       carry[12] = (s12 + (1 << 20)) >> 21
-       s13 += carry[12]
-       s12 -= carry[12] << 21
-       carry[14] = (s14 + (1 << 20)) >> 21
-       s15 += carry[14]
-       s14 -= carry[14] << 21
-       carry[16] = (s16 + (1 << 20)) >> 21
-       s17 += carry[16]
-       s16 -= carry[16] << 21
-       carry[18] = (s18 + (1 << 20)) >> 21
-       s19 += carry[18]
-       s18 -= carry[18] << 21
-       carry[20] = (s20 + (1 << 20)) >> 21
-       s21 += carry[20]
-       s20 -= carry[20] << 21
-       carry[22] = (s22 + (1 << 20)) >> 21
-       s23 += carry[22]
-       s22 -= carry[22] << 21
-
-       carry[1] = (s1 + (1 << 20)) >> 21
-       s2 += carry[1]
-       s1 -= carry[1] << 21
-       carry[3] = (s3 + (1 << 20)) >> 21
-       s4 += carry[3]
-       s3 -= carry[3] << 21
-       carry[5] = (s5 + (1 << 20)) >> 21
-       s6 += carry[5]
-       s5 -= carry[5] << 21
-       carry[7] = (s7 + (1 << 20)) >> 21
-       s8 += carry[7]
-       s7 -= carry[7] << 21
-       carry[9] = (s9 + (1 << 20)) >> 21
-       s10 += carry[9]
-       s9 -= carry[9] << 21
-       carry[11] = (s11 + (1 << 20)) >> 21
-       s12 += carry[11]
-       s11 -= carry[11] << 21
-       carry[13] = (s13 + (1 << 20)) >> 21
-       s14 += carry[13]
-       s13 -= carry[13] << 21
-       carry[15] = (s15 + (1 << 20)) >> 21
-       s16 += carry[15]
-       s15 -= carry[15] << 21
-       carry[17] = (s17 + (1 << 20)) >> 21
-       s18 += carry[17]
-       s17 -= carry[17] << 21
-       carry[19] = (s19 + (1 << 20)) >> 21
-       s20 += carry[19]
-       s19 -= carry[19] << 21
-       carry[21] = (s21 + (1 << 20)) >> 21
-       s22 += carry[21]
-       s21 -= carry[21] << 21
-
-       s11 += s23 * 666643
-       s12 += s23 * 470296
-       s13 += s23 * 654183
-       s14 -= s23 * 997805
-       s15 += s23 * 136657
-       s16 -= s23 * 683901
-       s23 = 0
-
-       s10 += s22 * 666643
-       s11 += s22 * 470296
-       s12 += s22 * 654183
-       s13 -= s22 * 997805
-       s14 += s22 * 136657
-       s15 -= s22 * 683901
-       s22 = 0
-
-       s9 += s21 * 666643
-       s10 += s21 * 470296
-       s11 += s21 * 654183
-       s12 -= s21 * 997805
-       s13 += s21 * 136657
-       s14 -= s21 * 683901
-       s21 = 0
-
-       s8 += s20 * 666643
-       s9 += s20 * 470296
-       s10 += s20 * 654183
-       s11 -= s20 * 997805
-       s12 += s20 * 136657
-       s13 -= s20 * 683901
-       s20 = 0
-
-       s7 += s19 * 666643
-       s8 += s19 * 470296
-       s9 += s19 * 654183
-       s10 -= s19 * 997805
-       s11 += s19 * 136657
-       s12 -= s19 * 683901
-       s19 = 0
-
-       s6 += s18 * 666643
-       s7 += s18 * 470296
-       s8 += s18 * 654183
-       s9 -= s18 * 997805
-       s10 += s18 * 136657
-       s11 -= s18 * 683901
-       s18 = 0
-
-       carry[6] = (s6 + (1 << 20)) >> 21
-       s7 += carry[6]
-       s6 -= carry[6] << 21
-       carry[8] = (s8 + (1 << 20)) >> 21
-       s9 += carry[8]
-       s8 -= carry[8] << 21
-       carry[10] = (s10 + (1 << 20)) >> 21
-       s11 += carry[10]
-       s10 -= carry[10] << 21
-       carry[12] = (s12 + (1 << 20)) >> 21
-       s13 += carry[12]
-       s12 -= carry[12] << 21
-       carry[14] = (s14 + (1 << 20)) >> 21
-       s15 += carry[14]
-       s14 -= carry[14] << 21
-       carry[16] = (s16 + (1 << 20)) >> 21
-       s17 += carry[16]
-       s16 -= carry[16] << 21
-
-       carry[7] = (s7 + (1 << 20)) >> 21
-       s8 += carry[7]
-       s7 -= carry[7] << 21
-       carry[9] = (s9 + (1 << 20)) >> 21
-       s10 += carry[9]
-       s9 -= carry[9] << 21
-       carry[11] = (s11 + (1 << 20)) >> 21
-       s12 += carry[11]
-       s11 -= carry[11] << 21
-       carry[13] = (s13 + (1 << 20)) >> 21
-       s14 += carry[13]
-       s13 -= carry[13] << 21
-       carry[15] = (s15 + (1 << 20)) >> 21
-       s16 += carry[15]
-       s15 -= carry[15] << 21
-
-       s5 += s17 * 666643
-       s6 += s17 * 470296
-       s7 += s17 * 654183
-       s8 -= s17 * 997805
-       s9 += s17 * 136657
-       s10 -= s17 * 683901
-       s17 = 0
-
-       s4 += s16 * 666643
-       s5 += s16 * 470296
-       s6 += s16 * 654183
-       s7 -= s16 * 997805
-       s8 += s16 * 136657
-       s9 -= s16 * 683901
-       s16 = 0
-
-       s3 += s15 * 666643
-       s4 += s15 * 470296
-       s5 += s15 * 654183
-       s6 -= s15 * 997805
-       s7 += s15 * 136657
-       s8 -= s15 * 683901
-       s15 = 0
-
-       s2 += s14 * 666643
-       s3 += s14 * 470296
-       s4 += s14 * 654183
-       s5 -= s14 * 997805
-       s6 += s14 * 136657
-       s7 -= s14 * 683901
-       s14 = 0
-
-       s1 += s13 * 666643
-       s2 += s13 * 470296
-       s3 += s13 * 654183
-       s4 -= s13 * 997805
-       s5 += s13 * 136657
-       s6 -= s13 * 683901
-       s13 = 0
-
-       s0 += s12 * 666643
-       s1 += s12 * 470296
-       s2 += s12 * 654183
-       s3 -= s12 * 997805
-       s4 += s12 * 136657
-       s5 -= s12 * 683901
-       s12 = 0
-
-       carry[0] = (s0 + (1 << 20)) >> 21
-       s1 += carry[0]
-       s0 -= carry[0] << 21
-       carry[2] = (s2 + (1 << 20)) >> 21
-       s3 += carry[2]
-       s2 -= carry[2] << 21
-       carry[4] = (s4 + (1 << 20)) >> 21
-       s5 += carry[4]
-       s4 -= carry[4] << 21
-       carry[6] = (s6 + (1 << 20)) >> 21
-       s7 += carry[6]
-       s6 -= carry[6] << 21
-       carry[8] = (s8 + (1 << 20)) >> 21
-       s9 += carry[8]
-       s8 -= carry[8] << 21
-       carry[10] = (s10 + (1 << 20)) >> 21
-       s11 += carry[10]
-       s10 -= carry[10] << 21
-
-       carry[1] = (s1 + (1 << 20)) >> 21
-       s2 += carry[1]
-       s1 -= carry[1] << 21
-       carry[3] = (s3 + (1 << 20)) >> 21
-       s4 += carry[3]
-       s3 -= carry[3] << 21
-       carry[5] = (s5 + (1 << 20)) >> 21
-       s6 += carry[5]
-       s5 -= carry[5] << 21
-       carry[7] = (s7 + (1 << 20)) >> 21
-       s8 += carry[7]
-       s7 -= carry[7] << 21
-       carry[9] = (s9 + (1 << 20)) >> 21
-       s10 += carry[9]
-       s9 -= carry[9] << 21
-       carry[11] = (s11 + (1 << 20)) >> 21
-       s12 += carry[11]
-       s11 -= carry[11] << 21
-
-       s0 += s12 * 666643
-       s1 += s12 * 470296
-       s2 += s12 * 654183
-       s3 -= s12 * 997805
-       s4 += s12 * 136657
-       s5 -= s12 * 683901
-       s12 = 0
-
-       carry[0] = s0 >> 21
-       s1 += carry[0]
-       s0 -= carry[0] << 21
-       carry[1] = s1 >> 21
-       s2 += carry[1]
-       s1 -= carry[1] << 21
-       carry[2] = s2 >> 21
-       s3 += carry[2]
-       s2 -= carry[2] << 21
-       carry[3] = s3 >> 21
-       s4 += carry[3]
-       s3 -= carry[3] << 21
-       carry[4] = s4 >> 21
-       s5 += carry[4]
-       s4 -= carry[4] << 21
-       carry[5] = s5 >> 21
-       s6 += carry[5]
-       s5 -= carry[5] << 21
-       carry[6] = s6 >> 21
-       s7 += carry[6]
-       s6 -= carry[6] << 21
-       carry[7] = s7 >> 21
-       s8 += carry[7]
-       s7 -= carry[7] << 21
-       carry[8] = s8 >> 21
-       s9 += carry[8]
-       s8 -= carry[8] << 21
-       carry[9] = s9 >> 21
-       s10 += carry[9]
-       s9 -= carry[9] << 21
-       carry[10] = s10 >> 21
-       s11 += carry[10]
-       s10 -= carry[10] << 21
-       carry[11] = s11 >> 21
-       s12 += carry[11]
-       s11 -= carry[11] << 21
-
-       s0 += s12 * 666643
-       s1 += s12 * 470296
-       s2 += s12 * 654183
-       s3 -= s12 * 997805
-       s4 += s12 * 136657
-       s5 -= s12 * 683901
-       s12 = 0
-
-       carry[0] = s0 >> 21
-       s1 += carry[0]
-       s0 -= carry[0] << 21
-       carry[1] = s1 >> 21
-       s2 += carry[1]
-       s1 -= carry[1] << 21
-       carry[2] = s2 >> 21
-       s3 += carry[2]
-       s2 -= carry[2] << 21
-       carry[3] = s3 >> 21
-       s4 += carry[3]
-       s3 -= carry[3] << 21
-       carry[4] = s4 >> 21
-       s5 += carry[4]
-       s4 -= carry[4] << 21
-       carry[5] = s5 >> 21
-       s6 += carry[5]
-       s5 -= carry[5] << 21
-       carry[6] = s6 >> 21
-       s7 += carry[6]
-       s6 -= carry[6] << 21
-       carry[7] = s7 >> 21
-       s8 += carry[7]
-       s7 -= carry[7] << 21
-       carry[8] = s8 >> 21
-       s9 += carry[8]
-       s8 -= carry[8] << 21
-       carry[9] = s9 >> 21
-       s10 += carry[9]
-       s9 -= carry[9] << 21
-       carry[10] = s10 >> 21
-       s11 += carry[10]
-       s10 -= carry[10] << 21
-
-       s[0] = byte(s0 >> 0)
-       s[1] = byte(s0 >> 8)
-       s[2] = byte((s0 >> 16) | (s1 << 5))
-       s[3] = byte(s1 >> 3)
-       s[4] = byte(s1 >> 11)
-       s[5] = byte((s1 >> 19) | (s2 << 2))
-       s[6] = byte(s2 >> 6)
-       s[7] = byte((s2 >> 14) | (s3 << 7))
-       s[8] = byte(s3 >> 1)
-       s[9] = byte(s3 >> 9)
-       s[10] = byte((s3 >> 17) | (s4 << 4))
-       s[11] = byte(s4 >> 4)
-       s[12] = byte(s4 >> 12)
-       s[13] = byte((s4 >> 20) | (s5 << 1))
-       s[14] = byte(s5 >> 7)
-       s[15] = byte((s5 >> 15) | (s6 << 6))
-       s[16] = byte(s6 >> 2)
-       s[17] = byte(s6 >> 10)
-       s[18] = byte((s6 >> 18) | (s7 << 3))
-       s[19] = byte(s7 >> 5)
-       s[20] = byte(s7 >> 13)
-       s[21] = byte(s8 >> 0)
-       s[22] = byte(s8 >> 8)
-       s[23] = byte((s8 >> 16) | (s9 << 5))
-       s[24] = byte(s9 >> 3)
-       s[25] = byte(s9 >> 11)
-       s[26] = byte((s9 >> 19) | (s10 << 2))
-       s[27] = byte(s10 >> 6)
-       s[28] = byte((s10 >> 14) | (s11 << 7))
-       s[29] = byte(s11 >> 1)
-       s[30] = byte(s11 >> 9)
-       s[31] = byte(s11 >> 17)
+// Select sets v to a if cond == 1 and to b if cond == 0.
+func (v *projCached) Select(a, b *projCached, cond int) *projCached {
+       v.YplusX.Select(&a.YplusX, &b.YplusX, cond)
+       v.YminusX.Select(&a.YminusX, &b.YminusX, cond)
+       v.Z.Select(&a.Z, &b.Z, cond)
+       v.T2d.Select(&a.T2d, &b.T2d, cond)
+       return v
 }
 
-// Input:
-//   s[0]+256*s[1]+...+256^63*s[63] = s
-//
-// Output:
-//   s[0]+256*s[1]+...+256^31*s[31] = s mod l
-//   where l = 2^252 + 27742317777372353535851937790883648493.
-func ScReduce(out *[32]byte, s *[64]byte) {
-       s0 := 2097151 & load3(s[:])
-       s1 := 2097151 & (load4(s[2:]) >> 5)
-       s2 := 2097151 & (load3(s[5:]) >> 2)
-       s3 := 2097151 & (load4(s[7:]) >> 7)
-       s4 := 2097151 & (load4(s[10:]) >> 4)
-       s5 := 2097151 & (load3(s[13:]) >> 1)
-       s6 := 2097151 & (load4(s[15:]) >> 6)
-       s7 := 2097151 & (load3(s[18:]) >> 3)
-       s8 := 2097151 & load3(s[21:])
-       s9 := 2097151 & (load4(s[23:]) >> 5)
-       s10 := 2097151 & (load3(s[26:]) >> 2)
-       s11 := 2097151 & (load4(s[28:]) >> 7)
-       s12 := 2097151 & (load4(s[31:]) >> 4)
-       s13 := 2097151 & (load3(s[34:]) >> 1)
-       s14 := 2097151 & (load4(s[36:]) >> 6)
-       s15 := 2097151 & (load3(s[39:]) >> 3)
-       s16 := 2097151 & load3(s[42:])
-       s17 := 2097151 & (load4(s[44:]) >> 5)
-       s18 := 2097151 & (load3(s[47:]) >> 2)
-       s19 := 2097151 & (load4(s[49:]) >> 7)
-       s20 := 2097151 & (load4(s[52:]) >> 4)
-       s21 := 2097151 & (load3(s[55:]) >> 1)
-       s22 := 2097151 & (load4(s[57:]) >> 6)
-       s23 := (load4(s[60:]) >> 3)
-
-       s11 += s23 * 666643
-       s12 += s23 * 470296
-       s13 += s23 * 654183
-       s14 -= s23 * 997805
-       s15 += s23 * 136657
-       s16 -= s23 * 683901
-       s23 = 0
-
-       s10 += s22 * 666643
-       s11 += s22 * 470296
-       s12 += s22 * 654183
-       s13 -= s22 * 997805
-       s14 += s22 * 136657
-       s15 -= s22 * 683901
-       s22 = 0
-
-       s9 += s21 * 666643
-       s10 += s21 * 470296
-       s11 += s21 * 654183
-       s12 -= s21 * 997805
-       s13 += s21 * 136657
-       s14 -= s21 * 683901
-       s21 = 0
-
-       s8 += s20 * 666643
-       s9 += s20 * 470296
-       s10 += s20 * 654183
-       s11 -= s20 * 997805
-       s12 += s20 * 136657
-       s13 -= s20 * 683901
-       s20 = 0
-
-       s7 += s19 * 666643
-       s8 += s19 * 470296
-       s9 += s19 * 654183
-       s10 -= s19 * 997805
-       s11 += s19 * 136657
-       s12 -= s19 * 683901
-       s19 = 0
-
-       s6 += s18 * 666643
-       s7 += s18 * 470296
-       s8 += s18 * 654183
-       s9 -= s18 * 997805
-       s10 += s18 * 136657
-       s11 -= s18 * 683901
-       s18 = 0
-
-       var carry [17]int64
-
-       carry[6] = (s6 + (1 << 20)) >> 21
-       s7 += carry[6]
-       s6 -= carry[6] << 21
-       carry[8] = (s8 + (1 << 20)) >> 21
-       s9 += carry[8]
-       s8 -= carry[8] << 21
-       carry[10] = (s10 + (1 << 20)) >> 21
-       s11 += carry[10]
-       s10 -= carry[10] << 21
-       carry[12] = (s12 + (1 << 20)) >> 21
-       s13 += carry[12]
-       s12 -= carry[12] << 21
-       carry[14] = (s14 + (1 << 20)) >> 21
-       s15 += carry[14]
-       s14 -= carry[14] << 21
-       carry[16] = (s16 + (1 << 20)) >> 21
-       s17 += carry[16]
-       s16 -= carry[16] << 21
-
-       carry[7] = (s7 + (1 << 20)) >> 21
-       s8 += carry[7]
-       s7 -= carry[7] << 21
-       carry[9] = (s9 + (1 << 20)) >> 21
-       s10 += carry[9]
-       s9 -= carry[9] << 21
-       carry[11] = (s11 + (1 << 20)) >> 21
-       s12 += carry[11]
-       s11 -= carry[11] << 21
-       carry[13] = (s13 + (1 << 20)) >> 21
-       s14 += carry[13]
-       s13 -= carry[13] << 21
-       carry[15] = (s15 + (1 << 20)) >> 21
-       s16 += carry[15]
-       s15 -= carry[15] << 21
-
-       s5 += s17 * 666643
-       s6 += s17 * 470296
-       s7 += s17 * 654183
-       s8 -= s17 * 997805
-       s9 += s17 * 136657
-       s10 -= s17 * 683901
-       s17 = 0
-
-       s4 += s16 * 666643
-       s5 += s16 * 470296
-       s6 += s16 * 654183
-       s7 -= s16 * 997805
-       s8 += s16 * 136657
-       s9 -= s16 * 683901
-       s16 = 0
-
-       s3 += s15 * 666643
-       s4 += s15 * 470296
-       s5 += s15 * 654183
-       s6 -= s15 * 997805
-       s7 += s15 * 136657
-       s8 -= s15 * 683901
-       s15 = 0
-
-       s2 += s14 * 666643
-       s3 += s14 * 470296
-       s4 += s14 * 654183
-       s5 -= s14 * 997805
-       s6 += s14 * 136657
-       s7 -= s14 * 683901
-       s14 = 0
-
-       s1 += s13 * 666643
-       s2 += s13 * 470296
-       s3 += s13 * 654183
-       s4 -= s13 * 997805
-       s5 += s13 * 136657
-       s6 -= s13 * 683901
-       s13 = 0
-
-       s0 += s12 * 666643
-       s1 += s12 * 470296
-       s2 += s12 * 654183
-       s3 -= s12 * 997805
-       s4 += s12 * 136657
-       s5 -= s12 * 683901
-       s12 = 0
-
-       carry[0] = (s0 + (1 << 20)) >> 21
-       s1 += carry[0]
-       s0 -= carry[0] << 21
-       carry[2] = (s2 + (1 << 20)) >> 21
-       s3 += carry[2]
-       s2 -= carry[2] << 21
-       carry[4] = (s4 + (1 << 20)) >> 21
-       s5 += carry[4]
-       s4 -= carry[4] << 21
-       carry[6] = (s6 + (1 << 20)) >> 21
-       s7 += carry[6]
-       s6 -= carry[6] << 21
-       carry[8] = (s8 + (1 << 20)) >> 21
-       s9 += carry[8]
-       s8 -= carry[8] << 21
-       carry[10] = (s10 + (1 << 20)) >> 21
-       s11 += carry[10]
-       s10 -= carry[10] << 21
-
-       carry[1] = (s1 + (1 << 20)) >> 21
-       s2 += carry[1]
-       s1 -= carry[1] << 21
-       carry[3] = (s3 + (1 << 20)) >> 21
-       s4 += carry[3]
-       s3 -= carry[3] << 21
-       carry[5] = (s5 + (1 << 20)) >> 21
-       s6 += carry[5]
-       s5 -= carry[5] << 21
-       carry[7] = (s7 + (1 << 20)) >> 21
-       s8 += carry[7]
-       s7 -= carry[7] << 21
-       carry[9] = (s9 + (1 << 20)) >> 21
-       s10 += carry[9]
-       s9 -= carry[9] << 21
-       carry[11] = (s11 + (1 << 20)) >> 21
-       s12 += carry[11]
-       s11 -= carry[11] << 21
-
-       s0 += s12 * 666643
-       s1 += s12 * 470296
-       s2 += s12 * 654183
-       s3 -= s12 * 997805
-       s4 += s12 * 136657
-       s5 -= s12 * 683901
-       s12 = 0
-
-       carry[0] = s0 >> 21
-       s1 += carry[0]
-       s0 -= carry[0] << 21
-       carry[1] = s1 >> 21
-       s2 += carry[1]
-       s1 -= carry[1] << 21
-       carry[2] = s2 >> 21
-       s3 += carry[2]
-       s2 -= carry[2] << 21
-       carry[3] = s3 >> 21
-       s4 += carry[3]
-       s3 -= carry[3] << 21
-       carry[4] = s4 >> 21
-       s5 += carry[4]
-       s4 -= carry[4] << 21
-       carry[5] = s5 >> 21
-       s6 += carry[5]
-       s5 -= carry[5] << 21
-       carry[6] = s6 >> 21
-       s7 += carry[6]
-       s6 -= carry[6] << 21
-       carry[7] = s7 >> 21
-       s8 += carry[7]
-       s7 -= carry[7] << 21
-       carry[8] = s8 >> 21
-       s9 += carry[8]
-       s8 -= carry[8] << 21
-       carry[9] = s9 >> 21
-       s10 += carry[9]
-       s9 -= carry[9] << 21
-       carry[10] = s10 >> 21
-       s11 += carry[10]
-       s10 -= carry[10] << 21
-       carry[11] = s11 >> 21
-       s12 += carry[11]
-       s11 -= carry[11] << 21
-
-       s0 += s12 * 666643
-       s1 += s12 * 470296
-       s2 += s12 * 654183
-       s3 -= s12 * 997805
-       s4 += s12 * 136657
-       s5 -= s12 * 683901
-       s12 = 0
-
-       carry[0] = s0 >> 21
-       s1 += carry[0]
-       s0 -= carry[0] << 21
-       carry[1] = s1 >> 21
-       s2 += carry[1]
-       s1 -= carry[1] << 21
-       carry[2] = s2 >> 21
-       s3 += carry[2]
-       s2 -= carry[2] << 21
-       carry[3] = s3 >> 21
-       s4 += carry[3]
-       s3 -= carry[3] << 21
-       carry[4] = s4 >> 21
-       s5 += carry[4]
-       s4 -= carry[4] << 21
-       carry[5] = s5 >> 21
-       s6 += carry[5]
-       s5 -= carry[5] << 21
-       carry[6] = s6 >> 21
-       s7 += carry[6]
-       s6 -= carry[6] << 21
-       carry[7] = s7 >> 21
-       s8 += carry[7]
-       s7 -= carry[7] << 21
-       carry[8] = s8 >> 21
-       s9 += carry[8]
-       s8 -= carry[8] << 21
-       carry[9] = s9 >> 21
-       s10 += carry[9]
-       s9 -= carry[9] << 21
-       carry[10] = s10 >> 21
-       s11 += carry[10]
-       s10 -= carry[10] << 21
-
-       out[0] = byte(s0 >> 0)
-       out[1] = byte(s0 >> 8)
-       out[2] = byte((s0 >> 16) | (s1 << 5))
-       out[3] = byte(s1 >> 3)
-       out[4] = byte(s1 >> 11)
-       out[5] = byte((s1 >> 19) | (s2 << 2))
-       out[6] = byte(s2 >> 6)
-       out[7] = byte((s2 >> 14) | (s3 << 7))
-       out[8] = byte(s3 >> 1)
-       out[9] = byte(s3 >> 9)
-       out[10] = byte((s3 >> 17) | (s4 << 4))
-       out[11] = byte(s4 >> 4)
-       out[12] = byte(s4 >> 12)
-       out[13] = byte((s4 >> 20) | (s5 << 1))
-       out[14] = byte(s5 >> 7)
-       out[15] = byte((s5 >> 15) | (s6 << 6))
-       out[16] = byte(s6 >> 2)
-       out[17] = byte(s6 >> 10)
-       out[18] = byte((s6 >> 18) | (s7 << 3))
-       out[19] = byte(s7 >> 5)
-       out[20] = byte(s7 >> 13)
-       out[21] = byte(s8 >> 0)
-       out[22] = byte(s8 >> 8)
-       out[23] = byte((s8 >> 16) | (s9 << 5))
-       out[24] = byte(s9 >> 3)
-       out[25] = byte(s9 >> 11)
-       out[26] = byte((s9 >> 19) | (s10 << 2))
-       out[27] = byte(s10 >> 6)
-       out[28] = byte((s10 >> 14) | (s11 << 7))
-       out[29] = byte(s11 >> 1)
-       out[30] = byte(s11 >> 9)
-       out[31] = byte(s11 >> 17)
+// Select sets v to a if cond == 1 and to b if cond == 0.
+func (v *affineCached) Select(a, b *affineCached, cond int) *affineCached {
+       v.YplusX.Select(&a.YplusX, &b.YplusX, cond)
+       v.YminusX.Select(&a.YminusX, &b.YminusX, cond)
+       v.T2d.Select(&a.T2d, &b.T2d, cond)
+       return v
 }
 
-// order is the order of Curve25519 in little-endian form.
-var order = [4]uint64{0x5812631a5cf5d3ed, 0x14def9dea2f79cd6, 0, 0x1000000000000000}
-
-// ScMinimal returns true if the given scalar is less than the order of the
-// curve.
-func ScMinimal(scalar *[32]byte) bool {
-       for i := 3; ; i-- {
-               v := binary.LittleEndian.Uint64(scalar[i*8:])
-               if v > order[i] {
-                       return false
-               } else if v < order[i] {
-                       break
-               } else if i == 0 {
-                       return false
-               }
-       }
+// CondNeg negates v if cond == 1 and leaves it unchanged if cond == 0.
+func (v *projCached) CondNeg(cond int) *projCached {
+       v.YplusX.Swap(&v.YminusX, cond)
+       v.T2d.Select(new(field.Element).Negate(&v.T2d), &v.T2d, cond)
+       return v
+}
 
-       return true
+// CondNeg negates v if cond == 1 and leaves it unchanged if cond == 0.
+func (v *affineCached) CondNeg(cond int) *affineCached {
+       v.YplusX.Swap(&v.YminusX, cond)
+       v.T2d.Select(new(field.Element).Negate(&v.T2d), &v.T2d, cond)
+       return v
 }
diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/edwards25519_test.go b/libgo/go/crypto/ed25519/internal/edwards25519/edwards25519_test.go
new file mode 100644 (file)
index 0000000..7b01920
--- /dev/null
@@ -0,0 +1,308 @@
+// Copyright (c) 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package edwards25519
+
+import (
+       "crypto/ed25519/internal/edwards25519/field"
+       "encoding/hex"
+       "os"
+       "reflect"
+       "runtime"
+       "strings"
+       "testing"
+)
+
+var B = NewGeneratorPoint()
+var I = NewIdentityPoint()
+
+func checkOnCurve(t *testing.T, points ...*Point) {
+       t.Helper()
+       for i, p := range points {
+               var XX, YY, ZZ, ZZZZ field.Element
+               XX.Square(&p.x)
+               YY.Square(&p.y)
+               ZZ.Square(&p.z)
+               ZZZZ.Square(&ZZ)
+               // -x² + y² = 1 + dx²y²
+               // -(X/Z)² + (Y/Z)² = 1 + d(X/Z)²(Y/Z)²
+               // (-X² + Y²)/Z² = 1 + (dX²Y²)/Z⁴
+               // (-X² + Y²)*Z² = Z⁴ + dX²Y²
+               var lhs, rhs field.Element
+               lhs.Subtract(&YY, &XX).Multiply(&lhs, &ZZ)
+               rhs.Multiply(d, &XX).Multiply(&rhs, &YY).Add(&rhs, &ZZZZ)
+               if lhs.Equal(&rhs) != 1 {
+                       t.Errorf("X, Y, and Z do not specify a point on the curve\nX = %v\nY = %v\nZ = %v", p.x, p.y, p.z)
+               }
+               // xy = T/Z
+               lhs.Multiply(&p.x, &p.y)
+               rhs.Multiply(&p.z, &p.t)
+               if lhs.Equal(&rhs) != 1 {
+                       t.Errorf("point %d is not valid\nX = %v\nY = %v\nZ = %v", i, p.x, p.y, p.z)
+               }
+       }
+}
+
+func TestGenerator(t *testing.T) {
+       // These are the coordinates of B from RFC 8032, Section 5.1, converted to
+       // little endian hex.
+       x := "1ad5258f602d56c9b2a7259560c72c695cdcd6fd31e2a4c0fe536ecdd3366921"
+       y := "5866666666666666666666666666666666666666666666666666666666666666"
+       if got := hex.EncodeToString(B.x.Bytes()); got != x {
+               t.Errorf("wrong B.x: got %s, expected %s", got, x)
+       }
+       if got := hex.EncodeToString(B.y.Bytes()); got != y {
+               t.Errorf("wrong B.y: got %s, expected %s", got, y)
+       }
+       if B.z.Equal(feOne) != 1 {
+               t.Errorf("wrong B.z: got %v, expected 1", B.z)
+       }
+       // Check that t is correct.
+       checkOnCurve(t, B)
+}
+
+func TestAddSubNegOnBasePoint(t *testing.T) {
+       checkLhs, checkRhs := &Point{}, &Point{}
+
+       checkLhs.Add(B, B)
+       tmpP2 := new(projP2).FromP3(B)
+       tmpP1xP1 := new(projP1xP1).Double(tmpP2)
+       checkRhs.fromP1xP1(tmpP1xP1)
+       if checkLhs.Equal(checkRhs) != 1 {
+               t.Error("B + B != [2]B")
+       }
+       checkOnCurve(t, checkLhs, checkRhs)
+
+       checkLhs.Subtract(B, B)
+       Bneg := new(Point).Negate(B)
+       checkRhs.Add(B, Bneg)
+       if checkLhs.Equal(checkRhs) != 1 {
+               t.Error("B - B != B + (-B)")
+       }
+       if I.Equal(checkLhs) != 1 {
+               t.Error("B - B != 0")
+       }
+       if I.Equal(checkRhs) != 1 {
+               t.Error("B + (-B) != 0")
+       }
+       checkOnCurve(t, checkLhs, checkRhs, Bneg)
+}
+
+func TestComparable(t *testing.T) {
+       if reflect.TypeOf(Point{}).Comparable() {
+               t.Error("Point is unexpectedly comparable")
+       }
+}
+
+func TestInvalidEncodings(t *testing.T) {
+       // An invalid point, that also happens to have y > p.
+       invalid := "efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f"
+       p := NewGeneratorPoint()
+       if out, err := p.SetBytes(decodeHex(invalid)); err == nil {
+               t.Error("expected error for invalid point")
+       } else if out != nil {
+               t.Error("SetBytes did not return nil on an invalid encoding")
+       } else if p.Equal(B) != 1 {
+               t.Error("the Point was modified while decoding an invalid encoding")
+       }
+       checkOnCurve(t, p)
+}
+
+func TestNonCanonicalPoints(t *testing.T) {
+       type test struct {
+               name                string
+               encoding, canonical string
+       }
+       tests := []test{
+               // Points with x = 0 and the sign bit set. With x = 0 the curve equation
+               // gives y² = 1, so y = ±1. 1 has two valid encodings.
+               {
+                       "y=1,sign-",
+                       "0100000000000000000000000000000000000000000000000000000000000080",
+                       "0100000000000000000000000000000000000000000000000000000000000000",
+               },
+               {
+                       "y=p+1,sign-",
+                       "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+                       "0100000000000000000000000000000000000000000000000000000000000000",
+               },
+               {
+                       "y=p-1,sign-",
+                       "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+                       "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+               },
+
+               // Non-canonical y encodings with values 2²⁵⁵-19 (p) to 2²⁵⁵-1 (p+18).
+               {
+                       "y=p,sign+",
+                       "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+                       "0000000000000000000000000000000000000000000000000000000000000000",
+               },
+               {
+                       "y=p,sign-",
+                       "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+                       "0000000000000000000000000000000000000000000000000000000000000080",
+               },
+               {
+                       "y=p+1,sign+",
+                       "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+                       "0100000000000000000000000000000000000000000000000000000000000000",
+               },
+               // "y=p+1,sign-" is already tested above.
+               // p+2 is not a valid y-coordinate.
+               {
+                       "y=p+3,sign+",
+                       "f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+                       "0300000000000000000000000000000000000000000000000000000000000000",
+               },
+               {
+                       "y=p+3,sign-",
+                       "f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+                       "0300000000000000000000000000000000000000000000000000000000000080",
+               },
+               {
+                       "y=p+4,sign+",
+                       "f1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+                       "0400000000000000000000000000000000000000000000000000000000000000",
+               },
+               {
+                       "y=p+4,sign-",
+                       "f1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+                       "0400000000000000000000000000000000000000000000000000000000000080",
+               },
+               {
+                       "y=p+5,sign+",
+                       "f2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+                       "0500000000000000000000000000000000000000000000000000000000000000",
+               },
+               {
+                       "y=p+5,sign-",
+                       "f2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+                       "0500000000000000000000000000000000000000000000000000000000000080",
+               },
+               {
+                       "y=p+6,sign+",
+                       "f3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+                       "0600000000000000000000000000000000000000000000000000000000000000",
+               },
+               {
+                       "y=p+6,sign-",
+                       "f3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+                       "0600000000000000000000000000000000000000000000000000000000000080",
+               },
+               // p+7 is not a valid y-coordinate.
+               // p+8 is not a valid y-coordinate.
+               {
+                       "y=p+9,sign+",
+                       "f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+                       "0900000000000000000000000000000000000000000000000000000000000000",
+               },
+               {
+                       "y=p+9,sign-",
+                       "f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+                       "0900000000000000000000000000000000000000000000000000000000000080",
+               },
+               {
+                       "y=p+10,sign+",
+                       "f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+                       "0a00000000000000000000000000000000000000000000000000000000000000",
+               },
+               {
+                       "y=p+10,sign-",
+                       "f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+                       "0a00000000000000000000000000000000000000000000000000000000000080",
+               },
+               // p+11 is not a valid y-coordinate.
+               // p+12 is not a valid y-coordinate.
+               // p+13 is not a valid y-coordinate.
+               {
+                       "y=p+14,sign+",
+                       "fbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+                       "0e00000000000000000000000000000000000000000000000000000000000000",
+               },
+               {
+                       "y=p+14,sign-",
+                       "fbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+                       "0e00000000000000000000000000000000000000000000000000000000000080",
+               },
+               {
+                       "y=p+15,sign+",
+                       "fcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+                       "0f00000000000000000000000000000000000000000000000000000000000000",
+               },
+               {
+                       "y=p+15,sign-",
+                       "fcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+                       "0f00000000000000000000000000000000000000000000000000000000000080",
+               },
+               {
+                       "y=p+16,sign+",
+                       "fdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+                       "1000000000000000000000000000000000000000000000000000000000000000",
+               },
+               {
+                       "y=p+16,sign-",
+                       "fdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+                       "1000000000000000000000000000000000000000000000000000000000000080",
+               },
+               // p+17 is not a valid y-coordinate.
+               {
+                       "y=p+18,sign+",
+                       "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+                       "1200000000000000000000000000000000000000000000000000000000000000",
+               },
+               {
+                       "y=p+18,sign-",
+                       "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+                       "1200000000000000000000000000000000000000000000000000000000000080",
+               },
+       }
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       p1, err := new(Point).SetBytes(decodeHex(tt.encoding))
+                       if err != nil {
+                               t.Fatalf("error decoding non-canonical point: %v", err)
+                       }
+                       p2, err := new(Point).SetBytes(decodeHex(tt.canonical))
+                       if err != nil {
+                               t.Fatalf("error decoding canonical point: %v", err)
+                       }
+                       if p1.Equal(p2) != 1 {
+                               t.Errorf("equivalent points are not equal: %v, %v", p1, p2)
+                       }
+                       if encoding := hex.EncodeToString(p1.Bytes()); encoding != tt.canonical {
+                               t.Errorf("re-encoding does not match canonical; got %q, expected %q", encoding, tt.canonical)
+                       }
+                       checkOnCurve(t, p1, p2)
+               })
+       }
+}
+
+var testAllocationsSink byte
+
+func TestAllocations(t *testing.T) {
+       if runtime.Compiler == "gccgo" {
+               t.Skip("gofronted escape analysis not good enough")
+       }
+       if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-noopt") {
+               t.Skip("skipping allocations test without relevant optimizations")
+       }
+       if allocs := testing.AllocsPerRun(100, func() {
+               p := NewIdentityPoint()
+               p.Add(p, NewGeneratorPoint())
+               s := NewScalar()
+               testAllocationsSink ^= s.Bytes()[0]
+               testAllocationsSink ^= p.Bytes()[0]
+       }); allocs > 0 {
+               t.Errorf("expected zero allocations, got %0.1v", allocs)
+       }
+}
+
+func decodeHex(s string) []byte {
+       b, err := hex.DecodeString(s)
+       if err != nil {
+               panic(err)
+       }
+       return b
+}
diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/field/_asm/fe_amd64_asm.go b/libgo/go/crypto/ed25519/internal/edwards25519/field/_asm/fe_amd64_asm.go
new file mode 100644 (file)
index 0000000..fbc0cce
--- /dev/null
@@ -0,0 +1,294 @@
+// Copyright (c) 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+       "fmt"
+
+       . "github.com/mmcloughlin/avo/build"
+       . "github.com/mmcloughlin/avo/gotypes"
+       . "github.com/mmcloughlin/avo/operand"
+       . "github.com/mmcloughlin/avo/reg"
+)
+
+//go:generate go run . -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field
+
+func main() {
+       Package("crypto/ed25519/internal/edwards25519/field")
+       ConstraintExpr("amd64,gc,!purego")
+       feMul()
+       feSquare()
+       Generate()
+}
+
+type namedComponent struct {
+       Component
+       name string
+}
+
+func (c namedComponent) String() string { return c.name }
+
+type uint128 struct {
+       name   string
+       hi, lo GPVirtual
+}
+
+func (c uint128) String() string { return c.name }
+
+func feSquare() {
+       TEXT("feSquare", NOSPLIT, "func(out, a *Element)")
+       Doc("feSquare sets out = a * a. It works like feSquareGeneric.")
+       Pragma("noescape")
+
+       a := Dereference(Param("a"))
+       l0 := namedComponent{a.Field("l0"), "l0"}
+       l1 := namedComponent{a.Field("l1"), "l1"}
+       l2 := namedComponent{a.Field("l2"), "l2"}
+       l3 := namedComponent{a.Field("l3"), "l3"}
+       l4 := namedComponent{a.Field("l4"), "l4"}
+
+       // r0 = l0×l0 + 19×2×(l1×l4 + l2×l3)
+       r0 := uint128{"r0", GP64(), GP64()}
+       mul64(r0, 1, l0, l0)
+       addMul64(r0, 38, l1, l4)
+       addMul64(r0, 38, l2, l3)
+
+       // r1 = 2×l0×l1 + 19×2×l2×l4 + 19×l3×l3
+       r1 := uint128{"r1", GP64(), GP64()}
+       mul64(r1, 2, l0, l1)
+       addMul64(r1, 38, l2, l4)
+       addMul64(r1, 19, l3, l3)
+
+       // r2 = = 2×l0×l2 + l1×l1 + 19×2×l3×l4
+       r2 := uint128{"r2", GP64(), GP64()}
+       mul64(r2, 2, l0, l2)
+       addMul64(r2, 1, l1, l1)
+       addMul64(r2, 38, l3, l4)
+
+       // r3 = = 2×l0×l3 + 2×l1×l2 + 19×l4×l4
+       r3 := uint128{"r3", GP64(), GP64()}
+       mul64(r3, 2, l0, l3)
+       addMul64(r3, 2, l1, l2)
+       addMul64(r3, 19, l4, l4)
+
+       // r4 = = 2×l0×l4 + 2×l1×l3 + l2×l2
+       r4 := uint128{"r4", GP64(), GP64()}
+       mul64(r4, 2, l0, l4)
+       addMul64(r4, 2, l1, l3)
+       addMul64(r4, 1, l2, l2)
+
+       Comment("First reduction chain")
+       maskLow51Bits := GP64()
+       MOVQ(Imm((1<<51)-1), maskLow51Bits)
+       c0, r0lo := shiftRightBy51(&r0)
+       c1, r1lo := shiftRightBy51(&r1)
+       c2, r2lo := shiftRightBy51(&r2)
+       c3, r3lo := shiftRightBy51(&r3)
+       c4, r4lo := shiftRightBy51(&r4)
+       maskAndAdd(r0lo, maskLow51Bits, c4, 19)
+       maskAndAdd(r1lo, maskLow51Bits, c0, 1)
+       maskAndAdd(r2lo, maskLow51Bits, c1, 1)
+       maskAndAdd(r3lo, maskLow51Bits, c2, 1)
+       maskAndAdd(r4lo, maskLow51Bits, c3, 1)
+
+       Comment("Second reduction chain (carryPropagate)")
+       // c0 = r0 >> 51
+       MOVQ(r0lo, c0)
+       SHRQ(Imm(51), c0)
+       // c1 = r1 >> 51
+       MOVQ(r1lo, c1)
+       SHRQ(Imm(51), c1)
+       // c2 = r2 >> 51
+       MOVQ(r2lo, c2)
+       SHRQ(Imm(51), c2)
+       // c3 = r3 >> 51
+       MOVQ(r3lo, c3)
+       SHRQ(Imm(51), c3)
+       // c4 = r4 >> 51
+       MOVQ(r4lo, c4)
+       SHRQ(Imm(51), c4)
+       maskAndAdd(r0lo, maskLow51Bits, c4, 19)
+       maskAndAdd(r1lo, maskLow51Bits, c0, 1)
+       maskAndAdd(r2lo, maskLow51Bits, c1, 1)
+       maskAndAdd(r3lo, maskLow51Bits, c2, 1)
+       maskAndAdd(r4lo, maskLow51Bits, c3, 1)
+
+       Comment("Store output")
+       out := Dereference(Param("out"))
+       Store(r0lo, out.Field("l0"))
+       Store(r1lo, out.Field("l1"))
+       Store(r2lo, out.Field("l2"))
+       Store(r3lo, out.Field("l3"))
+       Store(r4lo, out.Field("l4"))
+
+       RET()
+}
+
+func feMul() {
+       TEXT("feMul", NOSPLIT, "func(out, a, b *Element)")
+       Doc("feMul sets out = a * b. It works like feMulGeneric.")
+       Pragma("noescape")
+
+       a := Dereference(Param("a"))
+       a0 := namedComponent{a.Field("l0"), "a0"}
+       a1 := namedComponent{a.Field("l1"), "a1"}
+       a2 := namedComponent{a.Field("l2"), "a2"}
+       a3 := namedComponent{a.Field("l3"), "a3"}
+       a4 := namedComponent{a.Field("l4"), "a4"}
+
+       b := Dereference(Param("b"))
+       b0 := namedComponent{b.Field("l0"), "b0"}
+       b1 := namedComponent{b.Field("l1"), "b1"}
+       b2 := namedComponent{b.Field("l2"), "b2"}
+       b3 := namedComponent{b.Field("l3"), "b3"}
+       b4 := namedComponent{b.Field("l4"), "b4"}
+
+       // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1)
+       r0 := uint128{"r0", GP64(), GP64()}
+       mul64(r0, 1, a0, b0)
+       addMul64(r0, 19, a1, b4)
+       addMul64(r0, 19, a2, b3)
+       addMul64(r0, 19, a3, b2)
+       addMul64(r0, 19, a4, b1)
+
+       // r1 = a0×b1 + a1×b0 + 19×(a2×b4 + a3×b3 + a4×b2)
+       r1 := uint128{"r1", GP64(), GP64()}
+       mul64(r1, 1, a0, b1)
+       addMul64(r1, 1, a1, b0)
+       addMul64(r1, 19, a2, b4)
+       addMul64(r1, 19, a3, b3)
+       addMul64(r1, 19, a4, b2)
+
+       // r2 = a0×b2 + a1×b1 + a2×b0 + 19×(a3×b4 + a4×b3)
+       r2 := uint128{"r2", GP64(), GP64()}
+       mul64(r2, 1, a0, b2)
+       addMul64(r2, 1, a1, b1)
+       addMul64(r2, 1, a2, b0)
+       addMul64(r2, 19, a3, b4)
+       addMul64(r2, 19, a4, b3)
+
+       // r3 = a0×b3 + a1×b2 + a2×b1 + a3×b0 + 19×a4×b4
+       r3 := uint128{"r3", GP64(), GP64()}
+       mul64(r3, 1, a0, b3)
+       addMul64(r3, 1, a1, b2)
+       addMul64(r3, 1, a2, b1)
+       addMul64(r3, 1, a3, b0)
+       addMul64(r3, 19, a4, b4)
+
+       // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0
+       r4 := uint128{"r4", GP64(), GP64()}
+       mul64(r4, 1, a0, b4)
+       addMul64(r4, 1, a1, b3)
+       addMul64(r4, 1, a2, b2)
+       addMul64(r4, 1, a3, b1)
+       addMul64(r4, 1, a4, b0)
+
+       Comment("First reduction chain")
+       maskLow51Bits := GP64()
+       MOVQ(Imm((1<<51)-1), maskLow51Bits)
+       c0, r0lo := shiftRightBy51(&r0)
+       c1, r1lo := shiftRightBy51(&r1)
+       c2, r2lo := shiftRightBy51(&r2)
+       c3, r3lo := shiftRightBy51(&r3)
+       c4, r4lo := shiftRightBy51(&r4)
+       maskAndAdd(r0lo, maskLow51Bits, c4, 19)
+       maskAndAdd(r1lo, maskLow51Bits, c0, 1)
+       maskAndAdd(r2lo, maskLow51Bits, c1, 1)
+       maskAndAdd(r3lo, maskLow51Bits, c2, 1)
+       maskAndAdd(r4lo, maskLow51Bits, c3, 1)
+
+       Comment("Second reduction chain (carryPropagate)")
+       // c0 = r0 >> 51
+       MOVQ(r0lo, c0)
+       SHRQ(Imm(51), c0)
+       // c1 = r1 >> 51
+       MOVQ(r1lo, c1)
+       SHRQ(Imm(51), c1)
+       // c2 = r2 >> 51
+       MOVQ(r2lo, c2)
+       SHRQ(Imm(51), c2)
+       // c3 = r3 >> 51
+       MOVQ(r3lo, c3)
+       SHRQ(Imm(51), c3)
+       // c4 = r4 >> 51
+       MOVQ(r4lo, c4)
+       SHRQ(Imm(51), c4)
+       maskAndAdd(r0lo, maskLow51Bits, c4, 19)
+       maskAndAdd(r1lo, maskLow51Bits, c0, 1)
+       maskAndAdd(r2lo, maskLow51Bits, c1, 1)
+       maskAndAdd(r3lo, maskLow51Bits, c2, 1)
+       maskAndAdd(r4lo, maskLow51Bits, c3, 1)
+
+       Comment("Store output")
+       out := Dereference(Param("out"))
+       Store(r0lo, out.Field("l0"))
+       Store(r1lo, out.Field("l1"))
+       Store(r2lo, out.Field("l2"))
+       Store(r3lo, out.Field("l3"))
+       Store(r4lo, out.Field("l4"))
+
+       RET()
+}
+
+// mul64 sets r to i * aX * bX.
+func mul64(r uint128, i int, aX, bX namedComponent) {
+       switch i {
+       case 1:
+               Comment(fmt.Sprintf("%s = %s×%s", r, aX, bX))
+               Load(aX, RAX)
+       case 2:
+               Comment(fmt.Sprintf("%s = 2×%s×%s", r, aX, bX))
+               Load(aX, RAX)
+               SHLQ(Imm(1), RAX)
+       default:
+               panic("unsupported i value")
+       }
+       MULQ(mustAddr(bX)) // RDX, RAX = RAX * bX
+       MOVQ(RAX, r.lo)
+       MOVQ(RDX, r.hi)
+}
+
+// addMul64 sets r to r + i * aX * bX.
+func addMul64(r uint128, i uint64, aX, bX namedComponent) {
+       switch i {
+       case 1:
+               Comment(fmt.Sprintf("%s += %s×%s", r, aX, bX))
+               Load(aX, RAX)
+       default:
+               Comment(fmt.Sprintf("%s += %d×%s×%s", r, i, aX, bX))
+               IMUL3Q(Imm(i), Load(aX, GP64()), RAX)
+       }
+       MULQ(mustAddr(bX)) // RDX, RAX = RAX * bX
+       ADDQ(RAX, r.lo)
+       ADCQ(RDX, r.hi)
+}
+
+// shiftRightBy51 returns r >> 51 and r.lo.
+//
+// After this function is called, the uint128 may not be used anymore.
+func shiftRightBy51(r *uint128) (out, lo GPVirtual) {
+       out = r.hi
+       lo = r.lo
+       SHLQ(Imm(64-51), r.lo, r.hi)
+       r.lo, r.hi = nil, nil // make sure the uint128 is unusable
+       return
+}
+
+// maskAndAdd sets r = r&mask + c*i.
+func maskAndAdd(r, mask, c GPVirtual, i uint64) {
+       ANDQ(mask, r)
+       if i != 1 {
+               IMUL3Q(Imm(i), c, c)
+       }
+       ADDQ(c, r)
+}
+
+func mustAddr(c Component) Op {
+       b, err := c.Resolve()
+       if err != nil {
+               panic(err)
+       }
+       return b.Addr
+}
diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/field/_asm/go.mod b/libgo/go/crypto/ed25519/internal/edwards25519/field/_asm/go.mod
new file mode 100644 (file)
index 0000000..1127ade
--- /dev/null
@@ -0,0 +1,5 @@
+module asm
+
+go 1.16
+
+require github.com/mmcloughlin/avo v0.2.0
diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/field/fe.go b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe.go
new file mode 100644 (file)
index 0000000..dbe8659
--- /dev/null
@@ -0,0 +1,416 @@
+// Copyright (c) 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package field implements fast arithmetic modulo 2^255-19.
+package field
+
+import (
+       "crypto/subtle"
+       "encoding/binary"
+       "math/bits"
+)
+
+// Element represents an element of the field GF(2^255-19). Note that this
+// is not a cryptographically secure group, and should only be used to interact
+// with edwards25519.Point coordinates.
+//
+// This type works similarly to math/big.Int, and all arguments and receivers
+// are allowed to alias.
+//
+// The zero value is a valid zero element.
+type Element struct {
+       // An element t represents the integer
+       //     t.l0 + t.l1*2^51 + t.l2*2^102 + t.l3*2^153 + t.l4*2^204
+       //
+       // Between operations, all limbs are expected to be lower than 2^52.
+       l0 uint64
+       l1 uint64
+       l2 uint64
+       l3 uint64
+       l4 uint64
+}
+
+const maskLow51Bits uint64 = (1 << 51) - 1
+
+var feZero = &Element{0, 0, 0, 0, 0}
+
+// Zero sets v = 0, and returns v.
+func (v *Element) Zero() *Element {
+       *v = *feZero
+       return v
+}
+
+var feOne = &Element{1, 0, 0, 0, 0}
+
+// One sets v = 1, and returns v.
+func (v *Element) One() *Element {
+       *v = *feOne
+       return v
+}
+
+// reduce reduces v modulo 2^255 - 19 and returns it.
+func (v *Element) reduce() *Element {
+       v.carryPropagate()
+
+       // After the light reduction we now have a field element representation
+       // v < 2^255 + 2^13 * 19, but need v < 2^255 - 19.
+
+       // If v >= 2^255 - 19, then v + 19 >= 2^255, which would overflow 2^255 - 1,
+       // generating a carry. That is, c will be 0 if v < 2^255 - 19, and 1 otherwise.
+       c := (v.l0 + 19) >> 51
+       c = (v.l1 + c) >> 51
+       c = (v.l2 + c) >> 51
+       c = (v.l3 + c) >> 51
+       c = (v.l4 + c) >> 51
+
+       // If v < 2^255 - 19 and c = 0, this will be a no-op. Otherwise, it's
+       // effectively applying the reduction identity to the carry.
+       v.l0 += 19 * c
+
+       v.l1 += v.l0 >> 51
+       v.l0 = v.l0 & maskLow51Bits
+       v.l2 += v.l1 >> 51
+       v.l1 = v.l1 & maskLow51Bits
+       v.l3 += v.l2 >> 51
+       v.l2 = v.l2 & maskLow51Bits
+       v.l4 += v.l3 >> 51
+       v.l3 = v.l3 & maskLow51Bits
+       // no additional carry
+       v.l4 = v.l4 & maskLow51Bits
+
+       return v
+}
+
+// Add sets v = a + b, and returns v.
+func (v *Element) Add(a, b *Element) *Element {
+       v.l0 = a.l0 + b.l0
+       v.l1 = a.l1 + b.l1
+       v.l2 = a.l2 + b.l2
+       v.l3 = a.l3 + b.l3
+       v.l4 = a.l4 + b.l4
+       // Using the generic implementation here is actually faster than the
+       // assembly. Probably because the body of this function is so simple that
+       // the compiler can figure out better optimizations by inlining the carry
+       // propagation.
+       return v.carryPropagateGeneric()
+}
+
+// Subtract sets v = a - b, and returns v.
+func (v *Element) Subtract(a, b *Element) *Element {
+       // We first add 2 * p, to guarantee the subtraction won't underflow, and
+       // then subtract b (which can be up to 2^255 + 2^13 * 19).
+       v.l0 = (a.l0 + 0xFFFFFFFFFFFDA) - b.l0
+       v.l1 = (a.l1 + 0xFFFFFFFFFFFFE) - b.l1
+       v.l2 = (a.l2 + 0xFFFFFFFFFFFFE) - b.l2
+       v.l3 = (a.l3 + 0xFFFFFFFFFFFFE) - b.l3
+       v.l4 = (a.l4 + 0xFFFFFFFFFFFFE) - b.l4
+       return v.carryPropagate()
+}
+
+// Negate sets v = -a, and returns v.
+func (v *Element) Negate(a *Element) *Element {
+       return v.Subtract(feZero, a)
+}
+
+// Invert sets v = 1/z mod p, and returns v.
+//
+// If z == 0, Invert returns v = 0.
+func (v *Element) Invert(z *Element) *Element {
+       // Inversion is implemented as exponentiation with exponent p − 2. It uses the
+       // same sequence of 255 squarings and 11 multiplications as [Curve25519].
+       var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t Element
+
+       z2.Square(z)             // 2
+       t.Square(&z2)            // 4
+       t.Square(&t)             // 8
+       z9.Multiply(&t, z)       // 9
+       z11.Multiply(&z9, &z2)   // 11
+       t.Square(&z11)           // 22
+       z2_5_0.Multiply(&t, &z9) // 31 = 2^5 - 2^0
+
+       t.Square(&z2_5_0) // 2^6 - 2^1
+       for i := 0; i < 4; i++ {
+               t.Square(&t) // 2^10 - 2^5
+       }
+       z2_10_0.Multiply(&t, &z2_5_0) // 2^10 - 2^0
+
+       t.Square(&z2_10_0) // 2^11 - 2^1
+       for i := 0; i < 9; i++ {
+               t.Square(&t) // 2^20 - 2^10
+       }
+       z2_20_0.Multiply(&t, &z2_10_0) // 2^20 - 2^0
+
+       t.Square(&z2_20_0) // 2^21 - 2^1
+       for i := 0; i < 19; i++ {
+               t.Square(&t) // 2^40 - 2^20
+       }
+       t.Multiply(&t, &z2_20_0) // 2^40 - 2^0
+
+       t.Square(&t) // 2^41 - 2^1
+       for i := 0; i < 9; i++ {
+               t.Square(&t) // 2^50 - 2^10
+       }
+       z2_50_0.Multiply(&t, &z2_10_0) // 2^50 - 2^0
+
+       t.Square(&z2_50_0) // 2^51 - 2^1
+       for i := 0; i < 49; i++ {
+               t.Square(&t) // 2^100 - 2^50
+       }
+       z2_100_0.Multiply(&t, &z2_50_0) // 2^100 - 2^0
+
+       t.Square(&z2_100_0) // 2^101 - 2^1
+       for i := 0; i < 99; i++ {
+               t.Square(&t) // 2^200 - 2^100
+       }
+       t.Multiply(&t, &z2_100_0) // 2^200 - 2^0
+
+       t.Square(&t) // 2^201 - 2^1
+       for i := 0; i < 49; i++ {
+               t.Square(&t) // 2^250 - 2^50
+       }
+       t.Multiply(&t, &z2_50_0) // 2^250 - 2^0
+
+       t.Square(&t) // 2^251 - 2^1
+       t.Square(&t) // 2^252 - 2^2
+       t.Square(&t) // 2^253 - 2^3
+       t.Square(&t) // 2^254 - 2^4
+       t.Square(&t) // 2^255 - 2^5
+
+       return v.Multiply(&t, &z11) // 2^255 - 21
+}
+
+// Set sets v = a, and returns v.
+func (v *Element) Set(a *Element) *Element {
+       *v = *a
+       return v
+}
+
+// SetBytes sets v to x, which must be a 32-byte little-endian encoding.
+//
+// Consistent with RFC 7748, the most significant bit (the high bit of the
+// last byte) is ignored, and non-canonical values (2^255-19 through 2^255-1)
+// are accepted. Note that this is laxer than specified by RFC 8032.
+func (v *Element) SetBytes(x []byte) *Element {
+       if len(x) != 32 {
+               panic("edwards25519: invalid field element input size")
+       }
+
+       // Bits 0:51 (bytes 0:8, bits 0:64, shift 0, mask 51).
+       v.l0 = binary.LittleEndian.Uint64(x[0:8])
+       v.l0 &= maskLow51Bits
+       // Bits 51:102 (bytes 6:14, bits 48:112, shift 3, mask 51).
+       v.l1 = binary.LittleEndian.Uint64(x[6:14]) >> 3
+       v.l1 &= maskLow51Bits
+       // Bits 102:153 (bytes 12:20, bits 96:160, shift 6, mask 51).
+       v.l2 = binary.LittleEndian.Uint64(x[12:20]) >> 6
+       v.l2 &= maskLow51Bits
+       // Bits 153:204 (bytes 19:27, bits 152:216, shift 1, mask 51).
+       v.l3 = binary.LittleEndian.Uint64(x[19:27]) >> 1
+       v.l3 &= maskLow51Bits
+       // Bits 204:251 (bytes 24:32, bits 192:256, shift 12, mask 51).
+       // Note: not bytes 25:33, shift 4, to avoid overread.
+       v.l4 = binary.LittleEndian.Uint64(x[24:32]) >> 12
+       v.l4 &= maskLow51Bits
+
+       return v
+}
+
+// Bytes returns the canonical 32-byte little-endian encoding of v.
+func (v *Element) Bytes() []byte {
+       // This function is outlined to make the allocations inline in the caller
+       // rather than happen on the heap.
+       var out [32]byte
+       return v.bytes(&out)
+}
+
+func (v *Element) bytes(out *[32]byte) []byte {
+       t := *v
+       t.reduce()
+
+       var buf [8]byte
+       for i, l := range [5]uint64{t.l0, t.l1, t.l2, t.l3, t.l4} {
+               bitsOffset := i * 51
+               binary.LittleEndian.PutUint64(buf[:], l<<uint(bitsOffset%8))
+               for i, bb := range buf {
+                       off := bitsOffset/8 + i
+                       if off >= len(out) {
+                               break
+                       }
+                       out[off] |= bb
+               }
+       }
+
+       return out[:]
+}
+
+// Equal returns 1 if v and u are equal, and 0 otherwise.
+func (v *Element) Equal(u *Element) int {
+       sa, sv := u.Bytes(), v.Bytes()
+       return subtle.ConstantTimeCompare(sa, sv)
+}
+
+// mask64Bits returns 0xffffffff if cond is 1, and 0 otherwise.
+func mask64Bits(cond int) uint64 { return ^(uint64(cond) - 1) }
+
+// Select sets v to a if cond == 1, and to b if cond == 0.
+func (v *Element) Select(a, b *Element, cond int) *Element {
+       m := mask64Bits(cond)
+       v.l0 = (m & a.l0) | (^m & b.l0)
+       v.l1 = (m & a.l1) | (^m & b.l1)
+       v.l2 = (m & a.l2) | (^m & b.l2)
+       v.l3 = (m & a.l3) | (^m & b.l3)
+       v.l4 = (m & a.l4) | (^m & b.l4)
+       return v
+}
+
+// Swap swaps v and u if cond == 1 or leaves them unchanged if cond == 0, and returns v.
+func (v *Element) Swap(u *Element, cond int) {
+       m := mask64Bits(cond)
+       t := m & (v.l0 ^ u.l0)
+       v.l0 ^= t
+       u.l0 ^= t
+       t = m & (v.l1 ^ u.l1)
+       v.l1 ^= t
+       u.l1 ^= t
+       t = m & (v.l2 ^ u.l2)
+       v.l2 ^= t
+       u.l2 ^= t
+       t = m & (v.l3 ^ u.l3)
+       v.l3 ^= t
+       u.l3 ^= t
+       t = m & (v.l4 ^ u.l4)
+       v.l4 ^= t
+       u.l4 ^= t
+}
+
+// IsNegative returns 1 if v is negative, and 0 otherwise.
+func (v *Element) IsNegative() int {
+       return int(v.Bytes()[0] & 1)
+}
+
+// Absolute sets v to |u|, and returns v.
+func (v *Element) Absolute(u *Element) *Element {
+       return v.Select(new(Element).Negate(u), u, u.IsNegative())
+}
+
+// Multiply sets v = x * y, and returns v.
+func (v *Element) Multiply(x, y *Element) *Element {
+       feMul(v, x, y)
+       return v
+}
+
+// Square sets v = x * x, and returns v.
+func (v *Element) Square(x *Element) *Element {
+       feSquare(v, x)
+       return v
+}
+
+// Mult32 sets v = x * y, and returns v.
+func (v *Element) Mult32(x *Element, y uint32) *Element {
+       x0lo, x0hi := mul51(x.l0, y)
+       x1lo, x1hi := mul51(x.l1, y)
+       x2lo, x2hi := mul51(x.l2, y)
+       x3lo, x3hi := mul51(x.l3, y)
+       x4lo, x4hi := mul51(x.l4, y)
+       v.l0 = x0lo + 19*x4hi // carried over per the reduction identity
+       v.l1 = x1lo + x0hi
+       v.l2 = x2lo + x1hi
+       v.l3 = x3lo + x2hi
+       v.l4 = x4lo + x3hi
+       // The hi portions are going to be only 32 bits, plus any previous excess,
+       // so we can skip the carry propagation.
+       return v
+}
+
+// mul51 returns lo + hi * 2⁵¹ = a * b.
+func mul51(a uint64, b uint32) (lo uint64, hi uint64) {
+       mh, ml := bits.Mul64(a, uint64(b))
+       lo = ml & maskLow51Bits
+       hi = (mh << 13) | (ml >> 51)
+       return
+}
+
+// Pow22523 set v = x^((p-5)/8), and returns v. (p-5)/8 is 2^252-3.
+func (v *Element) Pow22523(x *Element) *Element {
+       var t0, t1, t2 Element
+
+       t0.Square(x)             // x^2
+       t1.Square(&t0)           // x^4
+       t1.Square(&t1)           // x^8
+       t1.Multiply(x, &t1)      // x^9
+       t0.Multiply(&t0, &t1)    // x^11
+       t0.Square(&t0)           // x^22
+       t0.Multiply(&t1, &t0)    // x^31
+       t1.Square(&t0)           // x^62
+       for i := 1; i < 5; i++ { // x^992
+               t1.Square(&t1)
+       }
+       t0.Multiply(&t1, &t0)     // x^1023 -> 1023 = 2^10 - 1
+       t1.Square(&t0)            // 2^11 - 2
+       for i := 1; i < 10; i++ { // 2^20 - 2^10
+               t1.Square(&t1)
+       }
+       t1.Multiply(&t1, &t0)     // 2^20 - 1
+       t2.Square(&t1)            // 2^21 - 2
+       for i := 1; i < 20; i++ { // 2^40 - 2^20
+               t2.Square(&t2)
+       }
+       t1.Multiply(&t2, &t1)     // 2^40 - 1
+       t1.Square(&t1)            // 2^41 - 2
+       for i := 1; i < 10; i++ { // 2^50 - 2^10
+               t1.Square(&t1)
+       }
+       t0.Multiply(&t1, &t0)     // 2^50 - 1
+       t1.Square(&t0)            // 2^51 - 2
+       for i := 1; i < 50; i++ { // 2^100 - 2^50
+               t1.Square(&t1)
+       }
+       t1.Multiply(&t1, &t0)      // 2^100 - 1
+       t2.Square(&t1)             // 2^101 - 2
+       for i := 1; i < 100; i++ { // 2^200 - 2^100
+               t2.Square(&t2)
+       }
+       t1.Multiply(&t2, &t1)     // 2^200 - 1
+       t1.Square(&t1)            // 2^201 - 2
+       for i := 1; i < 50; i++ { // 2^250 - 2^50
+               t1.Square(&t1)
+       }
+       t0.Multiply(&t1, &t0)     // 2^250 - 1
+       t0.Square(&t0)            // 2^251 - 2
+       t0.Square(&t0)            // 2^252 - 4
+       return v.Multiply(&t0, x) // 2^252 - 3 -> x^(2^252-3)
+}
+
+// sqrtM1 is 2^((p-1)/4), which squared is equal to -1 by Euler's Criterion.
+var sqrtM1 = &Element{1718705420411056, 234908883556509,
+       2233514472574048, 2117202627021982, 765476049583133}
+
+// SqrtRatio sets r to the non-negative square root of the ratio of u and v.
+//
+// If u/v is square, SqrtRatio returns r and 1. If u/v is not square, SqrtRatio
+// sets r according to Section 4.3 of draft-irtf-cfrg-ristretto255-decaf448-00,
+// and returns r and 0.
+func (r *Element) SqrtRatio(u, v *Element) (rr *Element, wasSquare int) {
+       var a, b Element
+
+       // r = (u * v3) * (u * v7)^((p-5)/8)
+       v2 := a.Square(v)
+       uv3 := b.Multiply(u, b.Multiply(v2, v))
+       uv7 := a.Multiply(uv3, a.Square(v2))
+       r.Multiply(uv3, r.Pow22523(uv7))
+
+       check := a.Multiply(v, a.Square(r)) // check = v * r^2
+
+       uNeg := b.Negate(u)
+       correctSignSqrt := check.Equal(u)
+       flippedSignSqrt := check.Equal(uNeg)
+       flippedSignSqrtI := check.Equal(uNeg.Multiply(uNeg, sqrtM1))
+
+       rPrime := b.Multiply(r, sqrtM1) // r_prime = SQRT_M1 * r
+       // r = CT_SELECT(r_prime IF flipped_sign_sqrt | flipped_sign_sqrt_i ELSE r)
+       r.Select(rPrime, r, flippedSignSqrt|flippedSignSqrtI)
+
+       r.Absolute(r) // Choose the nonnegative square root.
+       return r, correctSignSqrt | flippedSignSqrt
+}
diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_alias_test.go b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_alias_test.go
new file mode 100644 (file)
index 0000000..5ad81df
--- /dev/null
@@ -0,0 +1,126 @@
+// Copyright (c) 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package field
+
+import (
+       "testing"
+       "testing/quick"
+)
+
+func checkAliasingOneArg(f func(v, x *Element) *Element) func(v, x Element) bool {
+       return func(v, x Element) bool {
+               x1, v1 := x, x
+
+               // Calculate a reference f(x) without aliasing.
+               if out := f(&v, &x); out != &v && isInBounds(out) {
+                       return false
+               }
+
+               // Test aliasing the argument and the receiver.
+               if out := f(&v1, &v1); out != &v1 || v1 != v {
+                       return false
+               }
+
+               // Ensure the arguments was not modified.
+               return x == x1
+       }
+}
+
+func checkAliasingTwoArgs(f func(v, x, y *Element) *Element) func(v, x, y Element) bool {
+       return func(v, x, y Element) bool {
+               x1, y1, v1 := x, y, Element{}
+
+               // Calculate a reference f(x, y) without aliasing.
+               if out := f(&v, &x, &y); out != &v && isInBounds(out) {
+                       return false
+               }
+
+               // Test aliasing the first argument and the receiver.
+               v1 = x
+               if out := f(&v1, &v1, &y); out != &v1 || v1 != v {
+                       return false
+               }
+               // Test aliasing the second argument and the receiver.
+               v1 = y
+               if out := f(&v1, &x, &v1); out != &v1 || v1 != v {
+                       return false
+               }
+
+               // Calculate a reference f(x, x) without aliasing.
+               if out := f(&v, &x, &x); out != &v {
+                       return false
+               }
+
+               // Test aliasing the first argument and the receiver.
+               v1 = x
+               if out := f(&v1, &v1, &x); out != &v1 || v1 != v {
+                       return false
+               }
+               // Test aliasing the second argument and the receiver.
+               v1 = x
+               if out := f(&v1, &x, &v1); out != &v1 || v1 != v {
+                       return false
+               }
+               // Test aliasing both arguments and the receiver.
+               v1 = x
+               if out := f(&v1, &v1, &v1); out != &v1 || v1 != v {
+                       return false
+               }
+
+               // Ensure the arguments were not modified.
+               return x == x1 && y == y1
+       }
+}
+
+// TestAliasing checks that receivers and arguments can alias each other without
+// leading to incorrect results. That is, it ensures that it's safe to write
+//
+//     v.Invert(v)
+//
+// or
+//
+//     v.Add(v, v)
+//
+// without any of the inputs getting clobbered by the output being written.
+func TestAliasing(t *testing.T) {
+       type target struct {
+               name     string
+               oneArgF  func(v, x *Element) *Element
+               twoArgsF func(v, x, y *Element) *Element
+       }
+       for _, tt := range []target{
+               {name: "Absolute", oneArgF: (*Element).Absolute},
+               {name: "Invert", oneArgF: (*Element).Invert},
+               {name: "Negate", oneArgF: (*Element).Negate},
+               {name: "Set", oneArgF: (*Element).Set},
+               {name: "Square", oneArgF: (*Element).Square},
+               {name: "Multiply", twoArgsF: (*Element).Multiply},
+               {name: "Add", twoArgsF: (*Element).Add},
+               {name: "Subtract", twoArgsF: (*Element).Subtract},
+               {
+                       name: "Select0",
+                       twoArgsF: func(v, x, y *Element) *Element {
+                               return (*Element).Select(v, x, y, 0)
+                       },
+               },
+               {
+                       name: "Select1",
+                       twoArgsF: func(v, x, y *Element) *Element {
+                               return (*Element).Select(v, x, y, 1)
+                       },
+               },
+       } {
+               var err error
+               switch {
+               case tt.oneArgF != nil:
+                       err = quick.Check(checkAliasingOneArg(tt.oneArgF), &quick.Config{MaxCountScale: 1 << 8})
+               case tt.twoArgsF != nil:
+                       err = quick.Check(checkAliasingTwoArgs(tt.twoArgsF), &quick.Config{MaxCountScale: 1 << 8})
+               }
+               if err != nil {
+                       t.Errorf("%v: %v", tt.name, err)
+               }
+       }
+}
diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_amd64.go b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_amd64.go
new file mode 100644 (file)
index 0000000..8fe5839
--- /dev/null
@@ -0,0 +1,14 @@
+// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT.
+
+//go:build amd64 && gc && !purego
+// +build amd64,gc,!purego
+
+package field
+
+// feMul sets out = a * b. It works like feMulGeneric.
+//go:noescape
+func feMul(out *Element, a *Element, b *Element)
+
+// feSquare sets out = a * a. It works like feSquareGeneric.
+//go:noescape
+func feSquare(out *Element, a *Element)
diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_amd64_noasm.go b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_amd64_noasm.go
new file mode 100644 (file)
index 0000000..ddb6c9b
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright (c) 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !amd64 || !gc || purego
+// +build !amd64 !gc purego
+
+package field
+
+func feMul(v, x, y *Element) { feMulGeneric(v, x, y) }
+
+func feSquare(v, x *Element) { feSquareGeneric(v, x) }
diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_arm64.go b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_arm64.go
new file mode 100644 (file)
index 0000000..af459ef
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright (c) 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build arm64 && gc && !purego
+// +build arm64,gc,!purego
+
+package field
+
+//go:noescape
+func carryPropagate(v *Element)
+
+func (v *Element) carryPropagate() *Element {
+       carryPropagate(v)
+       return v
+}
diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_arm64_noasm.go b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_arm64_noasm.go
new file mode 100644 (file)
index 0000000..234a5b2
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright (c) 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !arm64 || !gc || purego
+// +build !arm64 !gc purego
+
+package field
+
+func (v *Element) carryPropagate() *Element {
+       return v.carryPropagateGeneric()
+}
diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_bench_test.go b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_bench_test.go
new file mode 100644 (file)
index 0000000..77dc06c
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright (c) 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package field
+
+import "testing"
+
+func BenchmarkAdd(b *testing.B) {
+       var x, y Element
+       x.One()
+       y.Add(feOne, feOne)
+       b.ResetTimer()
+       for i := 0; i < b.N; i++ {
+               x.Add(&x, &y)
+       }
+}
+
+func BenchmarkMultiply(b *testing.B) {
+       var x, y Element
+       x.One()
+       y.Add(feOne, feOne)
+       b.ResetTimer()
+       for i := 0; i < b.N; i++ {
+               x.Multiply(&x, &y)
+       }
+}
+
+func BenchmarkMult32(b *testing.B) {
+       var x Element
+       x.One()
+       b.ResetTimer()
+       for i := 0; i < b.N; i++ {
+               x.Mult32(&x, 0xaa42aa42)
+       }
+}
diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_generic.go b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_generic.go
new file mode 100644 (file)
index 0000000..bccf851
--- /dev/null
@@ -0,0 +1,264 @@
+// Copyright (c) 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package field
+
+import "math/bits"
+
+// uint128 holds a 128-bit number as two 64-bit limbs, for use with the
+// bits.Mul64 and bits.Add64 intrinsics.
+type uint128 struct {
+       lo, hi uint64
+}
+
+// mul64 returns a * b.
+func mul64(a, b uint64) uint128 {
+       hi, lo := bits.Mul64(a, b)
+       return uint128{lo, hi}
+}
+
+// addMul64 returns v + a * b.
+func addMul64(v uint128, a, b uint64) uint128 {
+       hi, lo := bits.Mul64(a, b)
+       lo, c := bits.Add64(lo, v.lo, 0)
+       hi, _ = bits.Add64(hi, v.hi, c)
+       return uint128{lo, hi}
+}
+
+// shiftRightBy51 returns a >> 51. a is assumed to be at most 115 bits.
+func shiftRightBy51(a uint128) uint64 {
+       return (a.hi << (64 - 51)) | (a.lo >> 51)
+}
+
+func feMulGeneric(v, a, b *Element) {
+       a0 := a.l0
+       a1 := a.l1
+       a2 := a.l2
+       a3 := a.l3
+       a4 := a.l4
+
+       b0 := b.l0
+       b1 := b.l1
+       b2 := b.l2
+       b3 := b.l3
+       b4 := b.l4
+
+       // Limb multiplication works like pen-and-paper columnar multiplication, but
+       // with 51-bit limbs instead of digits.
+       //
+       //                          a4   a3   a2   a1   a0  x
+       //                          b4   b3   b2   b1   b0  =
+       //                         ------------------------
+       //                        a4b0 a3b0 a2b0 a1b0 a0b0  +
+       //                   a4b1 a3b1 a2b1 a1b1 a0b1       +
+       //              a4b2 a3b2 a2b2 a1b2 a0b2            +
+       //         a4b3 a3b3 a2b3 a1b3 a0b3                 +
+       //    a4b4 a3b4 a2b4 a1b4 a0b4                      =
+       //   ----------------------------------------------
+       //      r8   r7   r6   r5   r4   r3   r2   r1   r0
+       //
+       // We can then use the reduction identity (a * 2²⁵⁵ + b = a * 19 + b) to
+       // reduce the limbs that would overflow 255 bits. r5 * 2²⁵⁵ becomes 19 * r5,
+       // r6 * 2³⁰⁶ becomes 19 * r6 * 2⁵¹, etc.
+       //
+       // Reduction can be carried out simultaneously to multiplication. For
+       // example, we do not compute r5: whenever the result of a multiplication
+       // belongs to r5, like a1b4, we multiply it by 19 and add the result to r0.
+       //
+       //            a4b0    a3b0    a2b0    a1b0    a0b0  +
+       //            a3b1    a2b1    a1b1    a0b1 19×a4b1  +
+       //            a2b2    a1b2    a0b2 19×a4b2 19×a3b2  +
+       //            a1b3    a0b3 19×a4b3 19×a3b3 19×a2b3  +
+       //            a0b4 19×a4b4 19×a3b4 19×a2b4 19×a1b4  =
+       //           --------------------------------------
+       //              r4      r3      r2      r1      r0
+       //
+       // Finally we add up the columns into wide, overlapping limbs.
+
+       a1_19 := a1 * 19
+       a2_19 := a2 * 19
+       a3_19 := a3 * 19
+       a4_19 := a4 * 19
+
+       // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1)
+       r0 := mul64(a0, b0)
+       r0 = addMul64(r0, a1_19, b4)
+       r0 = addMul64(r0, a2_19, b3)
+       r0 = addMul64(r0, a3_19, b2)
+       r0 = addMul64(r0, a4_19, b1)
+
+       // r1 = a0×b1 + a1×b0 + 19×(a2×b4 + a3×b3 + a4×b2)
+       r1 := mul64(a0, b1)
+       r1 = addMul64(r1, a1, b0)
+       r1 = addMul64(r1, a2_19, b4)
+       r1 = addMul64(r1, a3_19, b3)
+       r1 = addMul64(r1, a4_19, b2)
+
+       // r2 = a0×b2 + a1×b1 + a2×b0 + 19×(a3×b4 + a4×b3)
+       r2 := mul64(a0, b2)
+       r2 = addMul64(r2, a1, b1)
+       r2 = addMul64(r2, a2, b0)
+       r2 = addMul64(r2, a3_19, b4)
+       r2 = addMul64(r2, a4_19, b3)
+
+       // r3 = a0×b3 + a1×b2 + a2×b1 + a3×b0 + 19×a4×b4
+       r3 := mul64(a0, b3)
+       r3 = addMul64(r3, a1, b2)
+       r3 = addMul64(r3, a2, b1)
+       r3 = addMul64(r3, a3, b0)
+       r3 = addMul64(r3, a4_19, b4)
+
+       // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0
+       r4 := mul64(a0, b4)
+       r4 = addMul64(r4, a1, b3)
+       r4 = addMul64(r4, a2, b2)
+       r4 = addMul64(r4, a3, b1)
+       r4 = addMul64(r4, a4, b0)
+
+       // After the multiplication, we need to reduce (carry) the five coefficients
+       // to obtain a result with limbs that are at most slightly larger than 2⁵¹,
+       // to respect the Element invariant.
+       //
+       // Overall, the reduction works the same as carryPropagate, except with
+       // wider inputs: we take the carry for each coefficient by shifting it right
+       // by 51, and add it to the limb above it. The top carry is multiplied by 19
+       // according to the reduction identity and added to the lowest limb.
+       //
+       // The largest coefficient (r0) will be at most 111 bits, which guarantees
+       // that all carries are at most 111 - 51 = 60 bits, which fits in a uint64.
+       //
+       //     r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1)
+       //     r0 < 2⁵²×2⁵² + 19×(2⁵²×2⁵² + 2⁵²×2⁵² + 2⁵²×2⁵² + 2⁵²×2⁵²)
+       //     r0 < (1 + 19 × 4) × 2⁵² × 2⁵²
+       //     r0 < 2⁷ × 2⁵² × 2⁵²
+       //     r0 < 2¹¹¹
+       //
+       // Moreover, the top coefficient (r4) is at most 107 bits, so c4 is at most
+       // 56 bits, and c4 * 19 is at most 61 bits, which again fits in a uint64 and
+       // allows us to easily apply the reduction identity.
+       //
+       //     r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0
+       //     r4 < 5 × 2⁵² × 2⁵²
+       //     r4 < 2¹⁰⁷
+       //
+
+       c0 := shiftRightBy51(r0)
+       c1 := shiftRightBy51(r1)
+       c2 := shiftRightBy51(r2)
+       c3 := shiftRightBy51(r3)
+       c4 := shiftRightBy51(r4)
+
+       rr0 := r0.lo&maskLow51Bits + c4*19
+       rr1 := r1.lo&maskLow51Bits + c0
+       rr2 := r2.lo&maskLow51Bits + c1
+       rr3 := r3.lo&maskLow51Bits + c2
+       rr4 := r4.lo&maskLow51Bits + c3
+
+       // Now all coefficients fit into 64-bit registers but are still too large to
+       // be passed around as a Element. We therefore do one last carry chain,
+       // where the carries will be small enough to fit in the wiggle room above 2⁵¹.
+       *v = Element{rr0, rr1, rr2, rr3, rr4}
+       v.carryPropagate()
+}
+
+func feSquareGeneric(v, a *Element) {
+       l0 := a.l0
+       l1 := a.l1
+       l2 := a.l2
+       l3 := a.l3
+       l4 := a.l4
+
+       // Squaring works precisely like multiplication above, but thanks to its
+       // symmetry we get to group a few terms together.
+       //
+       //                          l4   l3   l2   l1   l0  x
+       //                          l4   l3   l2   l1   l0  =
+       //                         ------------------------
+       //                        l4l0 l3l0 l2l0 l1l0 l0l0  +
+       //                   l4l1 l3l1 l2l1 l1l1 l0l1       +
+       //              l4l2 l3l2 l2l2 l1l2 l0l2            +
+       //         l4l3 l3l3 l2l3 l1l3 l0l3                 +
+       //    l4l4 l3l4 l2l4 l1l4 l0l4                      =
+       //   ----------------------------------------------
+       //      r8   r7   r6   r5   r4   r3   r2   r1   r0
+       //
+       //            l4l0    l3l0    l2l0    l1l0    l0l0  +
+       //            l3l1    l2l1    l1l1    l0l1 19×l4l1  +
+       //            l2l2    l1l2    l0l2 19×l4l2 19×l3l2  +
+       //            l1l3    l0l3 19×l4l3 19×l3l3 19×l2l3  +
+       //            l0l4 19×l4l4 19×l3l4 19×l2l4 19×l1l4  =
+       //           --------------------------------------
+       //              r4      r3      r2      r1      r0
+       //
+       // With precomputed 2×, 19×, and 2×19× terms, we can compute each limb with
+       // only three Mul64 and four Add64, instead of five and eight.
+
+       l0_2 := l0 * 2
+       l1_2 := l1 * 2
+
+       l1_38 := l1 * 38
+       l2_38 := l2 * 38
+       l3_38 := l3 * 38
+
+       l3_19 := l3 * 19
+       l4_19 := l4 * 19
+
+       // r0 = l0×l0 + 19×(l1×l4 + l2×l3 + l3×l2 + l4×l1) = l0×l0 + 19×2×(l1×l4 + l2×l3)
+       r0 := mul64(l0, l0)
+       r0 = addMul64(r0, l1_38, l4)
+       r0 = addMul64(r0, l2_38, l3)
+
+       // r1 = l0×l1 + l1×l0 + 19×(l2×l4 + l3×l3 + l4×l2) = 2×l0×l1 + 19×2×l2×l4 + 19×l3×l3
+       r1 := mul64(l0_2, l1)
+       r1 = addMul64(r1, l2_38, l4)
+       r1 = addMul64(r1, l3_19, l3)
+
+       // r2 = l0×l2 + l1×l1 + l2×l0 + 19×(l3×l4 + l4×l3) = 2×l0×l2 + l1×l1 + 19×2×l3×l4
+       r2 := mul64(l0_2, l2)
+       r2 = addMul64(r2, l1, l1)
+       r2 = addMul64(r2, l3_38, l4)
+
+       // r3 = l0×l3 + l1×l2 + l2×l1 + l3×l0 + 19×l4×l4 = 2×l0×l3 + 2×l1×l2 + 19×l4×l4
+       r3 := mul64(l0_2, l3)
+       r3 = addMul64(r3, l1_2, l2)
+       r3 = addMul64(r3, l4_19, l4)
+
+       // r4 = l0×l4 + l1×l3 + l2×l2 + l3×l1 + l4×l0 = 2×l0×l4 + 2×l1×l3 + l2×l2
+       r4 := mul64(l0_2, l4)
+       r4 = addMul64(r4, l1_2, l3)
+       r4 = addMul64(r4, l2, l2)
+
+       c0 := shiftRightBy51(r0)
+       c1 := shiftRightBy51(r1)
+       c2 := shiftRightBy51(r2)
+       c3 := shiftRightBy51(r3)
+       c4 := shiftRightBy51(r4)
+
+       rr0 := r0.lo&maskLow51Bits + c4*19
+       rr1 := r1.lo&maskLow51Bits + c0
+       rr2 := r2.lo&maskLow51Bits + c1
+       rr3 := r3.lo&maskLow51Bits + c2
+       rr4 := r4.lo&maskLow51Bits + c3
+
+       *v = Element{rr0, rr1, rr2, rr3, rr4}
+       v.carryPropagate()
+}
+
+// carryPropagate brings the limbs below 52 bits by applying the reduction
+// identity (a * 2²⁵⁵ + b = a * 19 + b) to the l4 carry.
+func (v *Element) carryPropagateGeneric() *Element {
+       c0 := v.l0 >> 51
+       c1 := v.l1 >> 51
+       c2 := v.l2 >> 51
+       c3 := v.l3 >> 51
+       c4 := v.l4 >> 51
+
+       v.l0 = v.l0&maskLow51Bits + c4*19
+       v.l1 = v.l1&maskLow51Bits + c0
+       v.l2 = v.l2&maskLow51Bits + c1
+       v.l3 = v.l3&maskLow51Bits + c2
+       v.l4 = v.l4&maskLow51Bits + c3
+
+       return v
+}
diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_test.go b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_test.go
new file mode 100644 (file)
index 0000000..b484459
--- /dev/null
@@ -0,0 +1,558 @@
+// Copyright (c) 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package field
+
+import (
+       "bytes"
+       "crypto/rand"
+       "encoding/hex"
+       "io"
+       "math/big"
+       "math/bits"
+       mathrand "math/rand"
+       "reflect"
+       "testing"
+       "testing/quick"
+)
+
+func (v Element) String() string {
+       return hex.EncodeToString(v.Bytes())
+}
+
+// quickCheckConfig1024 will make each quickcheck test run (1024 * -quickchecks)
+// times. The default value of -quickchecks is 100.
+var quickCheckConfig1024 = &quick.Config{MaxCountScale: 1 << 10}
+
+func generateFieldElement(rand *mathrand.Rand) Element {
+       const maskLow52Bits = (1 << 52) - 1
+       return Element{
+               rand.Uint64() & maskLow52Bits,
+               rand.Uint64() & maskLow52Bits,
+               rand.Uint64() & maskLow52Bits,
+               rand.Uint64() & maskLow52Bits,
+               rand.Uint64() & maskLow52Bits,
+       }
+}
+
+// weirdLimbs can be combined to generate a range of edge-case field elements.
+// 0 and -1 are intentionally more weighted, as they combine well.
+var (
+       weirdLimbs51 = []uint64{
+               0, 0, 0, 0,
+               1,
+               19 - 1,
+               19,
+               0x2aaaaaaaaaaaa,
+               0x5555555555555,
+               (1 << 51) - 20,
+               (1 << 51) - 19,
+               (1 << 51) - 1, (1 << 51) - 1,
+               (1 << 51) - 1, (1 << 51) - 1,
+       }
+       weirdLimbs52 = []uint64{
+               0, 0, 0, 0, 0, 0,
+               1,
+               19 - 1,
+               19,
+               0x2aaaaaaaaaaaa,
+               0x5555555555555,
+               (1 << 51) - 20,
+               (1 << 51) - 19,
+               (1 << 51) - 1, (1 << 51) - 1,
+               (1 << 51) - 1, (1 << 51) - 1,
+               (1 << 51) - 1, (1 << 51) - 1,
+               1 << 51,
+               (1 << 51) + 1,
+               (1 << 52) - 19,
+               (1 << 52) - 1,
+       }
+)
+
+func generateWeirdFieldElement(rand *mathrand.Rand) Element {
+       return Element{
+               weirdLimbs52[rand.Intn(len(weirdLimbs52))],
+               weirdLimbs51[rand.Intn(len(weirdLimbs51))],
+               weirdLimbs51[rand.Intn(len(weirdLimbs51))],
+               weirdLimbs51[rand.Intn(len(weirdLimbs51))],
+               weirdLimbs51[rand.Intn(len(weirdLimbs51))],
+       }
+}
+
+func (Element) Generate(rand *mathrand.Rand, size int) reflect.Value {
+       if rand.Intn(2) == 0 {
+               return reflect.ValueOf(generateWeirdFieldElement(rand))
+       }
+       return reflect.ValueOf(generateFieldElement(rand))
+}
+
+// isInBounds returns whether the element is within the expected bit size bounds
+// after a light reduction.
+func isInBounds(x *Element) bool {
+       return bits.Len64(x.l0) <= 52 &&
+               bits.Len64(x.l1) <= 52 &&
+               bits.Len64(x.l2) <= 52 &&
+               bits.Len64(x.l3) <= 52 &&
+               bits.Len64(x.l4) <= 52
+}
+
+func TestMultiplyDistributesOverAdd(t *testing.T) {
+       multiplyDistributesOverAdd := func(x, y, z Element) bool {
+               // Compute t1 = (x+y)*z
+               t1 := new(Element)
+               t1.Add(&x, &y)
+               t1.Multiply(t1, &z)
+
+               // Compute t2 = x*z + y*z
+               t2 := new(Element)
+               t3 := new(Element)
+               t2.Multiply(&x, &z)
+               t3.Multiply(&y, &z)
+               t2.Add(t2, t3)
+
+               return t1.Equal(t2) == 1 && isInBounds(t1) && isInBounds(t2)
+       }
+
+       if err := quick.Check(multiplyDistributesOverAdd, quickCheckConfig1024); err != nil {
+               t.Error(err)
+       }
+}
+
+func TestMul64to128(t *testing.T) {
+       a := uint64(5)
+       b := uint64(5)
+       r := mul64(a, b)
+       if r.lo != 0x19 || r.hi != 0 {
+               t.Errorf("lo-range wide mult failed, got %d + %d*(2**64)", r.lo, r.hi)
+       }
+
+       a = uint64(18014398509481983) // 2^54 - 1
+       b = uint64(18014398509481983) // 2^54 - 1
+       r = mul64(a, b)
+       if r.lo != 0xff80000000000001 || r.hi != 0xfffffffffff {
+               t.Errorf("hi-range wide mult failed, got %d + %d*(2**64)", r.lo, r.hi)
+       }
+
+       a = uint64(1125899906842661)
+       b = uint64(2097155)
+       r = mul64(a, b)
+       r = addMul64(r, a, b)
+       r = addMul64(r, a, b)
+       r = addMul64(r, a, b)
+       r = addMul64(r, a, b)
+       if r.lo != 16888498990613035 || r.hi != 640 {
+               t.Errorf("wrong answer: %d + %d*(2**64)", r.lo, r.hi)
+       }
+}
+
+func TestSetBytesRoundTrip(t *testing.T) {
+       f1 := func(in [32]byte, fe Element) bool {
+               fe.SetBytes(in[:])
+
+               // Mask the most significant bit as it's ignored by SetBytes. (Now
+               // instead of earlier so we check the masking in SetBytes is working.)
+               in[len(in)-1] &= (1 << 7) - 1
+
+               return bytes.Equal(in[:], fe.Bytes()) && isInBounds(&fe)
+       }
+       if err := quick.Check(f1, nil); err != nil {
+               t.Errorf("failed bytes->FE->bytes round-trip: %v", err)
+       }
+
+       f2 := func(fe, r Element) bool {
+               r.SetBytes(fe.Bytes())
+
+               // Intentionally not using Equal not to go through Bytes again.
+               // Calling reduce because both Generate and SetBytes can produce
+               // non-canonical representations.
+               fe.reduce()
+               r.reduce()
+               return fe == r
+       }
+       if err := quick.Check(f2, nil); err != nil {
+               t.Errorf("failed FE->bytes->FE round-trip: %v", err)
+       }
+
+       // Check some fixed vectors from dalek
+       type feRTTest struct {
+               fe Element
+               b  []byte
+       }
+       var tests = []feRTTest{
+               {
+                       fe: Element{358744748052810, 1691584618240980, 977650209285361, 1429865912637724, 560044844278676},
+                       b:  []byte{74, 209, 69, 197, 70, 70, 161, 222, 56, 226, 229, 19, 112, 60, 25, 92, 187, 74, 222, 56, 50, 153, 51, 233, 40, 74, 57, 6, 160, 185, 213, 31},
+               },
+               {
+                       fe: Element{84926274344903, 473620666599931, 365590438845504, 1028470286882429, 2146499180330972},
+                       b:  []byte{199, 23, 106, 112, 61, 77, 216, 79, 186, 60, 11, 118, 13, 16, 103, 15, 42, 32, 83, 250, 44, 57, 204, 198, 78, 199, 253, 119, 146, 172, 3, 122},
+               },
+       }
+
+       for _, tt := range tests {
+               b := tt.fe.Bytes()
+               if !bytes.Equal(b, tt.b) || new(Element).SetBytes(tt.b).Equal(&tt.fe) != 1 {
+                       t.Errorf("Failed fixed roundtrip: %v", tt)
+               }
+       }
+}
+
+func swapEndianness(buf []byte) []byte {
+       for i := 0; i < len(buf)/2; i++ {
+               buf[i], buf[len(buf)-i-1] = buf[len(buf)-i-1], buf[i]
+       }
+       return buf
+}
+
+func TestBytesBigEquivalence(t *testing.T) {
+       f1 := func(in [32]byte, fe, fe1 Element) bool {
+               fe.SetBytes(in[:])
+
+               in[len(in)-1] &= (1 << 7) - 1 // mask the most significant bit
+               b := new(big.Int).SetBytes(swapEndianness(in[:]))
+               fe1.fromBig(b)
+
+               if fe != fe1 {
+                       return false
+               }
+
+               buf := make([]byte, 32) // pad with zeroes
+               copy(buf, swapEndianness(fe1.toBig().Bytes()))
+
+               return bytes.Equal(fe.Bytes(), buf) && isInBounds(&fe) && isInBounds(&fe1)
+       }
+       if err := quick.Check(f1, nil); err != nil {
+               t.Error(err)
+       }
+}
+
+// fromBig sets v = n, and returns v. The bit length of n must not exceed 256.
+func (v *Element) fromBig(n *big.Int) *Element {
+       if n.BitLen() > 32*8 {
+               panic("edwards25519: invalid field element input size")
+       }
+
+       buf := make([]byte, 0, 32)
+       for _, word := range n.Bits() {
+               for i := 0; i < bits.UintSize; i += 8 {
+                       if len(buf) >= cap(buf) {
+                               break
+                       }
+                       buf = append(buf, byte(word))
+                       word >>= 8
+               }
+       }
+
+       return v.SetBytes(buf[:32])
+}
+
+func (v *Element) fromDecimal(s string) *Element {
+       n, ok := new(big.Int).SetString(s, 10)
+       if !ok {
+               panic("not a valid decimal: " + s)
+       }
+       return v.fromBig(n)
+}
+
+// toBig returns v as a big.Int.
+func (v *Element) toBig() *big.Int {
+       buf := v.Bytes()
+
+       words := make([]big.Word, 32*8/bits.UintSize)
+       for n := range words {
+               for i := 0; i < bits.UintSize; i += 8 {
+                       if len(buf) == 0 {
+                               break
+                       }
+                       words[n] |= big.Word(buf[0]) << big.Word(i)
+                       buf = buf[1:]
+               }
+       }
+
+       return new(big.Int).SetBits(words)
+}
+
+func TestDecimalConstants(t *testing.T) {
+       sqrtM1String := "19681161376707505956807079304988542015446066515923890162744021073123829784752"
+       if exp := new(Element).fromDecimal(sqrtM1String); sqrtM1.Equal(exp) != 1 {
+               t.Errorf("sqrtM1 is %v, expected %v", sqrtM1, exp)
+       }
+       // d is in the parent package, and we don't want to expose d or fromDecimal.
+       // dString := "37095705934669439343138083508754565189542113879843219016388785533085940283555"
+       // if exp := new(Element).fromDecimal(dString); d.Equal(exp) != 1 {
+       //      t.Errorf("d is %v, expected %v", d, exp)
+       // }
+}
+
+func TestSetBytesRoundTripEdgeCases(t *testing.T) {
+       // TODO: values close to 0, close to 2^255-19, between 2^255-19 and 2^255-1,
+       // and between 2^255 and 2^256-1. Test both the documented SetBytes
+       // behavior, and that Bytes reduces them.
+}
+
+// Tests self-consistency between Multiply and Square.
+func TestConsistency(t *testing.T) {
+       var x Element
+       var x2, x2sq Element
+
+       x = Element{1, 1, 1, 1, 1}
+       x2.Multiply(&x, &x)
+       x2sq.Square(&x)
+
+       if x2 != x2sq {
+               t.Fatalf("all ones failed\nmul: %x\nsqr: %x\n", x2, x2sq)
+       }
+
+       var bytes [32]byte
+
+       _, err := io.ReadFull(rand.Reader, bytes[:])
+       if err != nil {
+               t.Fatal(err)
+       }
+       x.SetBytes(bytes[:])
+
+       x2.Multiply(&x, &x)
+       x2sq.Square(&x)
+
+       if x2 != x2sq {
+               t.Fatalf("all ones failed\nmul: %x\nsqr: %x\n", x2, x2sq)
+       }
+}
+
+func TestEqual(t *testing.T) {
+       x := Element{1, 1, 1, 1, 1}
+       y := Element{5, 4, 3, 2, 1}
+
+       eq := x.Equal(&x)
+       if eq != 1 {
+               t.Errorf("wrong about equality")
+       }
+
+       eq = x.Equal(&y)
+       if eq != 0 {
+               t.Errorf("wrong about inequality")
+       }
+}
+
+func TestInvert(t *testing.T) {
+       x := Element{1, 1, 1, 1, 1}
+       one := Element{1, 0, 0, 0, 0}
+       var xinv, r Element
+
+       xinv.Invert(&x)
+       r.Multiply(&x, &xinv)
+       r.reduce()
+
+       if one != r {
+               t.Errorf("inversion identity failed, got: %x", r)
+       }
+
+       var bytes [32]byte
+
+       _, err := io.ReadFull(rand.Reader, bytes[:])
+       if err != nil {
+               t.Fatal(err)
+       }
+       x.SetBytes(bytes[:])
+
+       xinv.Invert(&x)
+       r.Multiply(&x, &xinv)
+       r.reduce()
+
+       if one != r {
+               t.Errorf("random inversion identity failed, got: %x for field element %x", r, x)
+       }
+
+       zero := Element{}
+       x.Set(&zero)
+       if xx := xinv.Invert(&x); xx != &xinv {
+               t.Errorf("inverting zero did not return the receiver")
+       } else if xinv.Equal(&zero) != 1 {
+               t.Errorf("inverting zero did not return zero")
+       }
+}
+
+func TestSelectSwap(t *testing.T) {
+       a := Element{358744748052810, 1691584618240980, 977650209285361, 1429865912637724, 560044844278676}
+       b := Element{84926274344903, 473620666599931, 365590438845504, 1028470286882429, 2146499180330972}
+
+       var c, d Element
+
+       c.Select(&a, &b, 1)
+       d.Select(&a, &b, 0)
+
+       if c.Equal(&a) != 1 || d.Equal(&b) != 1 {
+               t.Errorf("Select failed")
+       }
+
+       c.Swap(&d, 0)
+
+       if c.Equal(&a) != 1 || d.Equal(&b) != 1 {
+               t.Errorf("Swap failed")
+       }
+
+       c.Swap(&d, 1)
+
+       if c.Equal(&b) != 1 || d.Equal(&a) != 1 {
+               t.Errorf("Swap failed")
+       }
+}
+
+func TestMult32(t *testing.T) {
+       mult32EquivalentToMul := func(x Element, y uint32) bool {
+               t1 := new(Element)
+               for i := 0; i < 100; i++ {
+                       t1.Mult32(&x, y)
+               }
+
+               ty := new(Element)
+               ty.l0 = uint64(y)
+
+               t2 := new(Element)
+               for i := 0; i < 100; i++ {
+                       t2.Multiply(&x, ty)
+               }
+
+               return t1.Equal(t2) == 1 && isInBounds(t1) && isInBounds(t2)
+       }
+
+       if err := quick.Check(mult32EquivalentToMul, quickCheckConfig1024); err != nil {
+               t.Error(err)
+       }
+}
+
+func TestSqrtRatio(t *testing.T) {
+       // From draft-irtf-cfrg-ristretto255-decaf448-00, Appendix A.4.
+       type test struct {
+               u, v      string
+               wasSquare int
+               r         string
+       }
+       var tests = []test{
+               // If u is 0, the function is defined to return (0, TRUE), even if v
+               // is zero. Note that where used in this package, the denominator v
+               // is never zero.
+               {
+                       "0000000000000000000000000000000000000000000000000000000000000000",
+                       "0000000000000000000000000000000000000000000000000000000000000000",
+                       1, "0000000000000000000000000000000000000000000000000000000000000000",
+               },
+               // 0/1 == 0²
+               {
+                       "0000000000000000000000000000000000000000000000000000000000000000",
+                       "0100000000000000000000000000000000000000000000000000000000000000",
+                       1, "0000000000000000000000000000000000000000000000000000000000000000",
+               },
+               // If u is non-zero and v is zero, defined to return (0, FALSE).
+               {
+                       "0100000000000000000000000000000000000000000000000000000000000000",
+                       "0000000000000000000000000000000000000000000000000000000000000000",
+                       0, "0000000000000000000000000000000000000000000000000000000000000000",
+               },
+               // 2/1 is not square in this field.
+               {
+                       "0200000000000000000000000000000000000000000000000000000000000000",
+                       "0100000000000000000000000000000000000000000000000000000000000000",
+                       0, "3c5ff1b5d8e4113b871bd052f9e7bcd0582804c266ffb2d4f4203eb07fdb7c54",
+               },
+               // 4/1 == 2²
+               {
+                       "0400000000000000000000000000000000000000000000000000000000000000",
+                       "0100000000000000000000000000000000000000000000000000000000000000",
+                       1, "0200000000000000000000000000000000000000000000000000000000000000",
+               },
+               // 1/4 == (2⁻¹)² == (2^(p-2))² per Euler's theorem
+               {
+                       "0100000000000000000000000000000000000000000000000000000000000000",
+                       "0400000000000000000000000000000000000000000000000000000000000000",
+                       1, "f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f",
+               },
+       }
+
+       for i, tt := range tests {
+               u := new(Element).SetBytes(decodeHex(tt.u))
+               v := new(Element).SetBytes(decodeHex(tt.v))
+               want := new(Element).SetBytes(decodeHex(tt.r))
+               got, wasSquare := new(Element).SqrtRatio(u, v)
+               if got.Equal(want) == 0 || wasSquare != tt.wasSquare {
+                       t.Errorf("%d: got (%v, %v), want (%v, %v)", i, got, wasSquare, want, tt.wasSquare)
+               }
+       }
+}
+
+func TestCarryPropagate(t *testing.T) {
+       asmLikeGeneric := func(a [5]uint64) bool {
+               t1 := &Element{a[0], a[1], a[2], a[3], a[4]}
+               t2 := &Element{a[0], a[1], a[2], a[3], a[4]}
+
+               t1.carryPropagate()
+               t2.carryPropagateGeneric()
+
+               if *t1 != *t2 {
+                       t.Logf("got: %#v,\nexpected: %#v", t1, t2)
+               }
+
+               return *t1 == *t2 && isInBounds(t2)
+       }
+
+       if err := quick.Check(asmLikeGeneric, quickCheckConfig1024); err != nil {
+               t.Error(err)
+       }
+
+       if !asmLikeGeneric([5]uint64{0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}) {
+               t.Errorf("failed for {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}")
+       }
+}
+
+func TestFeSquare(t *testing.T) {
+       asmLikeGeneric := func(a Element) bool {
+               t1 := a
+               t2 := a
+
+               feSquareGeneric(&t1, &t1)
+               feSquare(&t2, &t2)
+
+               if t1 != t2 {
+                       t.Logf("got: %#v,\nexpected: %#v", t1, t2)
+               }
+
+               return t1 == t2 && isInBounds(&t2)
+       }
+
+       if err := quick.Check(asmLikeGeneric, quickCheckConfig1024); err != nil {
+               t.Error(err)
+       }
+}
+
+func TestFeMul(t *testing.T) {
+       asmLikeGeneric := func(a, b Element) bool {
+               a1 := a
+               a2 := a
+               b1 := b
+               b2 := b
+
+               feMulGeneric(&a1, &a1, &b1)
+               feMul(&a2, &a2, &b2)
+
+               if a1 != a2 || b1 != b2 {
+                       t.Logf("got: %#v,\nexpected: %#v", a1, a2)
+                       t.Logf("got: %#v,\nexpected: %#v", b1, b2)
+               }
+
+               return a1 == a2 && isInBounds(&a2) &&
+                       b1 == b2 && isInBounds(&b2)
+       }
+
+       if err := quick.Check(asmLikeGeneric, quickCheckConfig1024); err != nil {
+               t.Error(err)
+       }
+}
+
+func decodeHex(s string) []byte {
+       b, err := hex.DecodeString(s)
+       if err != nil {
+               panic(err)
+       }
+       return b
+}
diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/scalar.go b/libgo/go/crypto/ed25519/internal/edwards25519/scalar.go
new file mode 100644 (file)
index 0000000..889acaa
--- /dev/null
@@ -0,0 +1,1025 @@
+// Copyright (c) 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package edwards25519
+
+import (
+       "crypto/subtle"
+       "encoding/binary"
+       "errors"
+)
+
+// A Scalar is an integer modulo
+//
+//     l = 2^252 + 27742317777372353535851937790883648493
+//
+// which is the prime order of the edwards25519 group.
+//
+// This type works similarly to math/big.Int, and all arguments and
+// receivers are allowed to alias.
+//
+// The zero value is a valid zero element.
+type Scalar struct {
+       // s is the Scalar value in little-endian. The value is always reduced
+       // between operations.
+       s [32]byte
+}
+
+var (
+       scZero = Scalar{[32]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}
+
+       scOne = Scalar{[32]byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}
+
+       scMinusOne = Scalar{[32]byte{236, 211, 245, 92, 26, 99, 18, 88, 214, 156, 247, 162, 222, 249, 222, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16}}
+)
+
+// NewScalar returns a new zero Scalar.
+func NewScalar() *Scalar {
+       return &Scalar{}
+}
+
+// MultiplyAdd sets s = x * y + z mod l, and returns s.
+func (s *Scalar) MultiplyAdd(x, y, z *Scalar) *Scalar {
+       scMulAdd(&s.s, &x.s, &y.s, &z.s)
+       return s
+}
+
+// Add sets s = x + y mod l, and returns s.
+func (s *Scalar) Add(x, y *Scalar) *Scalar {
+       // s = 1 * x + y mod l
+       scMulAdd(&s.s, &scOne.s, &x.s, &y.s)
+       return s
+}
+
+// Subtract sets s = x - y mod l, and returns s.
+func (s *Scalar) Subtract(x, y *Scalar) *Scalar {
+       // s = -1 * y + x mod l
+       scMulAdd(&s.s, &scMinusOne.s, &y.s, &x.s)
+       return s
+}
+
+// Negate sets s = -x mod l, and returns s.
+func (s *Scalar) Negate(x *Scalar) *Scalar {
+       // s = -1 * x + 0 mod l
+       scMulAdd(&s.s, &scMinusOne.s, &x.s, &scZero.s)
+       return s
+}
+
+// Multiply sets s = x * y mod l, and returns s.
+func (s *Scalar) Multiply(x, y *Scalar) *Scalar {
+       // s = x * y + 0 mod l
+       scMulAdd(&s.s, &x.s, &y.s, &scZero.s)
+       return s
+}
+
+// Set sets s = x, and returns s.
+func (s *Scalar) Set(x *Scalar) *Scalar {
+       *s = *x
+       return s
+}
+
+// SetUniformBytes sets s to an uniformly distributed value given 64 uniformly
+// distributed random bytes.
+func (s *Scalar) SetUniformBytes(x []byte) *Scalar {
+       if len(x) != 64 {
+               panic("edwards25519: invalid SetUniformBytes input length")
+       }
+       var wideBytes [64]byte
+       copy(wideBytes[:], x[:])
+       scReduce(&s.s, &wideBytes)
+       return s
+}
+
+// SetCanonicalBytes sets s = x, where x is a 32-byte little-endian encoding of
+// s, and returns s. If x is not a canonical encoding of s, SetCanonicalBytes
+// returns nil and an error, and the receiver is unchanged.
+func (s *Scalar) SetCanonicalBytes(x []byte) (*Scalar, error) {
+       if len(x) != 32 {
+               return nil, errors.New("invalid scalar length")
+       }
+       ss := &Scalar{}
+       copy(ss.s[:], x)
+       if !isReduced(ss) {
+               return nil, errors.New("invalid scalar encoding")
+       }
+       s.s = ss.s
+       return s, nil
+}
+
+// isReduced returns whether the given scalar is reduced modulo l.
+func isReduced(s *Scalar) bool {
+       for i := len(s.s) - 1; i >= 0; i-- {
+               switch {
+               case s.s[i] > scMinusOne.s[i]:
+                       return false
+               case s.s[i] < scMinusOne.s[i]:
+                       return true
+               }
+       }
+       return true
+}
+
+// SetBytesWithClamping applies the buffer pruning described in RFC 8032,
+// Section 5.1.5 (also known as clamping) and sets s to the result. The input
+// must be 32 bytes, and it is not modified.
+//
+// Note that since Scalar values are always reduced modulo the prime order of
+// the curve, the resulting value will not preserve any of the cofactor-clearing
+// properties that clamping is meant to provide. It will however work as
+// expected as long as it is applied to points on the prime order subgroup, like
+// in Ed25519. In fact, it is lost to history why RFC 8032 adopted the
+// irrelevant RFC 7748 clamping, but it is now required for compatibility.
+func (s *Scalar) SetBytesWithClamping(x []byte) *Scalar {
+       // The description above omits the purpose of the high bits of the clamping
+       // for brevity, but those are also lost to reductions, and are also
+       // irrelevant to edwards25519 as they protect against a specific
+       // implementation bug that was once observed in a generic Montgomery ladder.
+       if len(x) != 32 {
+               panic("edwards25519: invalid SetBytesWithClamping input length")
+       }
+       var wideBytes [64]byte
+       copy(wideBytes[:], x[:])
+       wideBytes[0] &= 248
+       wideBytes[31] &= 63
+       wideBytes[31] |= 64
+       scReduce(&s.s, &wideBytes)
+       return s
+}
+
+// Bytes returns the canonical 32-byte little-endian encoding of s.
+func (s *Scalar) Bytes() []byte {
+       buf := make([]byte, 32)
+       copy(buf, s.s[:])
+       return buf
+}
+
+// Equal returns 1 if s and t are equal, and 0 otherwise.
+func (s *Scalar) Equal(t *Scalar) int {
+       return subtle.ConstantTimeCompare(s.s[:], t.s[:])
+}
+
+// scMulAdd and scReduce are ported from the public domain, “ref10”
+// implementation of ed25519 from SUPERCOP.
+
+func load3(in []byte) int64 {
+       r := int64(in[0])
+       r |= int64(in[1]) << 8
+       r |= int64(in[2]) << 16
+       return r
+}
+
+func load4(in []byte) int64 {
+       r := int64(in[0])
+       r |= int64(in[1]) << 8
+       r |= int64(in[2]) << 16
+       r |= int64(in[3]) << 24
+       return r
+}
+
+// Input:
+//   a[0]+256*a[1]+...+256^31*a[31] = a
+//   b[0]+256*b[1]+...+256^31*b[31] = b
+//   c[0]+256*c[1]+...+256^31*c[31] = c
+//
+// Output:
+//   s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
+//   where l = 2^252 + 27742317777372353535851937790883648493.
+func scMulAdd(s, a, b, c *[32]byte) {
+       a0 := 2097151 & load3(a[:])
+       a1 := 2097151 & (load4(a[2:]) >> 5)
+       a2 := 2097151 & (load3(a[5:]) >> 2)
+       a3 := 2097151 & (load4(a[7:]) >> 7)
+       a4 := 2097151 & (load4(a[10:]) >> 4)
+       a5 := 2097151 & (load3(a[13:]) >> 1)
+       a6 := 2097151 & (load4(a[15:]) >> 6)
+       a7 := 2097151 & (load3(a[18:]) >> 3)
+       a8 := 2097151 & load3(a[21:])
+       a9 := 2097151 & (load4(a[23:]) >> 5)
+       a10 := 2097151 & (load3(a[26:]) >> 2)
+       a11 := (load4(a[28:]) >> 7)
+       b0 := 2097151 & load3(b[:])
+       b1 := 2097151 & (load4(b[2:]) >> 5)
+       b2 := 2097151 & (load3(b[5:]) >> 2)
+       b3 := 2097151 & (load4(b[7:]) >> 7)
+       b4 := 2097151 & (load4(b[10:]) >> 4)
+       b5 := 2097151 & (load3(b[13:]) >> 1)
+       b6 := 2097151 & (load4(b[15:]) >> 6)
+       b7 := 2097151 & (load3(b[18:]) >> 3)
+       b8 := 2097151 & load3(b[21:])
+       b9 := 2097151 & (load4(b[23:]) >> 5)
+       b10 := 2097151 & (load3(b[26:]) >> 2)
+       b11 := (load4(b[28:]) >> 7)
+       c0 := 2097151 & load3(c[:])
+       c1 := 2097151 & (load4(c[2:]) >> 5)
+       c2 := 2097151 & (load3(c[5:]) >> 2)
+       c3 := 2097151 & (load4(c[7:]) >> 7)
+       c4 := 2097151 & (load4(c[10:]) >> 4)
+       c5 := 2097151 & (load3(c[13:]) >> 1)
+       c6 := 2097151 & (load4(c[15:]) >> 6)
+       c7 := 2097151 & (load3(c[18:]) >> 3)
+       c8 := 2097151 & load3(c[21:])
+       c9 := 2097151 & (load4(c[23:]) >> 5)
+       c10 := 2097151 & (load3(c[26:]) >> 2)
+       c11 := (load4(c[28:]) >> 7)
+       var carry [23]int64
+
+       s0 := c0 + a0*b0
+       s1 := c1 + a0*b1 + a1*b0
+       s2 := c2 + a0*b2 + a1*b1 + a2*b0
+       s3 := c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0
+       s4 := c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0
+       s5 := c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0
+       s6 := c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0
+       s7 := c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0
+       s8 := c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0
+       s9 := c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0
+       s10 := c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0
+       s11 := c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0
+       s12 := a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1
+       s13 := a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2
+       s14 := a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3
+       s15 := a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4
+       s16 := a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5
+       s17 := a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6
+       s18 := a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7
+       s19 := a8*b11 + a9*b10 + a10*b9 + a11*b8
+       s20 := a9*b11 + a10*b10 + a11*b9
+       s21 := a10*b11 + a11*b10
+       s22 := a11 * b11
+       s23 := int64(0)
+
+       carry[0] = (s0 + (1 << 20)) >> 21
+       s1 += carry[0]
+       s0 -= carry[0] << 21
+       carry[2] = (s2 + (1 << 20)) >> 21
+       s3 += carry[2]
+       s2 -= carry[2] << 21
+       carry[4] = (s4 + (1 << 20)) >> 21
+       s5 += carry[4]
+       s4 -= carry[4] << 21
+       carry[6] = (s6 + (1 << 20)) >> 21
+       s7 += carry[6]
+       s6 -= carry[6] << 21
+       carry[8] = (s8 + (1 << 20)) >> 21
+       s9 += carry[8]
+       s8 -= carry[8] << 21
+       carry[10] = (s10 + (1 << 20)) >> 21
+       s11 += carry[10]
+       s10 -= carry[10] << 21
+       carry[12] = (s12 + (1 << 20)) >> 21
+       s13 += carry[12]
+       s12 -= carry[12] << 21
+       carry[14] = (s14 + (1 << 20)) >> 21
+       s15 += carry[14]
+       s14 -= carry[14] << 21
+       carry[16] = (s16 + (1 << 20)) >> 21
+       s17 += carry[16]
+       s16 -= carry[16] << 21
+       carry[18] = (s18 + (1 << 20)) >> 21
+       s19 += carry[18]
+       s18 -= carry[18] << 21
+       carry[20] = (s20 + (1 << 20)) >> 21
+       s21 += carry[20]
+       s20 -= carry[20] << 21
+       carry[22] = (s22 + (1 << 20)) >> 21
+       s23 += carry[22]
+       s22 -= carry[22] << 21
+
+       carry[1] = (s1 + (1 << 20)) >> 21
+       s2 += carry[1]
+       s1 -= carry[1] << 21
+       carry[3] = (s3 + (1 << 20)) >> 21
+       s4 += carry[3]
+       s3 -= carry[3] << 21
+       carry[5] = (s5 + (1 << 20)) >> 21
+       s6 += carry[5]
+       s5 -= carry[5] << 21
+       carry[7] = (s7 + (1 << 20)) >> 21
+       s8 += carry[7]
+       s7 -= carry[7] << 21
+       carry[9] = (s9 + (1 << 20)) >> 21
+       s10 += carry[9]
+       s9 -= carry[9] << 21
+       carry[11] = (s11 + (1 << 20)) >> 21
+       s12 += carry[11]
+       s11 -= carry[11] << 21
+       carry[13] = (s13 + (1 << 20)) >> 21
+       s14 += carry[13]
+       s13 -= carry[13] << 21
+       carry[15] = (s15 + (1 << 20)) >> 21
+       s16 += carry[15]
+       s15 -= carry[15] << 21
+       carry[17] = (s17 + (1 << 20)) >> 21
+       s18 += carry[17]
+       s17 -= carry[17] << 21
+       carry[19] = (s19 + (1 << 20)) >> 21
+       s20 += carry[19]
+       s19 -= carry[19] << 21
+       carry[21] = (s21 + (1 << 20)) >> 21
+       s22 += carry[21]
+       s21 -= carry[21] << 21
+
+       s11 += s23 * 666643
+       s12 += s23 * 470296
+       s13 += s23 * 654183
+       s14 -= s23 * 997805
+       s15 += s23 * 136657
+       s16 -= s23 * 683901
+       s23 = 0
+
+       s10 += s22 * 666643
+       s11 += s22 * 470296
+       s12 += s22 * 654183
+       s13 -= s22 * 997805
+       s14 += s22 * 136657
+       s15 -= s22 * 683901
+       s22 = 0
+
+       s9 += s21 * 666643
+       s10 += s21 * 470296
+       s11 += s21 * 654183
+       s12 -= s21 * 997805
+       s13 += s21 * 136657
+       s14 -= s21 * 683901
+       s21 = 0
+
+       s8 += s20 * 666643
+       s9 += s20 * 470296
+       s10 += s20 * 654183
+       s11 -= s20 * 997805
+       s12 += s20 * 136657
+       s13 -= s20 * 683901
+       s20 = 0
+
+       s7 += s19 * 666643
+       s8 += s19 * 470296
+       s9 += s19 * 654183
+       s10 -= s19 * 997805
+       s11 += s19 * 136657
+       s12 -= s19 * 683901
+       s19 = 0
+
+       s6 += s18 * 666643
+       s7 += s18 * 470296
+       s8 += s18 * 654183
+       s9 -= s18 * 997805
+       s10 += s18 * 136657
+       s11 -= s18 * 683901
+       s18 = 0
+
+       carry[6] = (s6 + (1 << 20)) >> 21
+       s7 += carry[6]
+       s6 -= carry[6] << 21
+       carry[8] = (s8 + (1 << 20)) >> 21
+       s9 += carry[8]
+       s8 -= carry[8] << 21
+       carry[10] = (s10 + (1 << 20)) >> 21
+       s11 += carry[10]
+       s10 -= carry[10] << 21
+       carry[12] = (s12 + (1 << 20)) >> 21
+       s13 += carry[12]
+       s12 -= carry[12] << 21
+       carry[14] = (s14 + (1 << 20)) >> 21
+       s15 += carry[14]
+       s14 -= carry[14] << 21
+       carry[16] = (s16 + (1 << 20)) >> 21
+       s17 += carry[16]
+       s16 -= carry[16] << 21
+
+       carry[7] = (s7 + (1 << 20)) >> 21
+       s8 += carry[7]
+       s7 -= carry[7] << 21
+       carry[9] = (s9 + (1 << 20)) >> 21
+       s10 += carry[9]
+       s9 -= carry[9] << 21
+       carry[11] = (s11 + (1 << 20)) >> 21
+       s12 += carry[11]
+       s11 -= carry[11] << 21
+       carry[13] = (s13 + (1 << 20)) >> 21
+       s14 += carry[13]
+       s13 -= carry[13] << 21
+       carry[15] = (s15 + (1 << 20)) >> 21
+       s16 += carry[15]
+       s15 -= carry[15] << 21
+
+       s5 += s17 * 666643
+       s6 += s17 * 470296
+       s7 += s17 * 654183
+       s8 -= s17 * 997805
+       s9 += s17 * 136657
+       s10 -= s17 * 683901
+       s17 = 0
+
+       s4 += s16 * 666643
+       s5 += s16 * 470296
+       s6 += s16 * 654183
+       s7 -= s16 * 997805
+       s8 += s16 * 136657
+       s9 -= s16 * 683901
+       s16 = 0
+
+       s3 += s15 * 666643
+       s4 += s15 * 470296
+       s5 += s15 * 654183
+       s6 -= s15 * 997805
+       s7 += s15 * 136657
+       s8 -= s15 * 683901
+       s15 = 0
+
+       s2 += s14 * 666643
+       s3 += s14 * 470296
+       s4 += s14 * 654183
+       s5 -= s14 * 997805
+       s6 += s14 * 136657
+       s7 -= s14 * 683901
+       s14 = 0
+
+       s1 += s13 * 666643
+       s2 += s13 * 470296
+       s3 += s13 * 654183
+       s4 -= s13 * 997805
+       s5 += s13 * 136657
+       s6 -= s13 * 683901
+       s13 = 0
+
+       s0 += s12 * 666643
+       s1 += s12 * 470296
+       s2 += s12 * 654183
+       s3 -= s12 * 997805
+       s4 += s12 * 136657
+       s5 -= s12 * 683901
+       s12 = 0
+
+       carry[0] = (s0 + (1 << 20)) >> 21
+       s1 += carry[0]
+       s0 -= carry[0] << 21
+       carry[2] = (s2 + (1 << 20)) >> 21
+       s3 += carry[2]
+       s2 -= carry[2] << 21
+       carry[4] = (s4 + (1 << 20)) >> 21
+       s5 += carry[4]
+       s4 -= carry[4] << 21
+       carry[6] = (s6 + (1 << 20)) >> 21
+       s7 += carry[6]
+       s6 -= carry[6] << 21
+       carry[8] = (s8 + (1 << 20)) >> 21
+       s9 += carry[8]
+       s8 -= carry[8] << 21
+       carry[10] = (s10 + (1 << 20)) >> 21
+       s11 += carry[10]
+       s10 -= carry[10] << 21
+
+       carry[1] = (s1 + (1 << 20)) >> 21
+       s2 += carry[1]
+       s1 -= carry[1] << 21
+       carry[3] = (s3 + (1 << 20)) >> 21
+       s4 += carry[3]
+       s3 -= carry[3] << 21
+       carry[5] = (s5 + (1 << 20)) >> 21
+       s6 += carry[5]
+       s5 -= carry[5] << 21
+       carry[7] = (s7 + (1 << 20)) >> 21
+       s8 += carry[7]
+       s7 -= carry[7] << 21
+       carry[9] = (s9 + (1 << 20)) >> 21
+       s10 += carry[9]
+       s9 -= carry[9] << 21
+       carry[11] = (s11 + (1 << 20)) >> 21
+       s12 += carry[11]
+       s11 -= carry[11] << 21
+
+       s0 += s12 * 666643
+       s1 += s12 * 470296
+       s2 += s12 * 654183
+       s3 -= s12 * 997805
+       s4 += s12 * 136657
+       s5 -= s12 * 683901
+       s12 = 0
+
+       carry[0] = s0 >> 21
+       s1 += carry[0]
+       s0 -= carry[0] << 21
+       carry[1] = s1 >> 21
+       s2 += carry[1]
+       s1 -= carry[1] << 21
+       carry[2] = s2 >> 21
+       s3 += carry[2]
+       s2 -= carry[2] << 21
+       carry[3] = s3 >> 21
+       s4 += carry[3]
+       s3 -= carry[3] << 21
+       carry[4] = s4 >> 21
+       s5 += carry[4]
+       s4 -= carry[4] << 21
+       carry[5] = s5 >> 21
+       s6 += carry[5]
+       s5 -= carry[5] << 21
+       carry[6] = s6 >> 21
+       s7 += carry[6]
+       s6 -= carry[6] << 21
+       carry[7] = s7 >> 21
+       s8 += carry[7]
+       s7 -= carry[7] << 21
+       carry[8] = s8 >> 21
+       s9 += carry[8]
+       s8 -= carry[8] << 21
+       carry[9] = s9 >> 21
+       s10 += carry[9]
+       s9 -= carry[9] << 21
+       carry[10] = s10 >> 21
+       s11 += carry[10]
+       s10 -= carry[10] << 21
+       carry[11] = s11 >> 21
+       s12 += carry[11]
+       s11 -= carry[11] << 21
+
+       s0 += s12 * 666643
+       s1 += s12 * 470296
+       s2 += s12 * 654183
+       s3 -= s12 * 997805
+       s4 += s12 * 136657
+       s5 -= s12 * 683901
+       s12 = 0
+
+       carry[0] = s0 >> 21
+       s1 += carry[0]
+       s0 -= carry[0] << 21
+       carry[1] = s1 >> 21
+       s2 += carry[1]
+       s1 -= carry[1] << 21
+       carry[2] = s2 >> 21
+       s3 += carry[2]
+       s2 -= carry[2] << 21
+       carry[3] = s3 >> 21
+       s4 += carry[3]
+       s3 -= carry[3] << 21
+       carry[4] = s4 >> 21
+       s5 += carry[4]
+       s4 -= carry[4] << 21
+       carry[5] = s5 >> 21
+       s6 += carry[5]
+       s5 -= carry[5] << 21
+       carry[6] = s6 >> 21
+       s7 += carry[6]
+       s6 -= carry[6] << 21
+       carry[7] = s7 >> 21
+       s8 += carry[7]
+       s7 -= carry[7] << 21
+       carry[8] = s8 >> 21
+       s9 += carry[8]
+       s8 -= carry[8] << 21
+       carry[9] = s9 >> 21
+       s10 += carry[9]
+       s9 -= carry[9] << 21
+       carry[10] = s10 >> 21
+       s11 += carry[10]
+       s10 -= carry[10] << 21
+
+       s[0] = byte(s0 >> 0)
+       s[1] = byte(s0 >> 8)
+       s[2] = byte((s0 >> 16) | (s1 << 5))
+       s[3] = byte(s1 >> 3)
+       s[4] = byte(s1 >> 11)
+       s[5] = byte((s1 >> 19) | (s2 << 2))
+       s[6] = byte(s2 >> 6)
+       s[7] = byte((s2 >> 14) | (s3 << 7))
+       s[8] = byte(s3 >> 1)
+       s[9] = byte(s3 >> 9)
+       s[10] = byte((s3 >> 17) | (s4 << 4))
+       s[11] = byte(s4 >> 4)
+       s[12] = byte(s4 >> 12)
+       s[13] = byte((s4 >> 20) | (s5 << 1))
+       s[14] = byte(s5 >> 7)
+       s[15] = byte((s5 >> 15) | (s6 << 6))
+       s[16] = byte(s6 >> 2)
+       s[17] = byte(s6 >> 10)
+       s[18] = byte((s6 >> 18) | (s7 << 3))
+       s[19] = byte(s7 >> 5)
+       s[20] = byte(s7 >> 13)
+       s[21] = byte(s8 >> 0)
+       s[22] = byte(s8 >> 8)
+       s[23] = byte((s8 >> 16) | (s9 << 5))
+       s[24] = byte(s9 >> 3)
+       s[25] = byte(s9 >> 11)
+       s[26] = byte((s9 >> 19) | (s10 << 2))
+       s[27] = byte(s10 >> 6)
+       s[28] = byte((s10 >> 14) | (s11 << 7))
+       s[29] = byte(s11 >> 1)
+       s[30] = byte(s11 >> 9)
+       s[31] = byte(s11 >> 17)
+}
+
+// Input:
+//   s[0]+256*s[1]+...+256^63*s[63] = s
+//
+// Output:
+//   s[0]+256*s[1]+...+256^31*s[31] = s mod l
+//   where l = 2^252 + 27742317777372353535851937790883648493.
+func scReduce(out *[32]byte, s *[64]byte) {
+       s0 := 2097151 & load3(s[:])
+       s1 := 2097151 & (load4(s[2:]) >> 5)
+       s2 := 2097151 & (load3(s[5:]) >> 2)
+       s3 := 2097151 & (load4(s[7:]) >> 7)
+       s4 := 2097151 & (load4(s[10:]) >> 4)
+       s5 := 2097151 & (load3(s[13:]) >> 1)
+       s6 := 2097151 & (load4(s[15:]) >> 6)
+       s7 := 2097151 & (load3(s[18:]) >> 3)
+       s8 := 2097151 & load3(s[21:])
+       s9 := 2097151 & (load4(s[23:]) >> 5)
+       s10 := 2097151 & (load3(s[26:]) >> 2)
+       s11 := 2097151 & (load4(s[28:]) >> 7)
+       s12 := 2097151 & (load4(s[31:]) >> 4)
+       s13 := 2097151 & (load3(s[34:]) >> 1)
+       s14 := 2097151 & (load4(s[36:]) >> 6)
+       s15 := 2097151 & (load3(s[39:]) >> 3)
+       s16 := 2097151 & load3(s[42:])
+       s17 := 2097151 & (load4(s[44:]) >> 5)
+       s18 := 2097151 & (load3(s[47:]) >> 2)
+       s19 := 2097151 & (load4(s[49:]) >> 7)
+       s20 := 2097151 & (load4(s[52:]) >> 4)
+       s21 := 2097151 & (load3(s[55:]) >> 1)
+       s22 := 2097151 & (load4(s[57:]) >> 6)
+       s23 := (load4(s[60:]) >> 3)
+
+       s11 += s23 * 666643
+       s12 += s23 * 470296
+       s13 += s23 * 654183
+       s14 -= s23 * 997805
+       s15 += s23 * 136657
+       s16 -= s23 * 683901
+       s23 = 0
+
+       s10 += s22 * 666643
+       s11 += s22 * 470296
+       s12 += s22 * 654183
+       s13 -= s22 * 997805
+       s14 += s22 * 136657
+       s15 -= s22 * 683901
+       s22 = 0
+
+       s9 += s21 * 666643
+       s10 += s21 * 470296
+       s11 += s21 * 654183
+       s12 -= s21 * 997805
+       s13 += s21 * 136657
+       s14 -= s21 * 683901
+       s21 = 0
+
+       s8 += s20 * 666643
+       s9 += s20 * 470296
+       s10 += s20 * 654183
+       s11 -= s20 * 997805
+       s12 += s20 * 136657
+       s13 -= s20 * 683901
+       s20 = 0
+
+       s7 += s19 * 666643
+       s8 += s19 * 470296
+       s9 += s19 * 654183
+       s10 -= s19 * 997805
+       s11 += s19 * 136657
+       s12 -= s19 * 683901
+       s19 = 0
+
+       s6 += s18 * 666643
+       s7 += s18 * 470296
+       s8 += s18 * 654183
+       s9 -= s18 * 997805
+       s10 += s18 * 136657
+       s11 -= s18 * 683901
+       s18 = 0
+
+       var carry [17]int64
+
+       carry[6] = (s6 + (1 << 20)) >> 21
+       s7 += carry[6]
+       s6 -= carry[6] << 21
+       carry[8] = (s8 + (1 << 20)) >> 21
+       s9 += carry[8]
+       s8 -= carry[8] << 21
+       carry[10] = (s10 + (1 << 20)) >> 21
+       s11 += carry[10]
+       s10 -= carry[10] << 21
+       carry[12] = (s12 + (1 << 20)) >> 21
+       s13 += carry[12]
+       s12 -= carry[12] << 21
+       carry[14] = (s14 + (1 << 20)) >> 21
+       s15 += carry[14]
+       s14 -= carry[14] << 21
+       carry[16] = (s16 + (1 << 20)) >> 21
+       s17 += carry[16]
+       s16 -= carry[16] << 21
+
+       carry[7] = (s7 + (1 << 20)) >> 21
+       s8 += carry[7]
+       s7 -= carry[7] << 21
+       carry[9] = (s9 + (1 << 20)) >> 21
+       s10 += carry[9]
+       s9 -= carry[9] << 21
+       carry[11] = (s11 + (1 << 20)) >> 21
+       s12 += carry[11]
+       s11 -= carry[11] << 21
+       carry[13] = (s13 + (1 << 20)) >> 21
+       s14 += carry[13]
+       s13 -= carry[13] << 21
+       carry[15] = (s15 + (1 << 20)) >> 21
+       s16 += carry[15]
+       s15 -= carry[15] << 21
+
+       s5 += s17 * 666643
+       s6 += s17 * 470296
+       s7 += s17 * 654183
+       s8 -= s17 * 997805
+       s9 += s17 * 136657
+       s10 -= s17 * 683901
+       s17 = 0
+
+       s4 += s16 * 666643
+       s5 += s16 * 470296
+       s6 += s16 * 654183
+       s7 -= s16 * 997805
+       s8 += s16 * 136657
+       s9 -= s16 * 683901
+       s16 = 0
+
+       s3 += s15 * 666643
+       s4 += s15 * 470296
+       s5 += s15 * 654183
+       s6 -= s15 * 997805
+       s7 += s15 * 136657
+       s8 -= s15 * 683901
+       s15 = 0
+
+       s2 += s14 * 666643
+       s3 += s14 * 470296
+       s4 += s14 * 654183
+       s5 -= s14 * 997805
+       s6 += s14 * 136657
+       s7 -= s14 * 683901
+       s14 = 0
+
+       s1 += s13 * 666643
+       s2 += s13 * 470296
+       s3 += s13 * 654183
+       s4 -= s13 * 997805
+       s5 += s13 * 136657
+       s6 -= s13 * 683901
+       s13 = 0
+
+       s0 += s12 * 666643
+       s1 += s12 * 470296
+       s2 += s12 * 654183
+       s3 -= s12 * 997805
+       s4 += s12 * 136657
+       s5 -= s12 * 683901
+       s12 = 0
+
+       carry[0] = (s0 + (1 << 20)) >> 21
+       s1 += carry[0]
+       s0 -= carry[0] << 21
+       carry[2] = (s2 + (1 << 20)) >> 21
+       s3 += carry[2]
+       s2 -= carry[2] << 21
+       carry[4] = (s4 + (1 << 20)) >> 21
+       s5 += carry[4]
+       s4 -= carry[4] << 21
+       carry[6] = (s6 + (1 << 20)) >> 21
+       s7 += carry[6]
+       s6 -= carry[6] << 21
+       carry[8] = (s8 + (1 << 20)) >> 21
+       s9 += carry[8]
+       s8 -= carry[8] << 21
+       carry[10] = (s10 + (1 << 20)) >> 21
+       s11 += carry[10]
+       s10 -= carry[10] << 21
+
+       carry[1] = (s1 + (1 << 20)) >> 21
+       s2 += carry[1]
+       s1 -= carry[1] << 21
+       carry[3] = (s3 + (1 << 20)) >> 21
+       s4 += carry[3]
+       s3 -= carry[3] << 21
+       carry[5] = (s5 + (1 << 20)) >> 21
+       s6 += carry[5]
+       s5 -= carry[5] << 21
+       carry[7] = (s7 + (1 << 20)) >> 21
+       s8 += carry[7]
+       s7 -= carry[7] << 21
+       carry[9] = (s9 + (1 << 20)) >> 21
+       s10 += carry[9]
+       s9 -= carry[9] << 21
+       carry[11] = (s11 + (1 << 20)) >> 21
+       s12 += carry[11]
+       s11 -= carry[11] << 21
+
+       s0 += s12 * 666643
+       s1 += s12 * 470296
+       s2 += s12 * 654183
+       s3 -= s12 * 997805
+       s4 += s12 * 136657
+       s5 -= s12 * 683901
+       s12 = 0
+
+       carry[0] = s0 >> 21
+       s1 += carry[0]
+       s0 -= carry[0] << 21
+       carry[1] = s1 >> 21
+       s2 += carry[1]
+       s1 -= carry[1] << 21
+       carry[2] = s2 >> 21
+       s3 += carry[2]
+       s2 -= carry[2] << 21
+       carry[3] = s3 >> 21
+       s4 += carry[3]
+       s3 -= carry[3] << 21
+       carry[4] = s4 >> 21
+       s5 += carry[4]
+       s4 -= carry[4] << 21
+       carry[5] = s5 >> 21
+       s6 += carry[5]
+       s5 -= carry[5] << 21
+       carry[6] = s6 >> 21
+       s7 += carry[6]
+       s6 -= carry[6] << 21
+       carry[7] = s7 >> 21
+       s8 += carry[7]
+       s7 -= carry[7] << 21
+       carry[8] = s8 >> 21
+       s9 += carry[8]
+       s8 -= carry[8] << 21
+       carry[9] = s9 >> 21
+       s10 += carry[9]
+       s9 -= carry[9] << 21
+       carry[10] = s10 >> 21
+       s11 += carry[10]
+       s10 -= carry[10] << 21
+       carry[11] = s11 >> 21
+       s12 += carry[11]
+       s11 -= carry[11] << 21
+
+       s0 += s12 * 666643
+       s1 += s12 * 470296
+       s2 += s12 * 654183
+       s3 -= s12 * 997805
+       s4 += s12 * 136657
+       s5 -= s12 * 683901
+       s12 = 0
+
+       carry[0] = s0 >> 21
+       s1 += carry[0]
+       s0 -= carry[0] << 21
+       carry[1] = s1 >> 21
+       s2 += carry[1]
+       s1 -= carry[1] << 21
+       carry[2] = s2 >> 21
+       s3 += carry[2]
+       s2 -= carry[2] << 21
+       carry[3] = s3 >> 21
+       s4 += carry[3]
+       s3 -= carry[3] << 21
+       carry[4] = s4 >> 21
+       s5 += carry[4]
+       s4 -= carry[4] << 21
+       carry[5] = s5 >> 21
+       s6 += carry[5]
+       s5 -= carry[5] << 21
+       carry[6] = s6 >> 21
+       s7 += carry[6]
+       s6 -= carry[6] << 21
+       carry[7] = s7 >> 21
+       s8 += carry[7]
+       s7 -= carry[7] << 21
+       carry[8] = s8 >> 21
+       s9 += carry[8]
+       s8 -= carry[8] << 21
+       carry[9] = s9 >> 21
+       s10 += carry[9]
+       s9 -= carry[9] << 21
+       carry[10] = s10 >> 21
+       s11 += carry[10]
+       s10 -= carry[10] << 21
+
+       out[0] = byte(s0 >> 0)
+       out[1] = byte(s0 >> 8)
+       out[2] = byte((s0 >> 16) | (s1 << 5))
+       out[3] = byte(s1 >> 3)
+       out[4] = byte(s1 >> 11)
+       out[5] = byte((s1 >> 19) | (s2 << 2))
+       out[6] = byte(s2 >> 6)
+       out[7] = byte((s2 >> 14) | (s3 << 7))
+       out[8] = byte(s3 >> 1)
+       out[9] = byte(s3 >> 9)
+       out[10] = byte((s3 >> 17) | (s4 << 4))
+       out[11] = byte(s4 >> 4)
+       out[12] = byte(s4 >> 12)
+       out[13] = byte((s4 >> 20) | (s5 << 1))
+       out[14] = byte(s5 >> 7)
+       out[15] = byte((s5 >> 15) | (s6 << 6))
+       out[16] = byte(s6 >> 2)
+       out[17] = byte(s6 >> 10)
+       out[18] = byte((s6 >> 18) | (s7 << 3))
+       out[19] = byte(s7 >> 5)
+       out[20] = byte(s7 >> 13)
+       out[21] = byte(s8 >> 0)
+       out[22] = byte(s8 >> 8)
+       out[23] = byte((s8 >> 16) | (s9 << 5))
+       out[24] = byte(s9 >> 3)
+       out[25] = byte(s9 >> 11)
+       out[26] = byte((s9 >> 19) | (s10 << 2))
+       out[27] = byte(s10 >> 6)
+       out[28] = byte((s10 >> 14) | (s11 << 7))
+       out[29] = byte(s11 >> 1)
+       out[30] = byte(s11 >> 9)
+       out[31] = byte(s11 >> 17)
+}
+
+// nonAdjacentForm computes a width-w non-adjacent form for this scalar.
+//
+// w must be between 2 and 8, or nonAdjacentForm will panic.
+func (s *Scalar) nonAdjacentForm(w uint) [256]int8 {
+       // This implementation is adapted from the one
+       // in curve25519-dalek and is documented there:
+       // https://github.com/dalek-cryptography/curve25519-dalek/blob/f630041af28e9a405255f98a8a93adca18e4315b/src/scalar.rs#L800-L871
+       if s.s[31] > 127 {
+               panic("scalar has high bit set illegally")
+       }
+       if w < 2 {
+               panic("w must be at least 2 by the definition of NAF")
+       } else if w > 8 {
+               panic("NAF digits must fit in int8")
+       }
+
+       var naf [256]int8
+       var digits [5]uint64
+
+       for i := 0; i < 4; i++ {
+               digits[i] = binary.LittleEndian.Uint64(s.s[i*8:])
+       }
+
+       width := uint64(1 << w)
+       windowMask := uint64(width - 1)
+
+       pos := uint(0)
+       carry := uint64(0)
+       for pos < 256 {
+               indexU64 := pos / 64
+               indexBit := pos % 64
+               var bitBuf uint64
+               if indexBit < 64-w {
+                       // This window's bits are contained in a single u64
+                       bitBuf = digits[indexU64] >> indexBit
+               } else {
+                       // Combine the current 64 bits with bits from the next 64
+                       bitBuf = (digits[indexU64] >> indexBit) | (digits[1+indexU64] << (64 - indexBit))
+               }
+
+               // Add carry into the current window
+               window := carry + (bitBuf & windowMask)
+
+               if window&1 == 0 {
+                       // If the window value is even, preserve the carry and continue.
+                       // Why is the carry preserved?
+                       // If carry == 0 and window & 1 == 0,
+                       //    then the next carry should be 0
+                       // If carry == 1 and window & 1 == 0,
+                       //    then bit_buf & 1 == 1 so the next carry should be 1
+                       pos += 1
+                       continue
+               }
+
+               if window < width/2 {
+                       carry = 0
+                       naf[pos] = int8(window)
+               } else {
+                       carry = 1
+                       naf[pos] = int8(window) - int8(width)
+               }
+
+               pos += w
+       }
+       return naf
+}
+
+func (s *Scalar) signedRadix16() [64]int8 {
+       if s.s[31] > 127 {
+               panic("scalar has high bit set illegally")
+       }
+
+       var digits [64]int8
+
+       // Compute unsigned radix-16 digits:
+       for i := 0; i < 32; i++ {
+               digits[2*i] = int8(s.s[i] & 15)
+               digits[2*i+1] = int8((s.s[i] >> 4) & 15)
+       }
+
+       // Recenter coefficients:
+       for i := 0; i < 63; i++ {
+               carry := (digits[i] + 8) >> 4
+               digits[i] -= carry << 4
+               digits[i+1] += carry
+       }
+
+       return digits
+}
diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/scalar_alias_test.go b/libgo/go/crypto/ed25519/internal/edwards25519/scalar_alias_test.go
new file mode 100644 (file)
index 0000000..18d800d
--- /dev/null
@@ -0,0 +1,93 @@
+// Copyright (c) 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package edwards25519
+
+import (
+       "testing"
+       "testing/quick"
+)
+
+func TestScalarAliasing(t *testing.T) {
+       checkAliasingOneArg := func(f func(v, x *Scalar) *Scalar, v, x Scalar) bool {
+               x1, v1 := x, x
+
+               // Calculate a reference f(x) without aliasing.
+               if out := f(&v, &x); out != &v || !isReduced(out) {
+                       return false
+               }
+
+               // Test aliasing the argument and the receiver.
+               if out := f(&v1, &v1); out != &v1 || v1 != v || !isReduced(out) {
+                       return false
+               }
+
+               // Ensure the arguments was not modified.
+               return x == x1
+       }
+
+       checkAliasingTwoArgs := func(f func(v, x, y *Scalar) *Scalar, v, x, y Scalar) bool {
+               x1, y1, v1 := x, y, Scalar{}
+
+               // Calculate a reference f(x, y) without aliasing.
+               if out := f(&v, &x, &y); out != &v || !isReduced(out) {
+                       return false
+               }
+
+               // Test aliasing the first argument and the receiver.
+               v1 = x
+               if out := f(&v1, &v1, &y); out != &v1 || v1 != v || !isReduced(out) {
+                       return false
+               }
+               // Test aliasing the second argument and the receiver.
+               v1 = y
+               if out := f(&v1, &x, &v1); out != &v1 || v1 != v || !isReduced(out) {
+                       return false
+               }
+
+               // Calculate a reference f(x, x) without aliasing.
+               if out := f(&v, &x, &x); out != &v || !isReduced(out) {
+                       return false
+               }
+
+               // Test aliasing the first argument and the receiver.
+               v1 = x
+               if out := f(&v1, &v1, &x); out != &v1 || v1 != v || !isReduced(out) {
+                       return false
+               }
+               // Test aliasing the second argument and the receiver.
+               v1 = x
+               if out := f(&v1, &x, &v1); out != &v1 || v1 != v || !isReduced(out) {
+                       return false
+               }
+               // Test aliasing both arguments and the receiver.
+               v1 = x
+               if out := f(&v1, &v1, &v1); out != &v1 || v1 != v || !isReduced(out) {
+                       return false
+               }
+
+               // Ensure the arguments were not modified.
+               return x == x1 && y == y1
+       }
+
+       for name, f := range map[string]interface{}{
+               "Negate": func(v, x Scalar) bool {
+                       return checkAliasingOneArg((*Scalar).Negate, v, x)
+               },
+               "Multiply": func(v, x, y Scalar) bool {
+                       return checkAliasingTwoArgs((*Scalar).Multiply, v, x, y)
+               },
+               "Add": func(v, x, y Scalar) bool {
+                       return checkAliasingTwoArgs((*Scalar).Add, v, x, y)
+               },
+               "Subtract": func(v, x, y Scalar) bool {
+                       return checkAliasingTwoArgs((*Scalar).Subtract, v, x, y)
+               },
+       } {
+               err := quick.Check(f, &quick.Config{MaxCountScale: 1 << 5})
+               if err != nil {
+                       t.Errorf("%v: %v", name, err)
+               }
+       }
+}
diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/scalar_test.go b/libgo/go/crypto/ed25519/internal/edwards25519/scalar_test.go
new file mode 100644 (file)
index 0000000..704caff
--- /dev/null
@@ -0,0 +1,233 @@
+// Copyright (c) 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package edwards25519
+
+import (
+       "bytes"
+       "encoding/hex"
+       "math/big"
+       mathrand "math/rand"
+       "reflect"
+       "testing"
+       "testing/quick"
+)
+
+// Generate returns a valid (reduced modulo l) Scalar with a distribution
+// weighted towards high, low, and edge values.
+func (Scalar) Generate(rand *mathrand.Rand, size int) reflect.Value {
+       s := scZero
+       diceRoll := rand.Intn(100)
+       switch {
+       case diceRoll == 0:
+       case diceRoll == 1:
+               s = scOne
+       case diceRoll == 2:
+               s = scMinusOne
+       case diceRoll < 5:
+               // Generate a low scalar in [0, 2^125).
+               rand.Read(s.s[:16])
+               s.s[15] &= (1 << 5) - 1
+       case diceRoll < 10:
+               // Generate a high scalar in [2^252, 2^252 + 2^124).
+               s.s[31] = 1 << 4
+               rand.Read(s.s[:16])
+               s.s[15] &= (1 << 4) - 1
+       default:
+               // Generate a valid scalar in [0, l) by returning [0, 2^252) which has a
+               // negligibly different distribution (the former has a 2^-127.6 chance
+               // of being out of the latter range).
+               rand.Read(s.s[:])
+               s.s[31] &= (1 << 4) - 1
+       }
+       return reflect.ValueOf(s)
+}
+
+// quickCheckConfig1024 will make each quickcheck test run (1024 * -quickchecks)
+// times. The default value of -quickchecks is 100.
+var quickCheckConfig1024 = &quick.Config{MaxCountScale: 1 << 10}
+
+func TestScalarGenerate(t *testing.T) {
+       f := func(sc Scalar) bool {
+               return isReduced(&sc)
+       }
+       if err := quick.Check(f, quickCheckConfig1024); err != nil {
+               t.Errorf("generated unreduced scalar: %v", err)
+       }
+}
+
+func TestScalarSetCanonicalBytes(t *testing.T) {
+       f1 := func(in [32]byte, sc Scalar) bool {
+               // Mask out top 4 bits to guarantee value falls in [0, l).
+               in[len(in)-1] &= (1 << 4) - 1
+               if _, err := sc.SetCanonicalBytes(in[:]); err != nil {
+                       return false
+               }
+               return bytes.Equal(in[:], sc.Bytes()) && isReduced(&sc)
+       }
+       if err := quick.Check(f1, quickCheckConfig1024); err != nil {
+               t.Errorf("failed bytes->scalar->bytes round-trip: %v", err)
+       }
+
+       f2 := func(sc1, sc2 Scalar) bool {
+               if _, err := sc2.SetCanonicalBytes(sc1.Bytes()); err != nil {
+                       return false
+               }
+               return sc1 == sc2
+       }
+       if err := quick.Check(f2, quickCheckConfig1024); err != nil {
+               t.Errorf("failed scalar->bytes->scalar round-trip: %v", err)
+       }
+
+       b := scMinusOne.s
+       b[31] += 1
+       s := scOne
+       if out, err := s.SetCanonicalBytes(b[:]); err == nil {
+               t.Errorf("SetCanonicalBytes worked on a non-canonical value")
+       } else if s != scOne {
+               t.Errorf("SetCanonicalBytes modified its receiver")
+       } else if out != nil {
+               t.Errorf("SetCanonicalBytes did not return nil with an error")
+       }
+}
+
+func TestScalarSetUniformBytes(t *testing.T) {
+       mod, _ := new(big.Int).SetString("27742317777372353535851937790883648493", 10)
+       mod.Add(mod, new(big.Int).Lsh(big.NewInt(1), 252))
+       f := func(in [64]byte, sc Scalar) bool {
+               sc.SetUniformBytes(in[:])
+               if !isReduced(&sc) {
+                       return false
+               }
+               scBig := bigIntFromLittleEndianBytes(sc.s[:])
+               inBig := bigIntFromLittleEndianBytes(in[:])
+               return inBig.Mod(inBig, mod).Cmp(scBig) == 0
+       }
+       if err := quick.Check(f, quickCheckConfig1024); err != nil {
+               t.Error(err)
+       }
+}
+
+func TestScalarSetBytesWithClamping(t *testing.T) {
+       // Generated with libsodium.js 1.0.18 crypto_scalarmult_ed25519_base.
+
+       random := "633d368491364dc9cd4c1bf891b1d59460face1644813240a313e61f2c88216e"
+       s := new(Scalar).SetBytesWithClamping(decodeHex(random))
+       p := new(Point).ScalarBaseMult(s)
+       want := "1d87a9026fd0126a5736fe1628c95dd419172b5b618457e041c9c861b2494a94"
+       if got := hex.EncodeToString(p.Bytes()); got != want {
+               t.Errorf("random: got %q, want %q", got, want)
+       }
+
+       zero := "0000000000000000000000000000000000000000000000000000000000000000"
+       s = new(Scalar).SetBytesWithClamping(decodeHex(zero))
+       p = new(Point).ScalarBaseMult(s)
+       want = "693e47972caf527c7883ad1b39822f026f47db2ab0e1919955b8993aa04411d1"
+       if got := hex.EncodeToString(p.Bytes()); got != want {
+               t.Errorf("zero: got %q, want %q", got, want)
+       }
+
+       one := "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+       s = new(Scalar).SetBytesWithClamping(decodeHex(one))
+       p = new(Point).ScalarBaseMult(s)
+       want = "12e9a68b73fd5aacdbcaf3e88c46fea6ebedb1aa84eed1842f07f8edab65e3a7"
+       if got := hex.EncodeToString(p.Bytes()); got != want {
+               t.Errorf("one: got %q, want %q", got, want)
+       }
+}
+
+func bigIntFromLittleEndianBytes(b []byte) *big.Int {
+       bb := make([]byte, len(b))
+       for i := range b {
+               bb[i] = b[len(b)-i-1]
+       }
+       return new(big.Int).SetBytes(bb)
+}
+
+func TestScalarMultiplyDistributesOverAdd(t *testing.T) {
+       multiplyDistributesOverAdd := func(x, y, z Scalar) bool {
+               // Compute t1 = (x+y)*z
+               var t1 Scalar
+               t1.Add(&x, &y)
+               t1.Multiply(&t1, &z)
+
+               // Compute t2 = x*z + y*z
+               var t2 Scalar
+               var t3 Scalar
+               t2.Multiply(&x, &z)
+               t3.Multiply(&y, &z)
+               t2.Add(&t2, &t3)
+
+               return t1 == t2 && isReduced(&t1) && isReduced(&t3)
+       }
+
+       if err := quick.Check(multiplyDistributesOverAdd, quickCheckConfig1024); err != nil {
+               t.Error(err)
+       }
+}
+
+func TestScalarAddLikeSubNeg(t *testing.T) {
+       addLikeSubNeg := func(x, y Scalar) bool {
+               // Compute t1 = x - y
+               var t1 Scalar
+               t1.Subtract(&x, &y)
+
+               // Compute t2 = -y + x
+               var t2 Scalar
+               t2.Negate(&y)
+               t2.Add(&t2, &x)
+
+               return t1 == t2 && isReduced(&t1)
+       }
+
+       if err := quick.Check(addLikeSubNeg, quickCheckConfig1024); err != nil {
+               t.Error(err)
+       }
+}
+
+func TestScalarNonAdjacentForm(t *testing.T) {
+       s := Scalar{[32]byte{
+               0x1a, 0x0e, 0x97, 0x8a, 0x90, 0xf6, 0x62, 0x2d,
+               0x37, 0x47, 0x02, 0x3f, 0x8a, 0xd8, 0x26, 0x4d,
+               0xa7, 0x58, 0xaa, 0x1b, 0x88, 0xe0, 0x40, 0xd1,
+               0x58, 0x9e, 0x7b, 0x7f, 0x23, 0x76, 0xef, 0x09,
+       }}
+       expectedNaf := [256]int8{
+               0, 13, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, -9, 0, 0, 0, 0, -11, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1,
+               0, 0, 0, 0, 9, 0, 0, 0, 0, -5, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 11, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0,
+               -9, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 9, 0,
+               0, 0, 0, -15, 0, 0, 0, 0, -7, 0, 0, 0, 0, -9, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, -3, 0,
+               0, 0, 0, -11, 0, 0, 0, 0, -7, 0, 0, 0, 0, -13, 0, 0, 0, 0, 11, 0, 0, 0, 0, -9, 0, 0, 0, 0, 0, 1, 0, 0,
+               0, 0, 0, -15, 0, 0, 0, 0, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 13, 0, 0, 0,
+               0, 0, 0, 11, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, -9, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 7,
+               0, 0, 0, 0, 0, -15, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 15, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+       }
+
+       sNaf := s.nonAdjacentForm(5)
+
+       for i := 0; i < 256; i++ {
+               if expectedNaf[i] != sNaf[i] {
+                       t.Errorf("Wrong digit at position %d, got %d, expected %d", i, sNaf[i], expectedNaf[i])
+               }
+       }
+}
+
+type notZeroScalar Scalar
+
+func (notZeroScalar) Generate(rand *mathrand.Rand, size int) reflect.Value {
+       var s Scalar
+       for s == scZero {
+               s = Scalar{}.Generate(rand, size).Interface().(Scalar)
+       }
+       return reflect.ValueOf(notZeroScalar(s))
+}
+
+func TestScalarEqual(t *testing.T) {
+       if scOne.Equal(&scMinusOne) == 1 {
+               t.Errorf("scOne.Equal(&scMinusOne) is true")
+       }
+       if scMinusOne.Equal(&scMinusOne) == 0 {
+               t.Errorf("scMinusOne.Equal(&scMinusOne) is false")
+       }
+}
diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/scalarmult.go b/libgo/go/crypto/ed25519/internal/edwards25519/scalarmult.go
new file mode 100644 (file)
index 0000000..f7ca3ce
--- /dev/null
@@ -0,0 +1,214 @@
+// Copyright (c) 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package edwards25519
+
+import "sync"
+
+// basepointTable is a set of 32 affineLookupTables, where table i is generated
+// from 256i * basepoint. It is precomputed the first time it's used.
+func basepointTable() *[32]affineLookupTable {
+       basepointTablePrecomp.initOnce.Do(func() {
+               p := NewGeneratorPoint()
+               for i := 0; i < 32; i++ {
+                       basepointTablePrecomp.table[i].FromP3(p)
+                       for j := 0; j < 8; j++ {
+                               p.Add(p, p)
+                       }
+               }
+       })
+       return &basepointTablePrecomp.table
+}
+
+var basepointTablePrecomp struct {
+       table    [32]affineLookupTable
+       initOnce sync.Once
+}
+
+// ScalarBaseMult sets v = x * B, where B is the canonical generator, and
+// returns v.
+//
+// The scalar multiplication is done in constant time.
+func (v *Point) ScalarBaseMult(x *Scalar) *Point {
+       basepointTable := basepointTable()
+
+       // Write x = sum(x_i * 16^i) so  x*B = sum( B*x_i*16^i )
+       // as described in the Ed25519 paper
+       //
+       // Group even and odd coefficients
+       // x*B     = x_0*16^0*B + x_2*16^2*B + ... + x_62*16^62*B
+       //         + x_1*16^1*B + x_3*16^3*B + ... + x_63*16^63*B
+       // x*B     = x_0*16^0*B + x_2*16^2*B + ... + x_62*16^62*B
+       //    + 16*( x_1*16^0*B + x_3*16^2*B + ... + x_63*16^62*B)
+       //
+       // We use a lookup table for each i to get x_i*16^(2*i)*B
+       // and do four doublings to multiply by 16.
+       digits := x.signedRadix16()
+
+       multiple := &affineCached{}
+       tmp1 := &projP1xP1{}
+       tmp2 := &projP2{}
+
+       // Accumulate the odd components first
+       v.Set(NewIdentityPoint())
+       for i := 1; i < 64; i += 2 {
+               basepointTable[i/2].SelectInto(multiple, digits[i])
+               tmp1.AddAffine(v, multiple)
+               v.fromP1xP1(tmp1)
+       }
+
+       // Multiply by 16
+       tmp2.FromP3(v)       // tmp2 =    v in P2 coords
+       tmp1.Double(tmp2)    // tmp1 =  2*v in P1xP1 coords
+       tmp2.FromP1xP1(tmp1) // tmp2 =  2*v in P2 coords
+       tmp1.Double(tmp2)    // tmp1 =  4*v in P1xP1 coords
+       tmp2.FromP1xP1(tmp1) // tmp2 =  4*v in P2 coords
+       tmp1.Double(tmp2)    // tmp1 =  8*v in P1xP1 coords
+       tmp2.FromP1xP1(tmp1) // tmp2 =  8*v in P2 coords
+       tmp1.Double(tmp2)    // tmp1 = 16*v in P1xP1 coords
+       v.fromP1xP1(tmp1)    // now v = 16*(odd components)
+
+       // Accumulate the even components
+       for i := 0; i < 64; i += 2 {
+               basepointTable[i/2].SelectInto(multiple, digits[i])
+               tmp1.AddAffine(v, multiple)
+               v.fromP1xP1(tmp1)
+       }
+
+       return v
+}
+
+// ScalarMult sets v = x * q, and returns v.
+//
+// The scalar multiplication is done in constant time.
+func (v *Point) ScalarMult(x *Scalar, q *Point) *Point {
+       checkInitialized(q)
+
+       var table projLookupTable
+       table.FromP3(q)
+
+       // Write x = sum(x_i * 16^i)
+       // so  x*Q = sum( Q*x_i*16^i )
+       //         = Q*x_0 + 16*(Q*x_1 + 16*( ... + Q*x_63) ... )
+       //           <------compute inside out---------
+       //
+       // We use the lookup table to get the x_i*Q values
+       // and do four doublings to compute 16*Q
+       digits := x.signedRadix16()
+
+       // Unwrap first loop iteration to save computing 16*identity
+       multiple := &projCached{}
+       tmp1 := &projP1xP1{}
+       tmp2 := &projP2{}
+       table.SelectInto(multiple, digits[63])
+
+       v.Set(NewIdentityPoint())
+       tmp1.Add(v, multiple) // tmp1 = x_63*Q in P1xP1 coords
+       for i := 62; i >= 0; i-- {
+               tmp2.FromP1xP1(tmp1) // tmp2 =    (prev) in P2 coords
+               tmp1.Double(tmp2)    // tmp1 =  2*(prev) in P1xP1 coords
+               tmp2.FromP1xP1(tmp1) // tmp2 =  2*(prev) in P2 coords
+               tmp1.Double(tmp2)    // tmp1 =  4*(prev) in P1xP1 coords
+               tmp2.FromP1xP1(tmp1) // tmp2 =  4*(prev) in P2 coords
+               tmp1.Double(tmp2)    // tmp1 =  8*(prev) in P1xP1 coords
+               tmp2.FromP1xP1(tmp1) // tmp2 =  8*(prev) in P2 coords
+               tmp1.Double(tmp2)    // tmp1 = 16*(prev) in P1xP1 coords
+               v.fromP1xP1(tmp1)    //    v = 16*(prev) in P3 coords
+               table.SelectInto(multiple, digits[i])
+               tmp1.Add(v, multiple) // tmp1 = x_i*Q + 16*(prev) in P1xP1 coords
+       }
+       v.fromP1xP1(tmp1)
+       return v
+}
+
+// basepointNafTable is the nafLookupTable8 for the basepoint.
+// It is precomputed the first time it's used.
+func basepointNafTable() *nafLookupTable8 {
+       basepointNafTablePrecomp.initOnce.Do(func() {
+               basepointNafTablePrecomp.table.FromP3(NewGeneratorPoint())
+       })
+       return &basepointNafTablePrecomp.table
+}
+
+var basepointNafTablePrecomp struct {
+       table    nafLookupTable8
+       initOnce sync.Once
+}
+
+// VarTimeDoubleScalarBaseMult sets v = a * A + b * B, where B is the canonical
+// generator, and returns v.
+//
+// Execution time depends on the inputs.
+func (v *Point) VarTimeDoubleScalarBaseMult(a *Scalar, A *Point, b *Scalar) *Point {
+       checkInitialized(A)
+
+       // Similarly to the single variable-base approach, we compute
+       // digits and use them with a lookup table.  However, because
+       // we are allowed to do variable-time operations, we don't
+       // need constant-time lookups or constant-time digit
+       // computations.
+       //
+       // So we use a non-adjacent form of some width w instead of
+       // radix 16.  This is like a binary representation (one digit
+       // for each binary place) but we allow the digits to grow in
+       // magnitude up to 2^{w-1} so that the nonzero digits are as
+       // sparse as possible.  Intuitively, this "condenses" the
+       // "mass" of the scalar onto sparse coefficients (meaning
+       // fewer additions).
+
+       basepointNafTable := basepointNafTable()
+       var aTable nafLookupTable5
+       aTable.FromP3(A)
+       // Because the basepoint is fixed, we can use a wider NAF
+       // corresponding to a bigger table.
+       aNaf := a.nonAdjacentForm(5)
+       bNaf := b.nonAdjacentForm(8)
+
+       // Find the first nonzero coefficient.
+       i := 255
+       for j := i; j >= 0; j-- {
+               if aNaf[j] != 0 || bNaf[j] != 0 {
+                       break
+               }
+       }
+
+       multA := &projCached{}
+       multB := &affineCached{}
+       tmp1 := &projP1xP1{}
+       tmp2 := &projP2{}
+       tmp2.Zero()
+
+       // Move from high to low bits, doubling the accumulator
+       // at each iteration and checking whether there is a nonzero
+       // coefficient to look up a multiple of.
+       for ; i >= 0; i-- {
+               tmp1.Double(tmp2)
+
+               // Only update v if we have a nonzero coeff to add in.
+               if aNaf[i] > 0 {
+                       v.fromP1xP1(tmp1)
+                       aTable.SelectInto(multA, aNaf[i])
+                       tmp1.Add(v, multA)
+               } else if aNaf[i] < 0 {
+                       v.fromP1xP1(tmp1)
+                       aTable.SelectInto(multA, -aNaf[i])
+                       tmp1.Sub(v, multA)
+               }
+
+               if bNaf[i] > 0 {
+                       v.fromP1xP1(tmp1)
+                       basepointNafTable.SelectInto(multB, bNaf[i])
+                       tmp1.AddAffine(v, multB)
+               } else if bNaf[i] < 0 {
+                       v.fromP1xP1(tmp1)
+                       basepointNafTable.SelectInto(multB, -bNaf[i])
+                       tmp1.SubAffine(v, multB)
+               }
+
+               tmp2.FromP1xP1(tmp1)
+       }
+
+       v.fromP2(tmp2)
+       return v
+}
diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/scalarmult_test.go b/libgo/go/crypto/ed25519/internal/edwards25519/scalarmult_test.go
new file mode 100644 (file)
index 0000000..c2027f5
--- /dev/null
@@ -0,0 +1,209 @@
+// Copyright (c) 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package edwards25519
+
+import (
+       "testing"
+       "testing/quick"
+)
+
+var (
+       // quickCheckConfig32 will make each quickcheck test run (32 * -quickchecks)
+       // times. The default value of -quickchecks is 100.
+       quickCheckConfig32 = &quick.Config{MaxCountScale: 1 << 5}
+
+       // a random scalar generated using dalek.
+       dalekScalar = Scalar{[32]byte{219, 106, 114, 9, 174, 249, 155, 89, 69, 203, 201, 93, 92, 116, 234, 187, 78, 115, 103, 172, 182, 98, 62, 103, 187, 136, 13, 100, 248, 110, 12, 4}}
+       // the above, times the edwards25519 basepoint.
+       dalekScalarBasepoint, _ = new(Point).SetBytes([]byte{0xf4, 0xef, 0x7c, 0xa, 0x34, 0x55, 0x7b, 0x9f, 0x72, 0x3b, 0xb6, 0x1e, 0xf9, 0x46, 0x9, 0x91, 0x1c, 0xb9, 0xc0, 0x6c, 0x17, 0x28, 0x2d, 0x8b, 0x43, 0x2b, 0x5, 0x18, 0x6a, 0x54, 0x3e, 0x48})
+)
+
+func TestScalarMultSmallScalars(t *testing.T) {
+       var z Scalar
+       var p Point
+       p.ScalarMult(&z, B)
+       if I.Equal(&p) != 1 {
+               t.Error("0*B != 0")
+       }
+       checkOnCurve(t, &p)
+
+       z = Scalar{[32]byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}
+       p.ScalarMult(&z, B)
+       if B.Equal(&p) != 1 {
+               t.Error("1*B != 1")
+       }
+       checkOnCurve(t, &p)
+}
+
+func TestScalarMultVsDalek(t *testing.T) {
+       var p Point
+       p.ScalarMult(&dalekScalar, B)
+       if dalekScalarBasepoint.Equal(&p) != 1 {
+               t.Error("Scalar mul does not match dalek")
+       }
+       checkOnCurve(t, &p)
+}
+
+func TestBaseMultVsDalek(t *testing.T) {
+       var p Point
+       p.ScalarBaseMult(&dalekScalar)
+       if dalekScalarBasepoint.Equal(&p) != 1 {
+               t.Error("Scalar mul does not match dalek")
+       }
+       checkOnCurve(t, &p)
+}
+
+func TestVarTimeDoubleBaseMultVsDalek(t *testing.T) {
+       var p Point
+       var z Scalar
+       p.VarTimeDoubleScalarBaseMult(&dalekScalar, B, &z)
+       if dalekScalarBasepoint.Equal(&p) != 1 {
+               t.Error("VarTimeDoubleScalarBaseMult fails with b=0")
+       }
+       checkOnCurve(t, &p)
+       p.VarTimeDoubleScalarBaseMult(&z, B, &dalekScalar)
+       if dalekScalarBasepoint.Equal(&p) != 1 {
+               t.Error("VarTimeDoubleScalarBaseMult fails with a=0")
+       }
+       checkOnCurve(t, &p)
+}
+
+func TestScalarMultDistributesOverAdd(t *testing.T) {
+       scalarMultDistributesOverAdd := func(x, y Scalar) bool {
+               var z Scalar
+               z.Add(&x, &y)
+               var p, q, r, check Point
+               p.ScalarMult(&x, B)
+               q.ScalarMult(&y, B)
+               r.ScalarMult(&z, B)
+               check.Add(&p, &q)
+               checkOnCurve(t, &p, &q, &r, &check)
+               return check.Equal(&r) == 1
+       }
+
+       if err := quick.Check(scalarMultDistributesOverAdd, quickCheckConfig32); err != nil {
+               t.Error(err)
+       }
+}
+
+func TestScalarMultNonIdentityPoint(t *testing.T) {
+       // Check whether p.ScalarMult and q.ScalaBaseMult give the same,
+       // when p and q are originally set to the base point.
+
+       scalarMultNonIdentityPoint := func(x Scalar) bool {
+               var p, q Point
+               p.Set(B)
+               q.Set(B)
+
+               p.ScalarMult(&x, B)
+               q.ScalarBaseMult(&x)
+
+               checkOnCurve(t, &p, &q)
+
+               return p.Equal(&q) == 1
+       }
+
+       if err := quick.Check(scalarMultNonIdentityPoint, quickCheckConfig32); err != nil {
+               t.Error(err)
+       }
+}
+
+func TestBasepointTableGeneration(t *testing.T) {
+       // The basepoint table is 32 affineLookupTables,
+       // corresponding to (16^2i)*B for table i.
+       basepointTable := basepointTable()
+
+       tmp1 := &projP1xP1{}
+       tmp2 := &projP2{}
+       tmp3 := &Point{}
+       tmp3.Set(B)
+       table := make([]affineLookupTable, 32)
+       for i := 0; i < 32; i++ {
+               // Build the table
+               table[i].FromP3(tmp3)
+               // Assert equality with the hardcoded one
+               if table[i] != basepointTable[i] {
+                       t.Errorf("Basepoint table %d does not match", i)
+               }
+
+               // Set p = (16^2)*p = 256*p = 2^8*p
+               tmp2.FromP3(tmp3)
+               for j := 0; j < 7; j++ {
+                       tmp1.Double(tmp2)
+                       tmp2.FromP1xP1(tmp1)
+               }
+               tmp1.Double(tmp2)
+               tmp3.fromP1xP1(tmp1)
+               checkOnCurve(t, tmp3)
+       }
+}
+
+func TestScalarMultMatchesBaseMult(t *testing.T) {
+       scalarMultMatchesBaseMult := func(x Scalar) bool {
+               var p, q Point
+               p.ScalarMult(&x, B)
+               q.ScalarBaseMult(&x)
+               checkOnCurve(t, &p, &q)
+               return p.Equal(&q) == 1
+       }
+
+       if err := quick.Check(scalarMultMatchesBaseMult, quickCheckConfig32); err != nil {
+               t.Error(err)
+       }
+}
+
+func TestBasepointNafTableGeneration(t *testing.T) {
+       var table nafLookupTable8
+       table.FromP3(B)
+
+       if table != *basepointNafTable() {
+               t.Error("BasepointNafTable does not match")
+       }
+}
+
+func TestVarTimeDoubleBaseMultMatchesBaseMult(t *testing.T) {
+       varTimeDoubleBaseMultMatchesBaseMult := func(x, y Scalar) bool {
+               var p, q1, q2, check Point
+
+               p.VarTimeDoubleScalarBaseMult(&x, B, &y)
+
+               q1.ScalarBaseMult(&x)
+               q2.ScalarBaseMult(&y)
+               check.Add(&q1, &q2)
+
+               checkOnCurve(t, &p, &check, &q1, &q2)
+               return p.Equal(&check) == 1
+       }
+
+       if err := quick.Check(varTimeDoubleBaseMultMatchesBaseMult, quickCheckConfig32); err != nil {
+               t.Error(err)
+       }
+}
+
+// Benchmarks.
+
+func BenchmarkScalarBaseMult(t *testing.B) {
+       var p Point
+
+       for i := 0; i < t.N; i++ {
+               p.ScalarBaseMult(&dalekScalar)
+       }
+}
+
+func BenchmarkScalarMult(t *testing.B) {
+       var p Point
+
+       for i := 0; i < t.N; i++ {
+               p.ScalarMult(&dalekScalar, B)
+       }
+}
+
+func BenchmarkVarTimeDoubleScalarBaseMult(t *testing.B) {
+       var p Point
+
+       for i := 0; i < t.N; i++ {
+               p.VarTimeDoubleScalarBaseMult(&dalekScalar, B, &dalekScalar)
+       }
+}
diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/tables.go b/libgo/go/crypto/ed25519/internal/edwards25519/tables.go
new file mode 100644 (file)
index 0000000..beec956
--- /dev/null
@@ -0,0 +1,129 @@
+// Copyright (c) 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package edwards25519
+
+import (
+       "crypto/subtle"
+)
+
+// A dynamic lookup table for variable-base, constant-time scalar muls.
+type projLookupTable struct {
+       points [8]projCached
+}
+
+// A precomputed lookup table for fixed-base, constant-time scalar muls.
+type affineLookupTable struct {
+       points [8]affineCached
+}
+
+// A dynamic lookup table for variable-base, variable-time scalar muls.
+type nafLookupTable5 struct {
+       points [8]projCached
+}
+
+// A precomputed lookup table for fixed-base, variable-time scalar muls.
+type nafLookupTable8 struct {
+       points [64]affineCached
+}
+
+// Constructors.
+
+// Builds a lookup table at runtime. Fast.
+func (v *projLookupTable) FromP3(q *Point) {
+       // Goal: v.points[i] = (i+1)*Q, i.e., Q, 2Q, ..., 8Q
+       // This allows lookup of -8Q, ..., -Q, 0, Q, ..., 8Q
+       v.points[0].FromP3(q)
+       tmpP3 := Point{}
+       tmpP1xP1 := projP1xP1{}
+       for i := 0; i < 7; i++ {
+               // Compute (i+1)*Q as Q + i*Q and convert to a ProjCached
+               // This is needlessly complicated because the API has explicit
+               // recievers instead of creating stack objects and relying on RVO
+               v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.Add(q, &v.points[i])))
+       }
+}
+
+// This is not optimised for speed; fixed-base tables should be precomputed.
+func (v *affineLookupTable) FromP3(q *Point) {
+       // Goal: v.points[i] = (i+1)*Q, i.e., Q, 2Q, ..., 8Q
+       // This allows lookup of -8Q, ..., -Q, 0, Q, ..., 8Q
+       v.points[0].FromP3(q)
+       tmpP3 := Point{}
+       tmpP1xP1 := projP1xP1{}
+       for i := 0; i < 7; i++ {
+               // Compute (i+1)*Q as Q + i*Q and convert to AffineCached
+               v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.AddAffine(q, &v.points[i])))
+       }
+}
+
+// Builds a lookup table at runtime. Fast.
+func (v *nafLookupTable5) FromP3(q *Point) {
+       // Goal: v.points[i] = (2*i+1)*Q, i.e., Q, 3Q, 5Q, ..., 15Q
+       // This allows lookup of -15Q, ..., -3Q, -Q, 0, Q, 3Q, ..., 15Q
+       v.points[0].FromP3(q)
+       q2 := Point{}
+       q2.Add(q, q)
+       tmpP3 := Point{}
+       tmpP1xP1 := projP1xP1{}
+       for i := 0; i < 7; i++ {
+               v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.Add(&q2, &v.points[i])))
+       }
+}
+
+// This is not optimised for speed; fixed-base tables should be precomputed.
+func (v *nafLookupTable8) FromP3(q *Point) {
+       v.points[0].FromP3(q)
+       q2 := Point{}
+       q2.Add(q, q)
+       tmpP3 := Point{}
+       tmpP1xP1 := projP1xP1{}
+       for i := 0; i < 63; i++ {
+               v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.AddAffine(&q2, &v.points[i])))
+       }
+}
+
+// Selectors.
+
+// Set dest to x*Q, where -8 <= x <= 8, in constant time.
+func (v *projLookupTable) SelectInto(dest *projCached, x int8) {
+       // Compute xabs = |x|
+       xmask := x >> 7
+       xabs := uint8((x + xmask) ^ xmask)
+
+       dest.Zero()
+       for j := 1; j <= 8; j++ {
+               // Set dest = j*Q if |x| = j
+               cond := subtle.ConstantTimeByteEq(xabs, uint8(j))
+               dest.Select(&v.points[j-1], dest, cond)
+       }
+       // Now dest = |x|*Q, conditionally negate to get x*Q
+       dest.CondNeg(int(xmask & 1))
+}
+
+// Set dest to x*Q, where -8 <= x <= 8, in constant time.
+func (v *affineLookupTable) SelectInto(dest *affineCached, x int8) {
+       // Compute xabs = |x|
+       xmask := x >> 7
+       xabs := uint8((x + xmask) ^ xmask)
+
+       dest.Zero()
+       for j := 1; j <= 8; j++ {
+               // Set dest = j*Q if |x| = j
+               cond := subtle.ConstantTimeByteEq(xabs, uint8(j))
+               dest.Select(&v.points[j-1], dest, cond)
+       }
+       // Now dest = |x|*Q, conditionally negate to get x*Q
+       dest.CondNeg(int(xmask & 1))
+}
+
+// Given odd x with 0 < x < 2^4, return x*Q (in variable time).
+func (v *nafLookupTable5) SelectInto(dest *projCached, x int8) {
+       *dest = v.points[x/2]
+}
+
+// Given odd x with 0 < x < 2^7, return x*Q (in variable time).
+func (v *nafLookupTable8) SelectInto(dest *affineCached, x int8) {
+       *dest = v.points[x/2]
+}
diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/tables_test.go b/libgo/go/crypto/ed25519/internal/edwards25519/tables_test.go
new file mode 100644 (file)
index 0000000..b5d161a
--- /dev/null
@@ -0,0 +1,119 @@
+// Copyright (c) 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package edwards25519
+
+import (
+       "testing"
+)
+
+func TestProjLookupTable(t *testing.T) {
+       var table projLookupTable
+       table.FromP3(B)
+
+       var tmp1, tmp2, tmp3 projCached
+       table.SelectInto(&tmp1, 6)
+       table.SelectInto(&tmp2, -2)
+       table.SelectInto(&tmp3, -4)
+       // Expect T1 + T2 + T3 = identity
+
+       var accP1xP1 projP1xP1
+       accP3 := NewIdentityPoint()
+
+       accP1xP1.Add(accP3, &tmp1)
+       accP3.fromP1xP1(&accP1xP1)
+       accP1xP1.Add(accP3, &tmp2)
+       accP3.fromP1xP1(&accP1xP1)
+       accP1xP1.Add(accP3, &tmp3)
+       accP3.fromP1xP1(&accP1xP1)
+
+       if accP3.Equal(I) != 1 {
+               t.Errorf("Consistency check on ProjLookupTable.SelectInto failed!  %x %x %x", tmp1, tmp2, tmp3)
+       }
+}
+
+func TestAffineLookupTable(t *testing.T) {
+       var table affineLookupTable
+       table.FromP3(B)
+
+       var tmp1, tmp2, tmp3 affineCached
+       table.SelectInto(&tmp1, 3)
+       table.SelectInto(&tmp2, -7)
+       table.SelectInto(&tmp3, 4)
+       // Expect T1 + T2 + T3 = identity
+
+       var accP1xP1 projP1xP1
+       accP3 := NewIdentityPoint()
+
+       accP1xP1.AddAffine(accP3, &tmp1)
+       accP3.fromP1xP1(&accP1xP1)
+       accP1xP1.AddAffine(accP3, &tmp2)
+       accP3.fromP1xP1(&accP1xP1)
+       accP1xP1.AddAffine(accP3, &tmp3)
+       accP3.fromP1xP1(&accP1xP1)
+
+       if accP3.Equal(I) != 1 {
+               t.Errorf("Consistency check on ProjLookupTable.SelectInto failed!  %x %x %x", tmp1, tmp2, tmp3)
+       }
+}
+
+func TestNafLookupTable5(t *testing.T) {
+       var table nafLookupTable5
+       table.FromP3(B)
+
+       var tmp1, tmp2, tmp3, tmp4 projCached
+       table.SelectInto(&tmp1, 9)
+       table.SelectInto(&tmp2, 11)
+       table.SelectInto(&tmp3, 7)
+       table.SelectInto(&tmp4, 13)
+       // Expect T1 + T2 = T3 + T4
+
+       var accP1xP1 projP1xP1
+       lhs := NewIdentityPoint()
+       rhs := NewIdentityPoint()
+
+       accP1xP1.Add(lhs, &tmp1)
+       lhs.fromP1xP1(&accP1xP1)
+       accP1xP1.Add(lhs, &tmp2)
+       lhs.fromP1xP1(&accP1xP1)
+
+       accP1xP1.Add(rhs, &tmp3)
+       rhs.fromP1xP1(&accP1xP1)
+       accP1xP1.Add(rhs, &tmp4)
+       rhs.fromP1xP1(&accP1xP1)
+
+       if lhs.Equal(rhs) != 1 {
+               t.Errorf("Consistency check on nafLookupTable5 failed")
+       }
+}
+
+func TestNafLookupTable8(t *testing.T) {
+       var table nafLookupTable8
+       table.FromP3(B)
+
+       var tmp1, tmp2, tmp3, tmp4 affineCached
+       table.SelectInto(&tmp1, 49)
+       table.SelectInto(&tmp2, 11)
+       table.SelectInto(&tmp3, 35)
+       table.SelectInto(&tmp4, 25)
+       // Expect T1 + T2 = T3 + T4
+
+       var accP1xP1 projP1xP1
+       lhs := NewIdentityPoint()
+       rhs := NewIdentityPoint()
+
+       accP1xP1.AddAffine(lhs, &tmp1)
+       lhs.fromP1xP1(&accP1xP1)
+       accP1xP1.AddAffine(lhs, &tmp2)
+       lhs.fromP1xP1(&accP1xP1)
+
+       accP1xP1.AddAffine(rhs, &tmp3)
+       rhs.fromP1xP1(&accP1xP1)
+       accP1xP1.AddAffine(rhs, &tmp4)
+       rhs.fromP1xP1(&accP1xP1)
+
+       if lhs.Equal(rhs) != 1 {
+               t.Errorf("Consistency check on nafLookupTable8 failed")
+       }
+}
index f93dc16419f8f95fc215ab969aa323c0c02f4409..f072960bfeddf83ce69d6a6ec1c701b99a2a6d9b 100644 (file)
@@ -40,6 +40,15 @@ type Curve interface {
        ScalarBaseMult(k []byte) (x, y *big.Int)
 }
 
+func matchesSpecificCurve(params *CurveParams, available ...Curve) (Curve, bool) {
+       for _, c := range available {
+               if params == c.Params() {
+                       return c, true
+               }
+       }
+       return nil, false
+}
+
 // CurveParams contains the parameters of an elliptic curve and also provides
 // a generic, non-constant time implementation of Curve.
 type CurveParams struct {
@@ -71,6 +80,12 @@ func (curve *CurveParams) polynomial(x *big.Int) *big.Int {
 }
 
 func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool {
+       // If there is a dedicated constant-time implementation for this curve operation,
+       // use that instead of the generic one.
+       if specific, ok := matchesSpecificCurve(curve, p224, p521); ok {
+               return specific.IsOnCurve(x, y)
+       }
+
        // y² = x³ - 3x + b
        y2 := new(big.Int).Mul(y, y)
        y2.Mod(y2, curve.P)
@@ -108,6 +123,12 @@ func (curve *CurveParams) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.
 }
 
 func (curve *CurveParams) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
+       // If there is a dedicated constant-time implementation for this curve operation,
+       // use that instead of the generic one.
+       if specific, ok := matchesSpecificCurve(curve, p224, p521); ok {
+               return specific.Add(x1, y1, x2, y2)
+       }
+
        z1 := zForAffine(x1, y1)
        z2 := zForAffine(x2, y2)
        return curve.affineFromJacobian(curve.addJacobian(x1, y1, z1, x2, y2, z2))
@@ -192,6 +213,12 @@ func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int
 }
 
 func (curve *CurveParams) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
+       // If there is a dedicated constant-time implementation for this curve operation,
+       // use that instead of the generic one.
+       if specific, ok := matchesSpecificCurve(curve, p224, p521); ok {
+               return specific.Double(x1, y1)
+       }
+
        z1 := zForAffine(x1, y1)
        return curve.affineFromJacobian(curve.doubleJacobian(x1, y1, z1))
 }
@@ -258,6 +285,12 @@ func (curve *CurveParams) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int,
 }
 
 func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) {
+       // If there is a dedicated constant-time implementation for this curve operation,
+       // use that instead of the generic one.
+       if specific, ok := matchesSpecificCurve(curve, p224, p256, p521); ok {
+               return specific.ScalarMult(Bx, By, k)
+       }
+
        Bz := new(big.Int).SetInt64(1)
        x, y, z := new(big.Int), new(big.Int), new(big.Int)
 
@@ -275,6 +308,12 @@ func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.
 }
 
 func (curve *CurveParams) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
+       // If there is a dedicated constant-time implementation for this curve operation,
+       // use that instead of the generic one.
+       if specific, ok := matchesSpecificCurve(curve, p224, p256, p521); ok {
+               return specific.ScalarBaseMult(k)
+       }
+
        return curve.ScalarMult(curve.Gx, curve.Gy, k)
 }
 
@@ -390,7 +429,6 @@ func UnmarshalCompressed(curve Curve, data []byte) (x, y *big.Int) {
 
 var initonce sync.Once
 var p384 *CurveParams
-var p521 *CurveParams
 
 func initAll() {
        initP224()
@@ -410,17 +448,6 @@ func initP384() {
        p384.BitSize = 384
 }
 
-func initP521() {
-       // See FIPS 186-3, section D.2.5
-       p521 = &CurveParams{Name: "P-521"}
-       p521.P, _ = new(big.Int).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", 10)
-       p521.N, _ = new(big.Int).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449", 10)
-       p521.B, _ = new(big.Int).SetString("051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", 16)
-       p521.Gx, _ = new(big.Int).SetString("c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", 16)
-       p521.Gy, _ = new(big.Int).SetString("11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", 16)
-       p521.BitSize = 521
-}
-
 // P256 returns a Curve which implements NIST P-256 (FIPS 186-3, section D.2.3),
 // also known as secp256r1 or prime256v1. The CurveParams.Name of this Curve is
 // "P-256".
@@ -428,7 +455,7 @@ func initP521() {
 // Multiple invocations of this function will return the same value, so it can
 // be used for equality checks and switch statements.
 //
-// The cryptographic operations are implemented using constant-time algorithms.
+// ScalarMult and ScalarBaseMult are implemented using constant-time algorithms.
 func P256() Curve {
        initonce.Do(initAll)
        return p256
@@ -452,7 +479,7 @@ func P384() Curve {
 // Multiple invocations of this function will return the same value, so it can
 // be used for equality checks and switch statements.
 //
-// The cryptographic operations do not use constant-time algorithms.
+// The cryptographic operations are implemented using constant-time algorithms.
 func P521() Curve {
        initonce.Do(initAll)
        return p521
index e80e7731aaaed03b15dcb698722738a99c4cf8e2..183861a54b52fe2678f9165b171a38b471e9b40f 100644 (file)
@@ -8,414 +8,70 @@ import (
        "bytes"
        "crypto/rand"
        "encoding/hex"
-       "fmt"
        "math/big"
        "testing"
 )
 
-func TestOnCurve(t *testing.T) {
-       p224 := P224()
-       if !p224.IsOnCurve(p224.Params().Gx, p224.Params().Gy) {
-               t.Errorf("FAIL")
-       }
+// genericParamsForCurve returns the dereferenced CurveParams for
+// the specified curve. This is used to avoid the logic for
+// upgrading a curve to it's specific implementation, forcing
+// usage of the generic implementation. This is only relevant
+// for the P224, P256, and P521 curves.
+func genericParamsForCurve(c Curve) *CurveParams {
+       d := *(c.Params())
+       return &d
 }
 
-func TestOffCurve(t *testing.T) {
-       p224 := P224()
-       x, y := new(big.Int).SetInt64(1), new(big.Int).SetInt64(1)
-       if p224.IsOnCurve(x, y) {
-               t.Errorf("FAIL: point off curve is claimed to be on the curve")
+func testAllCurves(t *testing.T, f func(*testing.T, Curve)) {
+       tests := []struct {
+               name  string
+               curve Curve
+       }{
+               {"P256", P256()},
+               {"P256/Params", genericParamsForCurve(P256())},
+               {"P224", P224()},
+               {"P224/Params", genericParamsForCurve(P224())},
+               {"P384", P384()},
+               {"P384/Params", genericParamsForCurve(P384())},
+               {"P521", P521()},
+               {"P521/Params", genericParamsForCurve(P521())},
        }
-       b := Marshal(p224, x, y)
-       x1, y1 := Unmarshal(p224, b)
-       if x1 != nil || y1 != nil {
-               t.Errorf("FAIL: unmarshaling a point not on the curve succeeded")
+       if testing.Short() {
+               tests = tests[:1]
        }
-}
-
-type baseMultTest struct {
-       k    string
-       x, y string
-}
-
-var p224BaseMultTests = []baseMultTest{
-       {
-               "1",
-               "b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
-               "bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34",
-       },
-       {
-               "2",
-               "706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6",
-               "1c2b76a7bc25e7702a704fa986892849fca629487acf3709d2e4e8bb",
-       },
-       {
-               "3",
-               "df1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04",
-               "a3f7f03cadd0be444c0aa56830130ddf77d317344e1af3591981a925",
-       },
-       {
-               "4",
-               "ae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301",
-               "482580a0ec5bc47e88bc8c378632cd196cb3fa058a7114eb03054c9",
-       },
-       {
-               "5",
-               "31c49ae75bce7807cdff22055d94ee9021fedbb5ab51c57526f011aa",
-               "27e8bff1745635ec5ba0c9f1c2ede15414c6507d29ffe37e790a079b",
-       },
-       {
-               "6",
-               "1f2483f82572251fca975fea40db821df8ad82a3c002ee6c57112408",
-               "89faf0ccb750d99b553c574fad7ecfb0438586eb3952af5b4b153c7e",
-       },
-       {
-               "7",
-               "db2f6be630e246a5cf7d99b85194b123d487e2d466b94b24a03c3e28",
-               "f3a30085497f2f611ee2517b163ef8c53b715d18bb4e4808d02b963",
-       },
-       {
-               "8",
-               "858e6f9cc6c12c31f5df124aa77767b05c8bc021bd683d2b55571550",
-               "46dcd3ea5c43898c5c5fc4fdac7db39c2f02ebee4e3541d1e78047a",
-       },
-       {
-               "9",
-               "2fdcccfee720a77ef6cb3bfbb447f9383117e3daa4a07e36ed15f78d",
-               "371732e4f41bf4f7883035e6a79fcedc0e196eb07b48171697517463",
-       },
-       {
-               "10",
-               "aea9e17a306517eb89152aa7096d2c381ec813c51aa880e7bee2c0fd",
-               "39bb30eab337e0a521b6cba1abe4b2b3a3e524c14a3fe3eb116b655f",
-       },
-       {
-               "11",
-               "ef53b6294aca431f0f3c22dc82eb9050324f1d88d377e716448e507c",
-               "20b510004092e96636cfb7e32efded8265c266dfb754fa6d6491a6da",
-       },
-       {
-               "12",
-               "6e31ee1dc137f81b056752e4deab1443a481033e9b4c93a3044f4f7a",
-               "207dddf0385bfdeab6e9acda8da06b3bbef224a93ab1e9e036109d13",
-       },
-       {
-               "13",
-               "34e8e17a430e43289793c383fac9774247b40e9ebd3366981fcfaeca",
-               "252819f71c7fb7fbcb159be337d37d3336d7feb963724fdfb0ecb767",
-       },
-       {
-               "14",
-               "a53640c83dc208603ded83e4ecf758f24c357d7cf48088b2ce01e9fa",
-               "d5814cd724199c4a5b974a43685fbf5b8bac69459c9469bc8f23ccaf",
-       },
-       {
-               "15",
-               "baa4d8635511a7d288aebeedd12ce529ff102c91f97f867e21916bf9",
-               "979a5f4759f80f4fb4ec2e34f5566d595680a11735e7b61046127989",
-       },
-       {
-               "16",
-               "b6ec4fe1777382404ef679997ba8d1cc5cd8e85349259f590c4c66d",
-               "3399d464345906b11b00e363ef429221f2ec720d2f665d7dead5b482",
-       },
-       {
-               "17",
-               "b8357c3a6ceef288310e17b8bfeff9200846ca8c1942497c484403bc",
-               "ff149efa6606a6bd20ef7d1b06bd92f6904639dce5174db6cc554a26",
-       },
-       {
-               "18",
-               "c9ff61b040874c0568479216824a15eab1a838a797d189746226e4cc",
-               "ea98d60e5ffc9b8fcf999fab1df7e7ef7084f20ddb61bb045a6ce002",
-       },
-       {
-               "19",
-               "a1e81c04f30ce201c7c9ace785ed44cc33b455a022f2acdbc6cae83c",
-               "dcf1f6c3db09c70acc25391d492fe25b4a180babd6cea356c04719cd",
-       },
-       {
-               "20",
-               "fcc7f2b45df1cd5a3c0c0731ca47a8af75cfb0347e8354eefe782455",
-               "d5d7110274cba7cdee90e1a8b0d394c376a5573db6be0bf2747f530",
-       },
-       {
-               "112233445566778899",
-               "61f077c6f62ed802dad7c2f38f5c67f2cc453601e61bd076bb46179e",
-               "2272f9e9f5933e70388ee652513443b5e289dd135dcc0d0299b225e4",
-       },
-       {
-               "112233445566778899112233445566778899",
-               "29895f0af496bfc62b6ef8d8a65c88c613949b03668aab4f0429e35",
-               "3ea6e53f9a841f2019ec24bde1a75677aa9b5902e61081c01064de93",
-       },
-       {
-               "6950511619965839450988900688150712778015737983940691968051900319680",
-               "ab689930bcae4a4aa5f5cb085e823e8ae30fd365eb1da4aba9cf0379",
-               "3345a121bbd233548af0d210654eb40bab788a03666419be6fbd34e7",
-       },
-       {
-               "13479972933410060327035789020509431695094902435494295338570602119423",
-               "bdb6a8817c1f89da1c2f3dd8e97feb4494f2ed302a4ce2bc7f5f4025",
-               "4c7020d57c00411889462d77a5438bb4e97d177700bf7243a07f1680",
-       },
-       {
-               "13479971751745682581351455311314208093898607229429740618390390702079",
-               "d58b61aa41c32dd5eba462647dba75c5d67c83606c0af2bd928446a9",
-               "d24ba6a837be0460dd107ae77725696d211446c5609b4595976b16bd",
-       },
-       {
-               "13479972931865328106486971546324465392952975980343228160962702868479",
-               "dc9fa77978a005510980e929a1485f63716df695d7a0c18bb518df03",
-               "ede2b016f2ddffc2a8c015b134928275ce09e5661b7ab14ce0d1d403",
-       },
-       {
-               "11795773708834916026404142434151065506931607341523388140225443265536",
-               "499d8b2829cfb879c901f7d85d357045edab55028824d0f05ba279ba",
-               "bf929537b06e4015919639d94f57838fa33fc3d952598dcdbb44d638",
-       },
-       {
-               "784254593043826236572847595991346435467177662189391577090",
-               "8246c999137186632c5f9eddf3b1b0e1764c5e8bd0e0d8a554b9cb77",
-               "e80ed8660bc1cb17ac7d845be40a7a022d3306f116ae9f81fea65947",
-       },
-       {
-               "13479767645505654746623887797783387853576174193480695826442858012671",
-               "6670c20afcceaea672c97f75e2e9dd5c8460e54bb38538ebb4bd30eb",
-               "f280d8008d07a4caf54271f993527d46ff3ff46fd1190a3f1faa4f74",
-       },
-       {
-               "205688069665150753842126177372015544874550518966168735589597183",
-               "eca934247425cfd949b795cb5ce1eff401550386e28d1a4c5a8eb",
-               "d4c01040dba19628931bc8855370317c722cbd9ca6156985f1c2e9ce",
-       },
-       {
-               "13479966930919337728895168462090683249159702977113823384618282123295",
-               "ef353bf5c73cd551b96d596fbc9a67f16d61dd9fe56af19de1fba9cd",
-               "21771b9cdce3e8430c09b3838be70b48c21e15bc09ee1f2d7945b91f",
-       },
-       {
-               "50210731791415612487756441341851895584393717453129007497216",
-               "4036052a3091eb481046ad3289c95d3ac905ca0023de2c03ecd451cf",
-               "d768165a38a2b96f812586a9d59d4136035d9c853a5bf2e1c86a4993",
-       },
-       {
-               "26959946667150639794667015087019625940457807714424391721682722368041",
-               "fcc7f2b45df1cd5a3c0c0731ca47a8af75cfb0347e8354eefe782455",
-               "f2a28eefd8b345832116f1e574f2c6b2c895aa8c24941f40d8b80ad1",
-       },
-       {
-               "26959946667150639794667015087019625940457807714424391721682722368042",
-               "a1e81c04f30ce201c7c9ace785ed44cc33b455a022f2acdbc6cae83c",
-               "230e093c24f638f533dac6e2b6d01da3b5e7f45429315ca93fb8e634",
-       },
-       {
-               "26959946667150639794667015087019625940457807714424391721682722368043",
-               "c9ff61b040874c0568479216824a15eab1a838a797d189746226e4cc",
-               "156729f1a003647030666054e208180f8f7b0df2249e44fba5931fff",
-       },
-       {
-               "26959946667150639794667015087019625940457807714424391721682722368044",
-               "b8357c3a6ceef288310e17b8bfeff9200846ca8c1942497c484403bc",
-               "eb610599f95942df1082e4f9426d086fb9c6231ae8b24933aab5db",
-       },
-       {
-               "26959946667150639794667015087019625940457807714424391721682722368045",
-               "b6ec4fe1777382404ef679997ba8d1cc5cd8e85349259f590c4c66d",
-               "cc662b9bcba6f94ee4ff1c9c10bd6ddd0d138df2d099a282152a4b7f",
-       },
-       {
-               "26959946667150639794667015087019625940457807714424391721682722368046",
-               "baa4d8635511a7d288aebeedd12ce529ff102c91f97f867e21916bf9",
-               "6865a0b8a607f0b04b13d1cb0aa992a5a97f5ee8ca1849efb9ed8678",
-       },
-       {
-               "26959946667150639794667015087019625940457807714424391721682722368047",
-               "a53640c83dc208603ded83e4ecf758f24c357d7cf48088b2ce01e9fa",
-               "2a7eb328dbe663b5a468b5bc97a040a3745396ba636b964370dc3352",
-       },
-       {
-               "26959946667150639794667015087019625940457807714424391721682722368048",
-               "34e8e17a430e43289793c383fac9774247b40e9ebd3366981fcfaeca",
-               "dad7e608e380480434ea641cc82c82cbc92801469c8db0204f13489a",
-       },
-       {
-               "26959946667150639794667015087019625940457807714424391721682722368049",
-               "6e31ee1dc137f81b056752e4deab1443a481033e9b4c93a3044f4f7a",
-               "df82220fc7a4021549165325725f94c3410ddb56c54e161fc9ef62ee",
-       },
-       {
-               "26959946667150639794667015087019625940457807714424391721682722368050",
-               "ef53b6294aca431f0f3c22dc82eb9050324f1d88d377e716448e507c",
-               "df4aefffbf6d1699c930481cd102127c9a3d992048ab05929b6e5927",
-       },
-       {
-               "26959946667150639794667015087019625940457807714424391721682722368051",
-               "aea9e17a306517eb89152aa7096d2c381ec813c51aa880e7bee2c0fd",
-               "c644cf154cc81f5ade49345e541b4d4b5c1adb3eb5c01c14ee949aa2",
-       },
-       {
-               "26959946667150639794667015087019625940457807714424391721682722368052",
-               "2fdcccfee720a77ef6cb3bfbb447f9383117e3daa4a07e36ed15f78d",
-               "c8e8cd1b0be40b0877cfca1958603122f1e6914f84b7e8e968ae8b9e",
-       },
-       {
-               "26959946667150639794667015087019625940457807714424391721682722368053",
-               "858e6f9cc6c12c31f5df124aa77767b05c8bc021bd683d2b55571550",
-               "fb9232c15a3bc7673a3a03b0253824c53d0fd1411b1cabe2e187fb87",
-       },
-       {
-               "26959946667150639794667015087019625940457807714424391721682722368054",
-               "db2f6be630e246a5cf7d99b85194b123d487e2d466b94b24a03c3e28",
-               "f0c5cff7ab680d09ee11dae84e9c1072ac48ea2e744b1b7f72fd469e",
-       },
-       {
-               "26959946667150639794667015087019625940457807714424391721682722368055",
-               "1f2483f82572251fca975fea40db821df8ad82a3c002ee6c57112408",
-               "76050f3348af2664aac3a8b05281304ebc7a7914c6ad50a4b4eac383",
-       },
-       {
-               "26959946667150639794667015087019625940457807714424391721682722368056",
-               "31c49ae75bce7807cdff22055d94ee9021fedbb5ab51c57526f011aa",
-               "d817400e8ba9ca13a45f360e3d121eaaeb39af82d6001c8186f5f866",
-       },
-       {
-               "26959946667150639794667015087019625940457807714424391721682722368057",
-               "ae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301",
-               "fb7da7f5f13a43b81774373c879cd32d6934c05fa758eeb14fcfab38",
-       },
-       {
-               "26959946667150639794667015087019625940457807714424391721682722368058",
-               "df1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04",
-               "5c080fc3522f41bbb3f55a97cfecf21f882ce8cbb1e50ca6e67e56dc",
-       },
-       {
-               "26959946667150639794667015087019625940457807714424391721682722368059",
-               "706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6",
-               "e3d4895843da188fd58fb0567976d7b50359d6b78530c8f62d1b1746",
-       },
-       {
-               "26959946667150639794667015087019625940457807714424391721682722368060",
-               "b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
-               "42c89c774a08dc04b3dd201932bc8a5ea5f8b89bbb2a7e667aff81cd",
-       },
-}
-
-type scalarMultTest struct {
-       k          string
-       xIn, yIn   string
-       xOut, yOut string
-}
-
-var p256MultTests = []scalarMultTest{
-       {
-               "2a265f8bcbdcaf94d58519141e578124cb40d64a501fba9c11847b28965bc737",
-               "023819813ac969847059028ea88a1f30dfbcde03fc791d3a252c6b41211882ea",
-               "f93e4ae433cc12cf2a43fc0ef26400c0e125508224cdb649380f25479148a4ad",
-               "4d4de80f1534850d261075997e3049321a0864082d24a917863366c0724f5ae3",
-               "a22d2b7f7818a3563e0f7a76c9bf0921ac55e06e2e4d11795b233824b1db8cc0",
-       },
-       {
-               "313f72ff9fe811bf573176231b286a3bdb6f1b14e05c40146590727a71c3bccd",
-               "cc11887b2d66cbae8f4d306627192522932146b42f01d3c6f92bd5c8ba739b06",
-               "a2f08a029cd06b46183085bae9248b0ed15b70280c7ef13a457f5af382426031",
-               "831c3f6b5f762d2f461901577af41354ac5f228c2591f84f8a6e51e2e3f17991",
-               "93f90934cd0ef2c698cc471c60a93524e87ab31ca2412252337f364513e43684",
-       },
-}
-
-func TestBaseMult(t *testing.T) {
-       p224 := P224()
-       for i, e := range p224BaseMultTests {
-               k, ok := new(big.Int).SetString(e.k, 10)
-               if !ok {
-                       t.Errorf("%d: bad value for k: %s", i, e.k)
-               }
-               x, y := p224.ScalarBaseMult(k.Bytes())
-               if fmt.Sprintf("%x", x) != e.x || fmt.Sprintf("%x", y) != e.y {
-                       t.Errorf("%d: bad output for k=%s: got (%x, %x), want (%s, %s)", i, e.k, x, y, e.x, e.y)
-               }
-               if testing.Short() && i > 5 {
-                       break
-               }
+       for _, test := range tests {
+               curve := test.curve
+               t.Run(test.name, func(t *testing.T) {
+                       t.Parallel()
+                       f(t, curve)
+               })
        }
 }
 
-func TestGenericBaseMult(t *testing.T) {
-       // We use the P224 CurveParams directly in order to test the generic implementation.
-       p224 := P224().Params()
-       for i, e := range p224BaseMultTests {
-               k, ok := new(big.Int).SetString(e.k, 10)
-               if !ok {
-                       t.Errorf("%d: bad value for k: %s", i, e.k)
-               }
-               x, y := p224.ScalarBaseMult(k.Bytes())
-               if fmt.Sprintf("%x", x) != e.x || fmt.Sprintf("%x", y) != e.y {
-                       t.Errorf("%d: bad output for k=%s: got (%x, %x), want (%s, %s)", i, e.k, x, y, e.x, e.y)
-               }
-               if testing.Short() && i > 5 {
-                       break
+func TestOnCurve(t *testing.T) {
+       testAllCurves(t, func(t *testing.T, curve Curve) {
+               if !curve.IsOnCurve(curve.Params().Gx, curve.Params().Gy) {
+                       t.Error("basepoint is not on the curve")
                }
-       }
+       })
 }
 
-func TestP256BaseMult(t *testing.T) {
-       p256 := P256()
-       p256Generic := p256.Params()
-
-       scalars := make([]*big.Int, 0, len(p224BaseMultTests)+1)
-       for _, e := range p224BaseMultTests {
-               k, _ := new(big.Int).SetString(e.k, 10)
-               scalars = append(scalars, k)
-       }
-       k := new(big.Int).SetInt64(1)
-       k.Lsh(k, 500)
-       scalars = append(scalars, k)
-
-       for i, k := range scalars {
-               x, y := p256.ScalarBaseMult(k.Bytes())
-               x2, y2 := p256Generic.ScalarBaseMult(k.Bytes())
-               if x.Cmp(x2) != 0 || y.Cmp(y2) != 0 {
-                       t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, x, y, x2, y2)
+func TestOffCurve(t *testing.T) {
+       testAllCurves(t, func(t *testing.T, curve Curve) {
+               x, y := new(big.Int).SetInt64(1), new(big.Int).SetInt64(1)
+               if curve.IsOnCurve(x, y) {
+                       t.Errorf("point off curve is claimed to be on the curve")
                }
-
-               if testing.Short() && i > 5 {
-                       break
+               b := Marshal(curve, x, y)
+               x1, y1 := Unmarshal(curve, b)
+               if x1 != nil || y1 != nil {
+                       t.Errorf("unmarshaling a point not on the curve succeeded")
                }
-       }
+       })
 }
 
-func TestP256Mult(t *testing.T) {
-       p256 := P256()
-       p256Generic := p256.Params()
-
-       for i, e := range p224BaseMultTests {
-               x, _ := new(big.Int).SetString(e.x, 16)
-               y, _ := new(big.Int).SetString(e.y, 16)
-               k, _ := new(big.Int).SetString(e.k, 10)
-
-               xx, yy := p256.ScalarMult(x, y, k.Bytes())
-               xx2, yy2 := p256Generic.ScalarMult(x, y, k.Bytes())
-               if xx.Cmp(xx2) != 0 || yy.Cmp(yy2) != 0 {
-                       t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, xx, yy, xx2, yy2)
-               }
-               if testing.Short() && i > 5 {
-                       break
-               }
-       }
-
-       for i, e := range p256MultTests {
-               x, _ := new(big.Int).SetString(e.xIn, 16)
-               y, _ := new(big.Int).SetString(e.yIn, 16)
-               k, _ := new(big.Int).SetString(e.k, 16)
-               expectedX, _ := new(big.Int).SetString(e.xOut, 16)
-               expectedY, _ := new(big.Int).SetString(e.yOut, 16)
-
-               xx, yy := p256.ScalarMult(x, y, k.Bytes())
-               if xx.Cmp(expectedX) != 0 || yy.Cmp(expectedY) != 0 {
-                       t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, xx, yy, expectedX, expectedY)
-               }
-       }
+func TestInfinity(t *testing.T) {
+       testAllCurves(t, testInfinity)
 }
 
 func testInfinity(t *testing.T, curve Curve) {
@@ -455,199 +111,66 @@ func testInfinity(t *testing.T, curve Curve) {
        }
 }
 
-func TestInfinity(t *testing.T) {
-       tests := []struct {
-               name  string
-               curve Curve
-       }{
-               {"P-224", P224()},
-               {"P-256", P256()},
-               {"P-256/Generic", P256().Params()},
-               {"P-384", P384()},
-               {"P-521", P521()},
-       }
-       if testing.Short() {
-               tests = tests[:1]
-       }
-       for _, test := range tests {
-               curve := test.curve
-               t.Run(test.name, func(t *testing.T) {
-                       testInfinity(t, curve)
-               })
-       }
-}
-
-type synthCombinedMult struct {
-       Curve
-}
-
-func (s synthCombinedMult) CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int) {
-       x1, y1 := s.ScalarBaseMult(baseScalar)
-       x2, y2 := s.ScalarMult(bigX, bigY, scalar)
-       return s.Add(x1, y1, x2, y2)
-}
-
-func TestCombinedMult(t *testing.T) {
-       type combinedMult interface {
-               Curve
-               CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int)
-       }
-
-       p256, ok := P256().(combinedMult)
-       if !ok {
-               p256 = &synthCombinedMult{P256()}
-       }
-
-       gx := p256.Params().Gx
-       gy := p256.Params().Gy
-
-       zero := make([]byte, 32)
-       one := make([]byte, 32)
-       one[31] = 1
-       two := make([]byte, 32)
-       two[31] = 2
-
-       // 0×G + 0×G = ∞
-       x, y := p256.CombinedMult(gx, gy, zero, zero)
-       if x.Sign() != 0 || y.Sign() != 0 {
-               t.Errorf("0×G + 0×G = (%d, %d), should be ∞", x, y)
-       }
-
-       // 1×G + 0×G = G
-       x, y = p256.CombinedMult(gx, gy, one, zero)
-       if x.Cmp(gx) != 0 || y.Cmp(gy) != 0 {
-               t.Errorf("1×G + 0×G = (%d, %d), should be (%d, %d)", x, y, gx, gy)
-       }
-
-       // 0×G + 1×G = G
-       x, y = p256.CombinedMult(gx, gy, zero, one)
-       if x.Cmp(gx) != 0 || y.Cmp(gy) != 0 {
-               t.Errorf("0×G + 1×G = (%d, %d), should be (%d, %d)", x, y, gx, gy)
-       }
-
-       // 1×G + 1×G = 2×G
-       x, y = p256.CombinedMult(gx, gy, one, one)
-       ggx, ggy := p256.ScalarBaseMult(two)
-       if x.Cmp(ggx) != 0 || y.Cmp(ggy) != 0 {
-               t.Errorf("1×G + 1×G = (%d, %d), should be (%d, %d)", x, y, ggx, ggy)
-       }
-
-       minusOne := new(big.Int).Sub(p256.Params().N, big.NewInt(1))
-       // 1×G + (-1)×G = ∞
-       x, y = p256.CombinedMult(gx, gy, one, minusOne.Bytes())
-       if x.Sign() != 0 || y.Sign() != 0 {
-               t.Errorf("1×G + (-1)×G = (%d, %d), should be ∞", x, y)
-       }
-}
-
-func BenchmarkBaseMult(b *testing.B) {
-       b.ResetTimer()
-       p224 := P224()
-       e := p224BaseMultTests[25]
-       k, _ := new(big.Int).SetString(e.k, 10)
-       b.ReportAllocs()
-       b.StartTimer()
-       b.RunParallel(func(pb *testing.PB) {
-               for pb.Next() {
-                       p224.ScalarBaseMult(k.Bytes())
+func TestMarshal(t *testing.T) {
+       testAllCurves(t, func(t *testing.T, curve Curve) {
+               _, x, y, err := GenerateKey(curve, rand.Reader)
+               if err != nil {
+                       t.Fatal(err)
                }
-       })
-}
-
-func BenchmarkBaseMultP256(b *testing.B) {
-       b.ResetTimer()
-       p256 := P256()
-       e := p224BaseMultTests[25]
-       k, _ := new(big.Int).SetString(e.k, 10)
-       b.ReportAllocs()
-       b.StartTimer()
-       b.RunParallel(func(pb *testing.PB) {
-               for pb.Next() {
-                       p256.ScalarBaseMult(k.Bytes())
+               serialized := Marshal(curve, x, y)
+               xx, yy := Unmarshal(curve, serialized)
+               if xx == nil {
+                       t.Fatal("failed to unmarshal")
                }
-       })
-}
-
-func BenchmarkScalarMultP256(b *testing.B) {
-       b.ResetTimer()
-       p256 := P256()
-       _, x, y, _ := GenerateKey(p256, rand.Reader)
-       priv, _, _, _ := GenerateKey(p256, rand.Reader)
-
-       b.ReportAllocs()
-       b.StartTimer()
-       b.RunParallel(func(pb *testing.PB) {
-               for pb.Next() {
-                       p256.ScalarMult(x, y, priv)
+               if xx.Cmp(x) != 0 || yy.Cmp(y) != 0 {
+                       t.Fatal("unmarshal returned different values")
                }
        })
 }
 
-func TestMarshal(t *testing.T) {
-       p224 := P224()
-       _, x, y, err := GenerateKey(p224, rand.Reader)
-       if err != nil {
-               t.Error(err)
-               return
-       }
-       serialized := Marshal(p224, x, y)
-       xx, yy := Unmarshal(p224, serialized)
-       if xx == nil {
-               t.Error("failed to unmarshal")
-               return
-       }
-       if xx.Cmp(x) != 0 || yy.Cmp(y) != 0 {
-               t.Error("unmarshal returned different values")
-               return
-       }
-}
-
-func TestP224Overflow(t *testing.T) {
-       // This tests for a specific bug in the P224 implementation.
-       p224 := P224()
-       pointData, _ := hex.DecodeString("049B535B45FB0A2072398A6831834624C7E32CCFD5A4B933BCEAF77F1DD945E08BBE5178F5EDF5E733388F196D2A631D2E075BB16CBFEEA15B")
-       x, y := Unmarshal(p224, pointData)
-       if !p224.IsOnCurve(x, y) {
-               t.Error("P224 failed to validate a correct point")
-       }
+func TestUnmarshalToLargeCoordinates(t *testing.T) {
+       // See https://golang.org/issues/20482.
+       testAllCurves(t, testUnmarshalToLargeCoordinates)
 }
 
-// See https://golang.org/issues/20482
-func TestUnmarshalToLargeCoordinates(t *testing.T) {
-       curve := P256()
+func testUnmarshalToLargeCoordinates(t *testing.T, curve Curve) {
        p := curve.Params().P
-
-       invalidX, invalidY := make([]byte, 65), make([]byte, 65)
-       invalidX[0], invalidY[0] = 4, 4 // uncompressed encoding
+       byteLen := (p.BitLen() + 7) / 8
 
        // Set x to be greater than curve's parameter P – specifically, to P+5.
        // Set y to mod_sqrt(x^3 - 3x + B)) so that (x mod P = 5 , y) is on the
        // curve.
        x := new(big.Int).Add(p, big.NewInt(5))
-       y, _ := new(big.Int).SetString("31468013646237722594854082025316614106172411895747863909393730389177298123724", 10)
+       y := curve.Params().polynomial(x)
+       y.ModSqrt(y, p)
 
-       copy(invalidX[1:], x.Bytes())
-       copy(invalidX[33:], y.Bytes())
+       invalid := make([]byte, byteLen*2+1)
+       invalid[0] = 4 // uncompressed encoding
+       x.FillBytes(invalid[1 : 1+byteLen])
+       y.FillBytes(invalid[1+byteLen:])
 
-       if X, Y := Unmarshal(curve, invalidX); X != nil || Y != nil {
+       if X, Y := Unmarshal(curve, invalid); X != nil || Y != nil {
                t.Errorf("Unmarshal accepts invalid X coordinate")
        }
 
-       // This is a point on the curve with a small y value, small enough that we can add p and still be within 32 bytes.
-       x, _ = new(big.Int).SetString("31931927535157963707678568152204072984517581467226068221761862915403492091210", 10)
-       y, _ = new(big.Int).SetString("5208467867388784005506817585327037698770365050895731383201516607147", 10)
-       y.Add(y, p)
+       if curve == p256 {
+               // This is a point on the curve with a small y value, small enough that
+               // we can add p and still be within 32 bytes.
+               x, _ = new(big.Int).SetString("31931927535157963707678568152204072984517581467226068221761862915403492091210", 10)
+               y, _ = new(big.Int).SetString("5208467867388784005506817585327037698770365050895731383201516607147", 10)
+               y.Add(y, p)
 
-       if p.Cmp(y) > 0 || y.BitLen() != 256 {
-               t.Fatal("y not within expected range")
-       }
+               if p.Cmp(y) > 0 || y.BitLen() != 256 {
+                       t.Fatal("y not within expected range")
+               }
 
-       // marshal
-       copy(invalidY[1:], x.Bytes())
-       copy(invalidY[33:], y.Bytes())
+               // marshal
+               x.FillBytes(invalid[1 : 1+byteLen])
+               y.FillBytes(invalid[1+byteLen:])
 
-       if X, Y := Unmarshal(curve, invalidY); X != nil || Y != nil {
-               t.Errorf("Unmarshal accepts invalid Y coordinate")
+               if X, Y := Unmarshal(curve, invalid); X != nil || Y != nil {
+                       t.Errorf("Unmarshal accepts invalid Y coordinate")
+               }
        }
 }
 
@@ -677,27 +200,14 @@ func TestMarshalCompressed(t *testing.T) {
                t.Skip("skipping other curves on short test")
        }
 
-       t.Run("P-224", func(t *testing.T) {
-               _, x, y, err := GenerateKey(P224(), rand.Reader)
+       testAllCurves(t, func(t *testing.T, curve Curve) {
+               _, x, y, err := GenerateKey(curve, rand.Reader)
                if err != nil {
                        t.Fatal(err)
                }
-               testMarshalCompressed(t, P224(), x, y, nil)
-       })
-       t.Run("P-384", func(t *testing.T) {
-               _, x, y, err := GenerateKey(P384(), rand.Reader)
-               if err != nil {
-                       t.Fatal(err)
-               }
-               testMarshalCompressed(t, P384(), x, y, nil)
-       })
-       t.Run("P-521", func(t *testing.T) {
-               _, x, y, err := GenerateKey(P521(), rand.Reader)
-               if err != nil {
-                       t.Fatal(err)
-               }
-               testMarshalCompressed(t, P521(), x, y, nil)
+               testMarshalCompressed(t, curve, x, y, nil)
        })
+
 }
 
 func testMarshalCompressed(t *testing.T, curve Curve, x, y *big.Int, want []byte) {
@@ -721,3 +231,46 @@ func testMarshalCompressed(t *testing.T, curve Curve, x, y *big.Int, want []byte
                t.Errorf("point did not round-trip correctly: got (%v, %v), want (%v, %v)", X, Y, x, y)
        }
 }
+
+func benchmarkAllCurves(t *testing.B, f func(*testing.B, Curve)) {
+       tests := []struct {
+               name  string
+               curve Curve
+       }{
+               {"P256", P256()},
+               {"P224", P224()},
+               {"P384", P384()},
+               {"P521", P521()},
+       }
+       for _, test := range tests {
+               curve := test.curve
+               t.Run(test.name, func(t *testing.B) {
+                       f(t, curve)
+               })
+       }
+}
+
+func BenchmarkScalarBaseMult(b *testing.B) {
+       benchmarkAllCurves(b, func(b *testing.B, curve Curve) {
+               priv, _, _, _ := GenerateKey(curve, rand.Reader)
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       x, _ := curve.ScalarBaseMult(priv)
+                       // Prevent the compiler from optimizing out the operation.
+                       priv[0] ^= byte(x.Bits()[0])
+               }
+       })
+}
+
+func BenchmarkScalarMult(b *testing.B) {
+       benchmarkAllCurves(b, func(b *testing.B, curve Curve) {
+               _, x, y, _ := GenerateKey(curve, rand.Reader)
+               priv, _, _, _ := GenerateKey(curve, rand.Reader)
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       x, y = curve.ScalarMult(x, y, priv)
+               }
+       })
+}
index b9209a789bf35ccbb95993f31a310a9cfa1e79d9..8ff3bf3cc245056169cc4c74d74de4db0d390217 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build amd64 || arm64 || ppc64le
 // +build amd64 arm64 ppc64le
 
 package elliptic
@@ -13,7 +14,6 @@ import (
 )
 
 func TestFuzz(t *testing.T) {
-
        p256 := P256()
        p256Generic := p256.Params()
 
diff --git a/libgo/go/crypto/elliptic/internal/fiat/p521.go b/libgo/go/crypto/elliptic/internal/fiat/p521.go
new file mode 100644 (file)
index 0000000..dc67732
--- /dev/null
@@ -0,0 +1,197 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package fiat implements prime order fields using formally verified algorithms
+// from the Fiat Cryptography project.
+package fiat
+
+import (
+       "crypto/subtle"
+       "errors"
+)
+
+// P521Element is an integer modulo 2^521 - 1.
+//
+// The zero value is a valid zero element.
+type P521Element struct {
+       // This element has the following bounds, which are tighter than
+       // the output bounds of some operations. Those operations must be
+       // followed by a carry.
+       //
+       // [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000],
+       // [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000],
+       // [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]
+       x [9]uint64
+}
+
+// One sets e = 1, and returns e.
+func (e *P521Element) One() *P521Element {
+       *e = P521Element{}
+       e.x[0] = 1
+       return e
+}
+
+// Equal returns 1 if e == t, and zero otherwise.
+func (e *P521Element) Equal(t *P521Element) int {
+       eBytes := e.Bytes()
+       tBytes := t.Bytes()
+       return subtle.ConstantTimeCompare(eBytes, tBytes)
+}
+
+var p521ZeroEncoding = new(P521Element).Bytes()
+
+// IsZero returns 1 if e == 0, and zero otherwise.
+func (e *P521Element) IsZero() int {
+       eBytes := e.Bytes()
+       return subtle.ConstantTimeCompare(eBytes, p521ZeroEncoding)
+}
+
+// Set sets e = t, and returns e.
+func (e *P521Element) Set(t *P521Element) *P521Element {
+       e.x = t.x
+       return e
+}
+
+// Bytes returns the 66-byte little-endian encoding of e.
+func (e *P521Element) Bytes() []byte {
+       // This function must be inlined to move the allocation to the parent and
+       // save it from escaping to the heap.
+       var out [66]byte
+       p521ToBytes(&out, &e.x)
+       return out[:]
+}
+
+// SetBytes sets e = v, where v is a little-endian 66-byte encoding, and returns
+// e. If v is not 66 bytes or it encodes a value higher than 2^521 - 1, SetBytes
+// returns nil and an error, and e is unchanged.
+func (e *P521Element) SetBytes(v []byte) (*P521Element, error) {
+       if len(v) != 66 || v[65] > 1 {
+               return nil, errors.New("invalid P-521 field encoding")
+       }
+       var in [66]byte
+       copy(in[:], v)
+       p521FromBytes(&e.x, &in)
+       return e, nil
+}
+
+// Add sets e = t1 + t2, and returns e.
+func (e *P521Element) Add(t1, t2 *P521Element) *P521Element {
+       p521Add(&e.x, &t1.x, &t2.x)
+       p521Carry(&e.x, &e.x)
+       return e
+}
+
+// Sub sets e = t1 - t2, and returns e.
+func (e *P521Element) Sub(t1, t2 *P521Element) *P521Element {
+       p521Sub(&e.x, &t1.x, &t2.x)
+       p521Carry(&e.x, &e.x)
+       return e
+}
+
+// Mul sets e = t1 * t2, and returns e.
+func (e *P521Element) Mul(t1, t2 *P521Element) *P521Element {
+       p521CarryMul(&e.x, &t1.x, &t2.x)
+       return e
+}
+
+// Square sets e = t * t, and returns e.
+func (e *P521Element) Square(t *P521Element) *P521Element {
+       p521CarrySquare(&e.x, &t.x)
+       return e
+}
+
+// Select sets e to a if cond == 1, and to b if cond == 0.
+func (v *P521Element) Select(a, b *P521Element, cond int) *P521Element {
+       p521Selectznz(&v.x, p521Uint1(cond), &b.x, &a.x)
+       return v
+}
+
+// Invert sets e = 1/t, and returns e.
+//
+// If t == 0, Invert returns e = 0.
+func (e *P521Element) Invert(t *P521Element) *P521Element {
+       // Inversion is implemented as exponentiation with exponent p − 2.
+       // The sequence of multiplications and squarings was generated with
+       // github.com/mmcloughlin/addchain v0.2.0.
+
+       var t1, t2 = new(P521Element), new(P521Element)
+
+       // _10 = 2 * 1
+       t1.Square(t)
+
+       // _11 = 1 + _10
+       t1.Mul(t, t1)
+
+       // _1100 = _11 << 2
+       t2.Square(t1)
+       t2.Square(t2)
+
+       // _1111 = _11 + _1100
+       t1.Mul(t1, t2)
+
+       // _11110000 = _1111 << 4
+       t2.Square(t1)
+       for i := 0; i < 3; i++ {
+               t2.Square(t2)
+       }
+
+       // _11111111 = _1111 + _11110000
+       t1.Mul(t1, t2)
+
+       // x16 = _11111111<<8 + _11111111
+       t2.Square(t1)
+       for i := 0; i < 7; i++ {
+               t2.Square(t2)
+       }
+       t1.Mul(t1, t2)
+
+       // x32 = x16<<16 + x16
+       t2.Square(t1)
+       for i := 0; i < 15; i++ {
+               t2.Square(t2)
+       }
+       t1.Mul(t1, t2)
+
+       // x64 = x32<<32 + x32
+       t2.Square(t1)
+       for i := 0; i < 31; i++ {
+               t2.Square(t2)
+       }
+       t1.Mul(t1, t2)
+
+       // x65 = 2*x64 + 1
+       t2.Square(t1)
+       t2.Mul(t2, t)
+
+       // x129 = x65<<64 + x64
+       for i := 0; i < 64; i++ {
+               t2.Square(t2)
+       }
+       t1.Mul(t1, t2)
+
+       // x130 = 2*x129 + 1
+       t2.Square(t1)
+       t2.Mul(t2, t)
+
+       // x259 = x130<<129 + x129
+       for i := 0; i < 129; i++ {
+               t2.Square(t2)
+       }
+       t1.Mul(t1, t2)
+
+       // x260 = 2*x259 + 1
+       t2.Square(t1)
+       t2.Mul(t2, t)
+
+       // x519 = x260<<259 + x259
+       for i := 0; i < 259; i++ {
+               t2.Square(t2)
+       }
+       t1.Mul(t1, t2)
+
+       // return x519<<2 + 1
+       t1.Square(t1)
+       t1.Square(t1)
+       return e.Mul(t1, t)
+}
diff --git a/libgo/go/crypto/elliptic/internal/fiat/p521_fiat64.go b/libgo/go/crypto/elliptic/internal/fiat/p521_fiat64.go
new file mode 100644 (file)
index 0000000..f86283b
--- /dev/null
@@ -0,0 +1,1856 @@
+// Code generated by Fiat Cryptography. DO NOT EDIT.
+//
+// Autogenerated: 'fiat-crypto/src/ExtractionOCaml/unsaturated_solinas' --lang Go --no-wide-int --cmovznz-by-mul --internal-static --public-function-case camelCase --public-type-case camelCase --private-function-case camelCase --private-type-case camelCase --no-prefix-fiat --package-name fiat --doc-text-before-function-name '' --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' --doc-newline-before-package-declaration p521 64 9 '2^521 - 1' carry_mul carry_square carry add sub to_bytes from_bytes selectznz
+//
+// curve description: p521
+//
+// machine_wordsize = 64 (from "64")
+//
+// requested operations: carry_mul, carry_square, carry, add, sub, to_bytes, from_bytes, selectznz
+//
+// n = 9 (from "9")
+//
+// s-c = 2^521 - [(1, 1)] (from "2^521 - 1")
+//
+// tight_bounds_multiplier = 1 (from "")
+//
+//
+//
+// Computed values:
+//
+//   carry_chain = [0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1]
+//
+//   eval z = z[0] + (z[1] << 58) + (z[2] << 116) + (z[3] << 174) + (z[4] << 232) + (z[5] << 0x122) + (z[6] << 0x15c) + (z[7] << 0x196) + (z[8] << 0x1d0)
+//
+//   bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) + (z[32] << 256) + (z[33] << 0x108) + (z[34] << 0x110) + (z[35] << 0x118) + (z[36] << 0x120) + (z[37] << 0x128) + (z[38] << 0x130) + (z[39] << 0x138) + (z[40] << 0x140) + (z[41] << 0x148) + (z[42] << 0x150) + (z[43] << 0x158) + (z[44] << 0x160) + (z[45] << 0x168) + (z[46] << 0x170) + (z[47] << 0x178) + (z[48] << 0x180) + (z[49] << 0x188) + (z[50] << 0x190) + (z[51] << 0x198) + (z[52] << 0x1a0) + (z[53] << 0x1a8) + (z[54] << 0x1b0) + (z[55] << 0x1b8) + (z[56] << 0x1c0) + (z[57] << 0x1c8) + (z[58] << 0x1d0) + (z[59] << 0x1d8) + (z[60] << 0x1e0) + (z[61] << 0x1e8) + (z[62] << 0x1f0) + (z[63] << 0x1f8) + (z[64] << 2^9) + (z[65] << 0x208)
+//
+//   balance = [0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x3fffffffffffffe]
+
+package fiat
+
+import "math/bits"
+
+type p521Uint1 uint8
+type p521Int1 int8
+
+// p521AddcarryxU64 is a thin wrapper around bits.Add64 that uses p521Uint1 rather than uint64
+func p521AddcarryxU64(x uint64, y uint64, carry p521Uint1) (uint64, p521Uint1) {
+       sum, carryOut := bits.Add64(x, y, uint64(carry))
+       return sum, p521Uint1(carryOut)
+}
+
+// p521SubborrowxU64 is a thin wrapper around bits.Sub64 that uses p521Uint1 rather than uint64
+func p521SubborrowxU64(x uint64, y uint64, carry p521Uint1) (uint64, p521Uint1) {
+       sum, carryOut := bits.Sub64(x, y, uint64(carry))
+       return sum, p521Uint1(carryOut)
+}
+
+// p521AddcarryxU58 is an addition with carry.
+//
+// Postconditions:
+//   out1 = (arg1 + arg2 + arg3) mod 2^58
+//   out2 = ⌊(arg1 + arg2 + arg3) / 2^58⌋
+//
+// Input Bounds:
+//   arg1: [0x0 ~> 0x1]
+//   arg2: [0x0 ~> 0x3ffffffffffffff]
+//   arg3: [0x0 ~> 0x3ffffffffffffff]
+// Output Bounds:
+//   out1: [0x0 ~> 0x3ffffffffffffff]
+//   out2: [0x0 ~> 0x1]
+func p521AddcarryxU58(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) {
+       x1 := ((uint64(arg1) + arg2) + arg3)
+       x2 := (x1 & 0x3ffffffffffffff)
+       x3 := p521Uint1((x1 >> 58))
+       *out1 = x2
+       *out2 = x3
+}
+
+// p521SubborrowxU58 is a subtraction with borrow.
+//
+// Postconditions:
+//   out1 = (-arg1 + arg2 + -arg3) mod 2^58
+//   out2 = -⌊(-arg1 + arg2 + -arg3) / 2^58⌋
+//
+// Input Bounds:
+//   arg1: [0x0 ~> 0x1]
+//   arg2: [0x0 ~> 0x3ffffffffffffff]
+//   arg3: [0x0 ~> 0x3ffffffffffffff]
+// Output Bounds:
+//   out1: [0x0 ~> 0x3ffffffffffffff]
+//   out2: [0x0 ~> 0x1]
+func p521SubborrowxU58(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) {
+       x1 := ((int64(arg2) - int64(arg1)) - int64(arg3))
+       x2 := p521Int1((x1 >> 58))
+       x3 := (uint64(x1) & 0x3ffffffffffffff)
+       *out1 = x3
+       *out2 = (0x0 - p521Uint1(x2))
+}
+
+// p521AddcarryxU57 is an addition with carry.
+//
+// Postconditions:
+//   out1 = (arg1 + arg2 + arg3) mod 2^57
+//   out2 = ⌊(arg1 + arg2 + arg3) / 2^57⌋
+//
+// Input Bounds:
+//   arg1: [0x0 ~> 0x1]
+//   arg2: [0x0 ~> 0x1ffffffffffffff]
+//   arg3: [0x0 ~> 0x1ffffffffffffff]
+// Output Bounds:
+//   out1: [0x0 ~> 0x1ffffffffffffff]
+//   out2: [0x0 ~> 0x1]
+func p521AddcarryxU57(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) {
+       x1 := ((uint64(arg1) + arg2) + arg3)
+       x2 := (x1 & 0x1ffffffffffffff)
+       x3 := p521Uint1((x1 >> 57))
+       *out1 = x2
+       *out2 = x3
+}
+
+// p521SubborrowxU57 is a subtraction with borrow.
+//
+// Postconditions:
+//   out1 = (-arg1 + arg2 + -arg3) mod 2^57
+//   out2 = -⌊(-arg1 + arg2 + -arg3) / 2^57⌋
+//
+// Input Bounds:
+//   arg1: [0x0 ~> 0x1]
+//   arg2: [0x0 ~> 0x1ffffffffffffff]
+//   arg3: [0x0 ~> 0x1ffffffffffffff]
+// Output Bounds:
+//   out1: [0x0 ~> 0x1ffffffffffffff]
+//   out2: [0x0 ~> 0x1]
+func p521SubborrowxU57(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) {
+       x1 := ((int64(arg2) - int64(arg1)) - int64(arg3))
+       x2 := p521Int1((x1 >> 57))
+       x3 := (uint64(x1) & 0x1ffffffffffffff)
+       *out1 = x3
+       *out2 = (0x0 - p521Uint1(x2))
+}
+
+// p521CmovznzU64 is a single-word conditional move.
+//
+// Postconditions:
+//   out1 = (if arg1 = 0 then arg2 else arg3)
+//
+// Input Bounds:
+//   arg1: [0x0 ~> 0x1]
+//   arg2: [0x0 ~> 0xffffffffffffffff]
+//   arg3: [0x0 ~> 0xffffffffffffffff]
+// Output Bounds:
+//   out1: [0x0 ~> 0xffffffffffffffff]
+func p521CmovznzU64(out1 *uint64, arg1 p521Uint1, arg2 uint64, arg3 uint64) {
+       x1 := (uint64(arg1) * 0xffffffffffffffff)
+       x2 := ((x1 & arg3) | ((^x1) & arg2))
+       *out1 = x2
+}
+
+// p521CarryMul multiplies two field elements and reduces the result.
+//
+// Postconditions:
+//   eval out1 mod m = (eval arg1 * eval arg2) mod m
+//
+// Input Bounds:
+//   arg1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]]
+//   arg2: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]]
+// Output Bounds:
+//   out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
+func p521CarryMul(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) {
+       var x1 uint64
+       var x2 uint64
+       x2, x1 = bits.Mul64(arg1[8], (arg2[8] * 0x2))
+       var x3 uint64
+       var x4 uint64
+       x4, x3 = bits.Mul64(arg1[8], (arg2[7] * 0x2))
+       var x5 uint64
+       var x6 uint64
+       x6, x5 = bits.Mul64(arg1[8], (arg2[6] * 0x2))
+       var x7 uint64
+       var x8 uint64
+       x8, x7 = bits.Mul64(arg1[8], (arg2[5] * 0x2))
+       var x9 uint64
+       var x10 uint64
+       x10, x9 = bits.Mul64(arg1[8], (arg2[4] * 0x2))
+       var x11 uint64
+       var x12 uint64
+       x12, x11 = bits.Mul64(arg1[8], (arg2[3] * 0x2))
+       var x13 uint64
+       var x14 uint64
+       x14, x13 = bits.Mul64(arg1[8], (arg2[2] * 0x2))
+       var x15 uint64
+       var x16 uint64
+       x16, x15 = bits.Mul64(arg1[8], (arg2[1] * 0x2))
+       var x17 uint64
+       var x18 uint64
+       x18, x17 = bits.Mul64(arg1[7], (arg2[8] * 0x2))
+       var x19 uint64
+       var x20 uint64
+       x20, x19 = bits.Mul64(arg1[7], (arg2[7] * 0x2))
+       var x21 uint64
+       var x22 uint64
+       x22, x21 = bits.Mul64(arg1[7], (arg2[6] * 0x2))
+       var x23 uint64
+       var x24 uint64
+       x24, x23 = bits.Mul64(arg1[7], (arg2[5] * 0x2))
+       var x25 uint64
+       var x26 uint64
+       x26, x25 = bits.Mul64(arg1[7], (arg2[4] * 0x2))
+       var x27 uint64
+       var x28 uint64
+       x28, x27 = bits.Mul64(arg1[7], (arg2[3] * 0x2))
+       var x29 uint64
+       var x30 uint64
+       x30, x29 = bits.Mul64(arg1[7], (arg2[2] * 0x2))
+       var x31 uint64
+       var x32 uint64
+       x32, x31 = bits.Mul64(arg1[6], (arg2[8] * 0x2))
+       var x33 uint64
+       var x34 uint64
+       x34, x33 = bits.Mul64(arg1[6], (arg2[7] * 0x2))
+       var x35 uint64
+       var x36 uint64
+       x36, x35 = bits.Mul64(arg1[6], (arg2[6] * 0x2))
+       var x37 uint64
+       var x38 uint64
+       x38, x37 = bits.Mul64(arg1[6], (arg2[5] * 0x2))
+       var x39 uint64
+       var x40 uint64
+       x40, x39 = bits.Mul64(arg1[6], (arg2[4] * 0x2))
+       var x41 uint64
+       var x42 uint64
+       x42, x41 = bits.Mul64(arg1[6], (arg2[3] * 0x2))
+       var x43 uint64
+       var x44 uint64
+       x44, x43 = bits.Mul64(arg1[5], (arg2[8] * 0x2))
+       var x45 uint64
+       var x46 uint64
+       x46, x45 = bits.Mul64(arg1[5], (arg2[7] * 0x2))
+       var x47 uint64
+       var x48 uint64
+       x48, x47 = bits.Mul64(arg1[5], (arg2[6] * 0x2))
+       var x49 uint64
+       var x50 uint64
+       x50, x49 = bits.Mul64(arg1[5], (arg2[5] * 0x2))
+       var x51 uint64
+       var x52 uint64
+       x52, x51 = bits.Mul64(arg1[5], (arg2[4] * 0x2))
+       var x53 uint64
+       var x54 uint64
+       x54, x53 = bits.Mul64(arg1[4], (arg2[8] * 0x2))
+       var x55 uint64
+       var x56 uint64
+       x56, x55 = bits.Mul64(arg1[4], (arg2[7] * 0x2))
+       var x57 uint64
+       var x58 uint64
+       x58, x57 = bits.Mul64(arg1[4], (arg2[6] * 0x2))
+       var x59 uint64
+       var x60 uint64
+       x60, x59 = bits.Mul64(arg1[4], (arg2[5] * 0x2))
+       var x61 uint64
+       var x62 uint64
+       x62, x61 = bits.Mul64(arg1[3], (arg2[8] * 0x2))
+       var x63 uint64
+       var x64 uint64
+       x64, x63 = bits.Mul64(arg1[3], (arg2[7] * 0x2))
+       var x65 uint64
+       var x66 uint64
+       x66, x65 = bits.Mul64(arg1[3], (arg2[6] * 0x2))
+       var x67 uint64
+       var x68 uint64
+       x68, x67 = bits.Mul64(arg1[2], (arg2[8] * 0x2))
+       var x69 uint64
+       var x70 uint64
+       x70, x69 = bits.Mul64(arg1[2], (arg2[7] * 0x2))
+       var x71 uint64
+       var x72 uint64
+       x72, x71 = bits.Mul64(arg1[1], (arg2[8] * 0x2))
+       var x73 uint64
+       var x74 uint64
+       x74, x73 = bits.Mul64(arg1[8], arg2[0])
+       var x75 uint64
+       var x76 uint64
+       x76, x75 = bits.Mul64(arg1[7], arg2[1])
+       var x77 uint64
+       var x78 uint64
+       x78, x77 = bits.Mul64(arg1[7], arg2[0])
+       var x79 uint64
+       var x80 uint64
+       x80, x79 = bits.Mul64(arg1[6], arg2[2])
+       var x81 uint64
+       var x82 uint64
+       x82, x81 = bits.Mul64(arg1[6], arg2[1])
+       var x83 uint64
+       var x84 uint64
+       x84, x83 = bits.Mul64(arg1[6], arg2[0])
+       var x85 uint64
+       var x86 uint64
+       x86, x85 = bits.Mul64(arg1[5], arg2[3])
+       var x87 uint64
+       var x88 uint64
+       x88, x87 = bits.Mul64(arg1[5], arg2[2])
+       var x89 uint64
+       var x90 uint64
+       x90, x89 = bits.Mul64(arg1[5], arg2[1])
+       var x91 uint64
+       var x92 uint64
+       x92, x91 = bits.Mul64(arg1[5], arg2[0])
+       var x93 uint64
+       var x94 uint64
+       x94, x93 = bits.Mul64(arg1[4], arg2[4])
+       var x95 uint64
+       var x96 uint64
+       x96, x95 = bits.Mul64(arg1[4], arg2[3])
+       var x97 uint64
+       var x98 uint64
+       x98, x97 = bits.Mul64(arg1[4], arg2[2])
+       var x99 uint64
+       var x100 uint64
+       x100, x99 = bits.Mul64(arg1[4], arg2[1])
+       var x101 uint64
+       var x102 uint64
+       x102, x101 = bits.Mul64(arg1[4], arg2[0])
+       var x103 uint64
+       var x104 uint64
+       x104, x103 = bits.Mul64(arg1[3], arg2[5])
+       var x105 uint64
+       var x106 uint64
+       x106, x105 = bits.Mul64(arg1[3], arg2[4])
+       var x107 uint64
+       var x108 uint64
+       x108, x107 = bits.Mul64(arg1[3], arg2[3])
+       var x109 uint64
+       var x110 uint64
+       x110, x109 = bits.Mul64(arg1[3], arg2[2])
+       var x111 uint64
+       var x112 uint64
+       x112, x111 = bits.Mul64(arg1[3], arg2[1])
+       var x113 uint64
+       var x114 uint64
+       x114, x113 = bits.Mul64(arg1[3], arg2[0])
+       var x115 uint64
+       var x116 uint64
+       x116, x115 = bits.Mul64(arg1[2], arg2[6])
+       var x117 uint64
+       var x118 uint64
+       x118, x117 = bits.Mul64(arg1[2], arg2[5])
+       var x119 uint64
+       var x120 uint64
+       x120, x119 = bits.Mul64(arg1[2], arg2[4])
+       var x121 uint64
+       var x122 uint64
+       x122, x121 = bits.Mul64(arg1[2], arg2[3])
+       var x123 uint64
+       var x124 uint64
+       x124, x123 = bits.Mul64(arg1[2], arg2[2])
+       var x125 uint64
+       var x126 uint64
+       x126, x125 = bits.Mul64(arg1[2], arg2[1])
+       var x127 uint64
+       var x128 uint64
+       x128, x127 = bits.Mul64(arg1[2], arg2[0])
+       var x129 uint64
+       var x130 uint64
+       x130, x129 = bits.Mul64(arg1[1], arg2[7])
+       var x131 uint64
+       var x132 uint64
+       x132, x131 = bits.Mul64(arg1[1], arg2[6])
+       var x133 uint64
+       var x134 uint64
+       x134, x133 = bits.Mul64(arg1[1], arg2[5])
+       var x135 uint64
+       var x136 uint64
+       x136, x135 = bits.Mul64(arg1[1], arg2[4])
+       var x137 uint64
+       var x138 uint64
+       x138, x137 = bits.Mul64(arg1[1], arg2[3])
+       var x139 uint64
+       var x140 uint64
+       x140, x139 = bits.Mul64(arg1[1], arg2[2])
+       var x141 uint64
+       var x142 uint64
+       x142, x141 = bits.Mul64(arg1[1], arg2[1])
+       var x143 uint64
+       var x144 uint64
+       x144, x143 = bits.Mul64(arg1[1], arg2[0])
+       var x145 uint64
+       var x146 uint64
+       x146, x145 = bits.Mul64(arg1[0], arg2[8])
+       var x147 uint64
+       var x148 uint64
+       x148, x147 = bits.Mul64(arg1[0], arg2[7])
+       var x149 uint64
+       var x150 uint64
+       x150, x149 = bits.Mul64(arg1[0], arg2[6])
+       var x151 uint64
+       var x152 uint64
+       x152, x151 = bits.Mul64(arg1[0], arg2[5])
+       var x153 uint64
+       var x154 uint64
+       x154, x153 = bits.Mul64(arg1[0], arg2[4])
+       var x155 uint64
+       var x156 uint64
+       x156, x155 = bits.Mul64(arg1[0], arg2[3])
+       var x157 uint64
+       var x158 uint64
+       x158, x157 = bits.Mul64(arg1[0], arg2[2])
+       var x159 uint64
+       var x160 uint64
+       x160, x159 = bits.Mul64(arg1[0], arg2[1])
+       var x161 uint64
+       var x162 uint64
+       x162, x161 = bits.Mul64(arg1[0], arg2[0])
+       var x163 uint64
+       var x164 p521Uint1
+       x163, x164 = p521AddcarryxU64(x29, x15, 0x0)
+       var x165 uint64
+       x165, _ = p521AddcarryxU64(x30, x16, x164)
+       var x167 uint64
+       var x168 p521Uint1
+       x167, x168 = p521AddcarryxU64(x41, x163, 0x0)
+       var x169 uint64
+       x169, _ = p521AddcarryxU64(x42, x165, x168)
+       var x171 uint64
+       var x172 p521Uint1
+       x171, x172 = p521AddcarryxU64(x51, x167, 0x0)
+       var x173 uint64
+       x173, _ = p521AddcarryxU64(x52, x169, x172)
+       var x175 uint64
+       var x176 p521Uint1
+       x175, x176 = p521AddcarryxU64(x59, x171, 0x0)
+       var x177 uint64
+       x177, _ = p521AddcarryxU64(x60, x173, x176)
+       var x179 uint64
+       var x180 p521Uint1
+       x179, x180 = p521AddcarryxU64(x65, x175, 0x0)
+       var x181 uint64
+       x181, _ = p521AddcarryxU64(x66, x177, x180)
+       var x183 uint64
+       var x184 p521Uint1
+       x183, x184 = p521AddcarryxU64(x69, x179, 0x0)
+       var x185 uint64
+       x185, _ = p521AddcarryxU64(x70, x181, x184)
+       var x187 uint64
+       var x188 p521Uint1
+       x187, x188 = p521AddcarryxU64(x71, x183, 0x0)
+       var x189 uint64
+       x189, _ = p521AddcarryxU64(x72, x185, x188)
+       var x191 uint64
+       var x192 p521Uint1
+       x191, x192 = p521AddcarryxU64(x161, x187, 0x0)
+       var x193 uint64
+       x193, _ = p521AddcarryxU64(x162, x189, x192)
+       x195 := ((x191 >> 58) | ((x193 << 6) & 0xffffffffffffffff))
+       x196 := (x193 >> 58)
+       x197 := (x191 & 0x3ffffffffffffff)
+       var x198 uint64
+       var x199 p521Uint1
+       x198, x199 = p521AddcarryxU64(x75, x73, 0x0)
+       var x200 uint64
+       x200, _ = p521AddcarryxU64(x76, x74, x199)
+       var x202 uint64
+       var x203 p521Uint1
+       x202, x203 = p521AddcarryxU64(x79, x198, 0x0)
+       var x204 uint64
+       x204, _ = p521AddcarryxU64(x80, x200, x203)
+       var x206 uint64
+       var x207 p521Uint1
+       x206, x207 = p521AddcarryxU64(x85, x202, 0x0)
+       var x208 uint64
+       x208, _ = p521AddcarryxU64(x86, x204, x207)
+       var x210 uint64
+       var x211 p521Uint1
+       x210, x211 = p521AddcarryxU64(x93, x206, 0x0)
+       var x212 uint64
+       x212, _ = p521AddcarryxU64(x94, x208, x211)
+       var x214 uint64
+       var x215 p521Uint1
+       x214, x215 = p521AddcarryxU64(x103, x210, 0x0)
+       var x216 uint64
+       x216, _ = p521AddcarryxU64(x104, x212, x215)
+       var x218 uint64
+       var x219 p521Uint1
+       x218, x219 = p521AddcarryxU64(x115, x214, 0x0)
+       var x220 uint64
+       x220, _ = p521AddcarryxU64(x116, x216, x219)
+       var x222 uint64
+       var x223 p521Uint1
+       x222, x223 = p521AddcarryxU64(x129, x218, 0x0)
+       var x224 uint64
+       x224, _ = p521AddcarryxU64(x130, x220, x223)
+       var x226 uint64
+       var x227 p521Uint1
+       x226, x227 = p521AddcarryxU64(x145, x222, 0x0)
+       var x228 uint64
+       x228, _ = p521AddcarryxU64(x146, x224, x227)
+       var x230 uint64
+       var x231 p521Uint1
+       x230, x231 = p521AddcarryxU64(x77, x1, 0x0)
+       var x232 uint64
+       x232, _ = p521AddcarryxU64(x78, x2, x231)
+       var x234 uint64
+       var x235 p521Uint1
+       x234, x235 = p521AddcarryxU64(x81, x230, 0x0)
+       var x236 uint64
+       x236, _ = p521AddcarryxU64(x82, x232, x235)
+       var x238 uint64
+       var x239 p521Uint1
+       x238, x239 = p521AddcarryxU64(x87, x234, 0x0)
+       var x240 uint64
+       x240, _ = p521AddcarryxU64(x88, x236, x239)
+       var x242 uint64
+       var x243 p521Uint1
+       x242, x243 = p521AddcarryxU64(x95, x238, 0x0)
+       var x244 uint64
+       x244, _ = p521AddcarryxU64(x96, x240, x243)
+       var x246 uint64
+       var x247 p521Uint1
+       x246, x247 = p521AddcarryxU64(x105, x242, 0x0)
+       var x248 uint64
+       x248, _ = p521AddcarryxU64(x106, x244, x247)
+       var x250 uint64
+       var x251 p521Uint1
+       x250, x251 = p521AddcarryxU64(x117, x246, 0x0)
+       var x252 uint64
+       x252, _ = p521AddcarryxU64(x118, x248, x251)
+       var x254 uint64
+       var x255 p521Uint1
+       x254, x255 = p521AddcarryxU64(x131, x250, 0x0)
+       var x256 uint64
+       x256, _ = p521AddcarryxU64(x132, x252, x255)
+       var x258 uint64
+       var x259 p521Uint1
+       x258, x259 = p521AddcarryxU64(x147, x254, 0x0)
+       var x260 uint64
+       x260, _ = p521AddcarryxU64(x148, x256, x259)
+       var x262 uint64
+       var x263 p521Uint1
+       x262, x263 = p521AddcarryxU64(x17, x3, 0x0)
+       var x264 uint64
+       x264, _ = p521AddcarryxU64(x18, x4, x263)
+       var x266 uint64
+       var x267 p521Uint1
+       x266, x267 = p521AddcarryxU64(x83, x262, 0x0)
+       var x268 uint64
+       x268, _ = p521AddcarryxU64(x84, x264, x267)
+       var x270 uint64
+       var x271 p521Uint1
+       x270, x271 = p521AddcarryxU64(x89, x266, 0x0)
+       var x272 uint64
+       x272, _ = p521AddcarryxU64(x90, x268, x271)
+       var x274 uint64
+       var x275 p521Uint1
+       x274, x275 = p521AddcarryxU64(x97, x270, 0x0)
+       var x276 uint64
+       x276, _ = p521AddcarryxU64(x98, x272, x275)
+       var x278 uint64
+       var x279 p521Uint1
+       x278, x279 = p521AddcarryxU64(x107, x274, 0x0)
+       var x280 uint64
+       x280, _ = p521AddcarryxU64(x108, x276, x279)
+       var x282 uint64
+       var x283 p521Uint1
+       x282, x283 = p521AddcarryxU64(x119, x278, 0x0)
+       var x284 uint64
+       x284, _ = p521AddcarryxU64(x120, x280, x283)
+       var x286 uint64
+       var x287 p521Uint1
+       x286, x287 = p521AddcarryxU64(x133, x282, 0x0)
+       var x288 uint64
+       x288, _ = p521AddcarryxU64(x134, x284, x287)
+       var x290 uint64
+       var x291 p521Uint1
+       x290, x291 = p521AddcarryxU64(x149, x286, 0x0)
+       var x292 uint64
+       x292, _ = p521AddcarryxU64(x150, x288, x291)
+       var x294 uint64
+       var x295 p521Uint1
+       x294, x295 = p521AddcarryxU64(x19, x5, 0x0)
+       var x296 uint64
+       x296, _ = p521AddcarryxU64(x20, x6, x295)
+       var x298 uint64
+       var x299 p521Uint1
+       x298, x299 = p521AddcarryxU64(x31, x294, 0x0)
+       var x300 uint64
+       x300, _ = p521AddcarryxU64(x32, x296, x299)
+       var x302 uint64
+       var x303 p521Uint1
+       x302, x303 = p521AddcarryxU64(x91, x298, 0x0)
+       var x304 uint64
+       x304, _ = p521AddcarryxU64(x92, x300, x303)
+       var x306 uint64
+       var x307 p521Uint1
+       x306, x307 = p521AddcarryxU64(x99, x302, 0x0)
+       var x308 uint64
+       x308, _ = p521AddcarryxU64(x100, x304, x307)
+       var x310 uint64
+       var x311 p521Uint1
+       x310, x311 = p521AddcarryxU64(x109, x306, 0x0)
+       var x312 uint64
+       x312, _ = p521AddcarryxU64(x110, x308, x311)
+       var x314 uint64
+       var x315 p521Uint1
+       x314, x315 = p521AddcarryxU64(x121, x310, 0x0)
+       var x316 uint64
+       x316, _ = p521AddcarryxU64(x122, x312, x315)
+       var x318 uint64
+       var x319 p521Uint1
+       x318, x319 = p521AddcarryxU64(x135, x314, 0x0)
+       var x320 uint64
+       x320, _ = p521AddcarryxU64(x136, x316, x319)
+       var x322 uint64
+       var x323 p521Uint1
+       x322, x323 = p521AddcarryxU64(x151, x318, 0x0)
+       var x324 uint64
+       x324, _ = p521AddcarryxU64(x152, x320, x323)
+       var x326 uint64
+       var x327 p521Uint1
+       x326, x327 = p521AddcarryxU64(x21, x7, 0x0)
+       var x328 uint64
+       x328, _ = p521AddcarryxU64(x22, x8, x327)
+       var x330 uint64
+       var x331 p521Uint1
+       x330, x331 = p521AddcarryxU64(x33, x326, 0x0)
+       var x332 uint64
+       x332, _ = p521AddcarryxU64(x34, x328, x331)
+       var x334 uint64
+       var x335 p521Uint1
+       x334, x335 = p521AddcarryxU64(x43, x330, 0x0)
+       var x336 uint64
+       x336, _ = p521AddcarryxU64(x44, x332, x335)
+       var x338 uint64
+       var x339 p521Uint1
+       x338, x339 = p521AddcarryxU64(x101, x334, 0x0)
+       var x340 uint64
+       x340, _ = p521AddcarryxU64(x102, x336, x339)
+       var x342 uint64
+       var x343 p521Uint1
+       x342, x343 = p521AddcarryxU64(x111, x338, 0x0)
+       var x344 uint64
+       x344, _ = p521AddcarryxU64(x112, x340, x343)
+       var x346 uint64
+       var x347 p521Uint1
+       x346, x347 = p521AddcarryxU64(x123, x342, 0x0)
+       var x348 uint64
+       x348, _ = p521AddcarryxU64(x124, x344, x347)
+       var x350 uint64
+       var x351 p521Uint1
+       x350, x351 = p521AddcarryxU64(x137, x346, 0x0)
+       var x352 uint64
+       x352, _ = p521AddcarryxU64(x138, x348, x351)
+       var x354 uint64
+       var x355 p521Uint1
+       x354, x355 = p521AddcarryxU64(x153, x350, 0x0)
+       var x356 uint64
+       x356, _ = p521AddcarryxU64(x154, x352, x355)
+       var x358 uint64
+       var x359 p521Uint1
+       x358, x359 = p521AddcarryxU64(x23, x9, 0x0)
+       var x360 uint64
+       x360, _ = p521AddcarryxU64(x24, x10, x359)
+       var x362 uint64
+       var x363 p521Uint1
+       x362, x363 = p521AddcarryxU64(x35, x358, 0x0)
+       var x364 uint64
+       x364, _ = p521AddcarryxU64(x36, x360, x363)
+       var x366 uint64
+       var x367 p521Uint1
+       x366, x367 = p521AddcarryxU64(x45, x362, 0x0)
+       var x368 uint64
+       x368, _ = p521AddcarryxU64(x46, x364, x367)
+       var x370 uint64
+       var x371 p521Uint1
+       x370, x371 = p521AddcarryxU64(x53, x366, 0x0)
+       var x372 uint64
+       x372, _ = p521AddcarryxU64(x54, x368, x371)
+       var x374 uint64
+       var x375 p521Uint1
+       x374, x375 = p521AddcarryxU64(x113, x370, 0x0)
+       var x376 uint64
+       x376, _ = p521AddcarryxU64(x114, x372, x375)
+       var x378 uint64
+       var x379 p521Uint1
+       x378, x379 = p521AddcarryxU64(x125, x374, 0x0)
+       var x380 uint64
+       x380, _ = p521AddcarryxU64(x126, x376, x379)
+       var x382 uint64
+       var x383 p521Uint1
+       x382, x383 = p521AddcarryxU64(x139, x378, 0x0)
+       var x384 uint64
+       x384, _ = p521AddcarryxU64(x140, x380, x383)
+       var x386 uint64
+       var x387 p521Uint1
+       x386, x387 = p521AddcarryxU64(x155, x382, 0x0)
+       var x388 uint64
+       x388, _ = p521AddcarryxU64(x156, x384, x387)
+       var x390 uint64
+       var x391 p521Uint1
+       x390, x391 = p521AddcarryxU64(x25, x11, 0x0)
+       var x392 uint64
+       x392, _ = p521AddcarryxU64(x26, x12, x391)
+       var x394 uint64
+       var x395 p521Uint1
+       x394, x395 = p521AddcarryxU64(x37, x390, 0x0)
+       var x396 uint64
+       x396, _ = p521AddcarryxU64(x38, x392, x395)
+       var x398 uint64
+       var x399 p521Uint1
+       x398, x399 = p521AddcarryxU64(x47, x394, 0x0)
+       var x400 uint64
+       x400, _ = p521AddcarryxU64(x48, x396, x399)
+       var x402 uint64
+       var x403 p521Uint1
+       x402, x403 = p521AddcarryxU64(x55, x398, 0x0)
+       var x404 uint64
+       x404, _ = p521AddcarryxU64(x56, x400, x403)
+       var x406 uint64
+       var x407 p521Uint1
+       x406, x407 = p521AddcarryxU64(x61, x402, 0x0)
+       var x408 uint64
+       x408, _ = p521AddcarryxU64(x62, x404, x407)
+       var x410 uint64
+       var x411 p521Uint1
+       x410, x411 = p521AddcarryxU64(x127, x406, 0x0)
+       var x412 uint64
+       x412, _ = p521AddcarryxU64(x128, x408, x411)
+       var x414 uint64
+       var x415 p521Uint1
+       x414, x415 = p521AddcarryxU64(x141, x410, 0x0)
+       var x416 uint64
+       x416, _ = p521AddcarryxU64(x142, x412, x415)
+       var x418 uint64
+       var x419 p521Uint1
+       x418, x419 = p521AddcarryxU64(x157, x414, 0x0)
+       var x420 uint64
+       x420, _ = p521AddcarryxU64(x158, x416, x419)
+       var x422 uint64
+       var x423 p521Uint1
+       x422, x423 = p521AddcarryxU64(x27, x13, 0x0)
+       var x424 uint64
+       x424, _ = p521AddcarryxU64(x28, x14, x423)
+       var x426 uint64
+       var x427 p521Uint1
+       x426, x427 = p521AddcarryxU64(x39, x422, 0x0)
+       var x428 uint64
+       x428, _ = p521AddcarryxU64(x40, x424, x427)
+       var x430 uint64
+       var x431 p521Uint1
+       x430, x431 = p521AddcarryxU64(x49, x426, 0x0)
+       var x432 uint64
+       x432, _ = p521AddcarryxU64(x50, x428, x431)
+       var x434 uint64
+       var x435 p521Uint1
+       x434, x435 = p521AddcarryxU64(x57, x430, 0x0)
+       var x436 uint64
+       x436, _ = p521AddcarryxU64(x58, x432, x435)
+       var x438 uint64
+       var x439 p521Uint1
+       x438, x439 = p521AddcarryxU64(x63, x434, 0x0)
+       var x440 uint64
+       x440, _ = p521AddcarryxU64(x64, x436, x439)
+       var x442 uint64
+       var x443 p521Uint1
+       x442, x443 = p521AddcarryxU64(x67, x438, 0x0)
+       var x444 uint64
+       x444, _ = p521AddcarryxU64(x68, x440, x443)
+       var x446 uint64
+       var x447 p521Uint1
+       x446, x447 = p521AddcarryxU64(x143, x442, 0x0)
+       var x448 uint64
+       x448, _ = p521AddcarryxU64(x144, x444, x447)
+       var x450 uint64
+       var x451 p521Uint1
+       x450, x451 = p521AddcarryxU64(x159, x446, 0x0)
+       var x452 uint64
+       x452, _ = p521AddcarryxU64(x160, x448, x451)
+       var x454 uint64
+       var x455 p521Uint1
+       x454, x455 = p521AddcarryxU64(x195, x450, 0x0)
+       var x456 uint64
+       x456, _ = p521AddcarryxU64(x196, x452, x455)
+       x458 := ((x454 >> 58) | ((x456 << 6) & 0xffffffffffffffff))
+       x459 := (x456 >> 58)
+       x460 := (x454 & 0x3ffffffffffffff)
+       var x461 uint64
+       var x462 p521Uint1
+       x461, x462 = p521AddcarryxU64(x458, x418, 0x0)
+       var x463 uint64
+       x463, _ = p521AddcarryxU64(x459, x420, x462)
+       x465 := ((x461 >> 58) | ((x463 << 6) & 0xffffffffffffffff))
+       x466 := (x463 >> 58)
+       x467 := (x461 & 0x3ffffffffffffff)
+       var x468 uint64
+       var x469 p521Uint1
+       x468, x469 = p521AddcarryxU64(x465, x386, 0x0)
+       var x470 uint64
+       x470, _ = p521AddcarryxU64(x466, x388, x469)
+       x472 := ((x468 >> 58) | ((x470 << 6) & 0xffffffffffffffff))
+       x473 := (x470 >> 58)
+       x474 := (x468 & 0x3ffffffffffffff)
+       var x475 uint64
+       var x476 p521Uint1
+       x475, x476 = p521AddcarryxU64(x472, x354, 0x0)
+       var x477 uint64
+       x477, _ = p521AddcarryxU64(x473, x356, x476)
+       x479 := ((x475 >> 58) | ((x477 << 6) & 0xffffffffffffffff))
+       x480 := (x477 >> 58)
+       x481 := (x475 & 0x3ffffffffffffff)
+       var x482 uint64
+       var x483 p521Uint1
+       x482, x483 = p521AddcarryxU64(x479, x322, 0x0)
+       var x484 uint64
+       x484, _ = p521AddcarryxU64(x480, x324, x483)
+       x486 := ((x482 >> 58) | ((x484 << 6) & 0xffffffffffffffff))
+       x487 := (x484 >> 58)
+       x488 := (x482 & 0x3ffffffffffffff)
+       var x489 uint64
+       var x490 p521Uint1
+       x489, x490 = p521AddcarryxU64(x486, x290, 0x0)
+       var x491 uint64
+       x491, _ = p521AddcarryxU64(x487, x292, x490)
+       x493 := ((x489 >> 58) | ((x491 << 6) & 0xffffffffffffffff))
+       x494 := (x491 >> 58)
+       x495 := (x489 & 0x3ffffffffffffff)
+       var x496 uint64
+       var x497 p521Uint1
+       x496, x497 = p521AddcarryxU64(x493, x258, 0x0)
+       var x498 uint64
+       x498, _ = p521AddcarryxU64(x494, x260, x497)
+       x500 := ((x496 >> 58) | ((x498 << 6) & 0xffffffffffffffff))
+       x501 := (x498 >> 58)
+       x502 := (x496 & 0x3ffffffffffffff)
+       var x503 uint64
+       var x504 p521Uint1
+       x503, x504 = p521AddcarryxU64(x500, x226, 0x0)
+       var x505 uint64
+       x505, _ = p521AddcarryxU64(x501, x228, x504)
+       x507 := ((x503 >> 57) | ((x505 << 7) & 0xffffffffffffffff))
+       x508 := (x505 >> 57)
+       x509 := (x503 & 0x1ffffffffffffff)
+       var x510 uint64
+       var x511 p521Uint1
+       x510, x511 = p521AddcarryxU64(x197, x507, 0x0)
+       x512 := (uint64(x511) + x508)
+       x513 := ((x510 >> 58) | ((x512 << 6) & 0xffffffffffffffff))
+       x514 := (x510 & 0x3ffffffffffffff)
+       x515 := (x513 + x460)
+       x516 := p521Uint1((x515 >> 58))
+       x517 := (x515 & 0x3ffffffffffffff)
+       x518 := (uint64(x516) + x467)
+       out1[0] = x514
+       out1[1] = x517
+       out1[2] = x518
+       out1[3] = x474
+       out1[4] = x481
+       out1[5] = x488
+       out1[6] = x495
+       out1[7] = x502
+       out1[8] = x509
+}
+
+// p521CarrySquare squares a field element and reduces the result.
+//
+// Postconditions:
+//   eval out1 mod m = (eval arg1 * eval arg1) mod m
+//
+// Input Bounds:
+//   arg1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]]
+// Output Bounds:
+//   out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
+func p521CarrySquare(out1 *[9]uint64, arg1 *[9]uint64) {
+       x1 := arg1[8]
+       x2 := (x1 * 0x2)
+       x3 := (arg1[8] * 0x2)
+       x4 := arg1[7]
+       x5 := (x4 * 0x2)
+       x6 := (arg1[7] * 0x2)
+       x7 := arg1[6]
+       x8 := (x7 * 0x2)
+       x9 := (arg1[6] * 0x2)
+       x10 := arg1[5]
+       x11 := (x10 * 0x2)
+       x12 := (arg1[5] * 0x2)
+       x13 := (arg1[4] * 0x2)
+       x14 := (arg1[3] * 0x2)
+       x15 := (arg1[2] * 0x2)
+       x16 := (arg1[1] * 0x2)
+       var x17 uint64
+       var x18 uint64
+       x18, x17 = bits.Mul64(arg1[8], (x1 * 0x2))
+       var x19 uint64
+       var x20 uint64
+       x20, x19 = bits.Mul64(arg1[7], (x2 * 0x2))
+       var x21 uint64
+       var x22 uint64
+       x22, x21 = bits.Mul64(arg1[7], (x4 * 0x2))
+       var x23 uint64
+       var x24 uint64
+       x24, x23 = bits.Mul64(arg1[6], (x2 * 0x2))
+       var x25 uint64
+       var x26 uint64
+       x26, x25 = bits.Mul64(arg1[6], (x5 * 0x2))
+       var x27 uint64
+       var x28 uint64
+       x28, x27 = bits.Mul64(arg1[6], (x7 * 0x2))
+       var x29 uint64
+       var x30 uint64
+       x30, x29 = bits.Mul64(arg1[5], (x2 * 0x2))
+       var x31 uint64
+       var x32 uint64
+       x32, x31 = bits.Mul64(arg1[5], (x5 * 0x2))
+       var x33 uint64
+       var x34 uint64
+       x34, x33 = bits.Mul64(arg1[5], (x8 * 0x2))
+       var x35 uint64
+       var x36 uint64
+       x36, x35 = bits.Mul64(arg1[5], (x10 * 0x2))
+       var x37 uint64
+       var x38 uint64
+       x38, x37 = bits.Mul64(arg1[4], (x2 * 0x2))
+       var x39 uint64
+       var x40 uint64
+       x40, x39 = bits.Mul64(arg1[4], (x5 * 0x2))
+       var x41 uint64
+       var x42 uint64
+       x42, x41 = bits.Mul64(arg1[4], (x8 * 0x2))
+       var x43 uint64
+       var x44 uint64
+       x44, x43 = bits.Mul64(arg1[4], (x11 * 0x2))
+       var x45 uint64
+       var x46 uint64
+       x46, x45 = bits.Mul64(arg1[4], arg1[4])
+       var x47 uint64
+       var x48 uint64
+       x48, x47 = bits.Mul64(arg1[3], (x2 * 0x2))
+       var x49 uint64
+       var x50 uint64
+       x50, x49 = bits.Mul64(arg1[3], (x5 * 0x2))
+       var x51 uint64
+       var x52 uint64
+       x52, x51 = bits.Mul64(arg1[3], (x8 * 0x2))
+       var x53 uint64
+       var x54 uint64
+       x54, x53 = bits.Mul64(arg1[3], x12)
+       var x55 uint64
+       var x56 uint64
+       x56, x55 = bits.Mul64(arg1[3], x13)
+       var x57 uint64
+       var x58 uint64
+       x58, x57 = bits.Mul64(arg1[3], arg1[3])
+       var x59 uint64
+       var x60 uint64
+       x60, x59 = bits.Mul64(arg1[2], (x2 * 0x2))
+       var x61 uint64
+       var x62 uint64
+       x62, x61 = bits.Mul64(arg1[2], (x5 * 0x2))
+       var x63 uint64
+       var x64 uint64
+       x64, x63 = bits.Mul64(arg1[2], x9)
+       var x65 uint64
+       var x66 uint64
+       x66, x65 = bits.Mul64(arg1[2], x12)
+       var x67 uint64
+       var x68 uint64
+       x68, x67 = bits.Mul64(arg1[2], x13)
+       var x69 uint64
+       var x70 uint64
+       x70, x69 = bits.Mul64(arg1[2], x14)
+       var x71 uint64
+       var x72 uint64
+       x72, x71 = bits.Mul64(arg1[2], arg1[2])
+       var x73 uint64
+       var x74 uint64
+       x74, x73 = bits.Mul64(arg1[1], (x2 * 0x2))
+       var x75 uint64
+       var x76 uint64
+       x76, x75 = bits.Mul64(arg1[1], x6)
+       var x77 uint64
+       var x78 uint64
+       x78, x77 = bits.Mul64(arg1[1], x9)
+       var x79 uint64
+       var x80 uint64
+       x80, x79 = bits.Mul64(arg1[1], x12)
+       var x81 uint64
+       var x82 uint64
+       x82, x81 = bits.Mul64(arg1[1], x13)
+       var x83 uint64
+       var x84 uint64
+       x84, x83 = bits.Mul64(arg1[1], x14)
+       var x85 uint64
+       var x86 uint64
+       x86, x85 = bits.Mul64(arg1[1], x15)
+       var x87 uint64
+       var x88 uint64
+       x88, x87 = bits.Mul64(arg1[1], arg1[1])
+       var x89 uint64
+       var x90 uint64
+       x90, x89 = bits.Mul64(arg1[0], x3)
+       var x91 uint64
+       var x92 uint64
+       x92, x91 = bits.Mul64(arg1[0], x6)
+       var x93 uint64
+       var x94 uint64
+       x94, x93 = bits.Mul64(arg1[0], x9)
+       var x95 uint64
+       var x96 uint64
+       x96, x95 = bits.Mul64(arg1[0], x12)
+       var x97 uint64
+       var x98 uint64
+       x98, x97 = bits.Mul64(arg1[0], x13)
+       var x99 uint64
+       var x100 uint64
+       x100, x99 = bits.Mul64(arg1[0], x14)
+       var x101 uint64
+       var x102 uint64
+       x102, x101 = bits.Mul64(arg1[0], x15)
+       var x103 uint64
+       var x104 uint64
+       x104, x103 = bits.Mul64(arg1[0], x16)
+       var x105 uint64
+       var x106 uint64
+       x106, x105 = bits.Mul64(arg1[0], arg1[0])
+       var x107 uint64
+       var x108 p521Uint1
+       x107, x108 = p521AddcarryxU64(x51, x43, 0x0)
+       var x109 uint64
+       x109, _ = p521AddcarryxU64(x52, x44, x108)
+       var x111 uint64
+       var x112 p521Uint1
+       x111, x112 = p521AddcarryxU64(x61, x107, 0x0)
+       var x113 uint64
+       x113, _ = p521AddcarryxU64(x62, x109, x112)
+       var x115 uint64
+       var x116 p521Uint1
+       x115, x116 = p521AddcarryxU64(x73, x111, 0x0)
+       var x117 uint64
+       x117, _ = p521AddcarryxU64(x74, x113, x116)
+       var x119 uint64
+       var x120 p521Uint1
+       x119, x120 = p521AddcarryxU64(x105, x115, 0x0)
+       var x121 uint64
+       x121, _ = p521AddcarryxU64(x106, x117, x120)
+       x123 := ((x119 >> 58) | ((x121 << 6) & 0xffffffffffffffff))
+       x124 := (x121 >> 58)
+       x125 := (x119 & 0x3ffffffffffffff)
+       var x126 uint64
+       var x127 p521Uint1
+       x126, x127 = p521AddcarryxU64(x53, x45, 0x0)
+       var x128 uint64
+       x128, _ = p521AddcarryxU64(x54, x46, x127)
+       var x130 uint64
+       var x131 p521Uint1
+       x130, x131 = p521AddcarryxU64(x63, x126, 0x0)
+       var x132 uint64
+       x132, _ = p521AddcarryxU64(x64, x128, x131)
+       var x134 uint64
+       var x135 p521Uint1
+       x134, x135 = p521AddcarryxU64(x75, x130, 0x0)
+       var x136 uint64
+       x136, _ = p521AddcarryxU64(x76, x132, x135)
+       var x138 uint64
+       var x139 p521Uint1
+       x138, x139 = p521AddcarryxU64(x89, x134, 0x0)
+       var x140 uint64
+       x140, _ = p521AddcarryxU64(x90, x136, x139)
+       var x142 uint64
+       var x143 p521Uint1
+       x142, x143 = p521AddcarryxU64(x55, x17, 0x0)
+       var x144 uint64
+       x144, _ = p521AddcarryxU64(x56, x18, x143)
+       var x146 uint64
+       var x147 p521Uint1
+       x146, x147 = p521AddcarryxU64(x65, x142, 0x0)
+       var x148 uint64
+       x148, _ = p521AddcarryxU64(x66, x144, x147)
+       var x150 uint64
+       var x151 p521Uint1
+       x150, x151 = p521AddcarryxU64(x77, x146, 0x0)
+       var x152 uint64
+       x152, _ = p521AddcarryxU64(x78, x148, x151)
+       var x154 uint64
+       var x155 p521Uint1
+       x154, x155 = p521AddcarryxU64(x91, x150, 0x0)
+       var x156 uint64
+       x156, _ = p521AddcarryxU64(x92, x152, x155)
+       var x158 uint64
+       var x159 p521Uint1
+       x158, x159 = p521AddcarryxU64(x57, x19, 0x0)
+       var x160 uint64
+       x160, _ = p521AddcarryxU64(x58, x20, x159)
+       var x162 uint64
+       var x163 p521Uint1
+       x162, x163 = p521AddcarryxU64(x67, x158, 0x0)
+       var x164 uint64
+       x164, _ = p521AddcarryxU64(x68, x160, x163)
+       var x166 uint64
+       var x167 p521Uint1
+       x166, x167 = p521AddcarryxU64(x79, x162, 0x0)
+       var x168 uint64
+       x168, _ = p521AddcarryxU64(x80, x164, x167)
+       var x170 uint64
+       var x171 p521Uint1
+       x170, x171 = p521AddcarryxU64(x93, x166, 0x0)
+       var x172 uint64
+       x172, _ = p521AddcarryxU64(x94, x168, x171)
+       var x174 uint64
+       var x175 p521Uint1
+       x174, x175 = p521AddcarryxU64(x23, x21, 0x0)
+       var x176 uint64
+       x176, _ = p521AddcarryxU64(x24, x22, x175)
+       var x178 uint64
+       var x179 p521Uint1
+       x178, x179 = p521AddcarryxU64(x69, x174, 0x0)
+       var x180 uint64
+       x180, _ = p521AddcarryxU64(x70, x176, x179)
+       var x182 uint64
+       var x183 p521Uint1
+       x182, x183 = p521AddcarryxU64(x81, x178, 0x0)
+       var x184 uint64
+       x184, _ = p521AddcarryxU64(x82, x180, x183)
+       var x186 uint64
+       var x187 p521Uint1
+       x186, x187 = p521AddcarryxU64(x95, x182, 0x0)
+       var x188 uint64
+       x188, _ = p521AddcarryxU64(x96, x184, x187)
+       var x190 uint64
+       var x191 p521Uint1
+       x190, x191 = p521AddcarryxU64(x29, x25, 0x0)
+       var x192 uint64
+       x192, _ = p521AddcarryxU64(x30, x26, x191)
+       var x194 uint64
+       var x195 p521Uint1
+       x194, x195 = p521AddcarryxU64(x71, x190, 0x0)
+       var x196 uint64
+       x196, _ = p521AddcarryxU64(x72, x192, x195)
+       var x198 uint64
+       var x199 p521Uint1
+       x198, x199 = p521AddcarryxU64(x83, x194, 0x0)
+       var x200 uint64
+       x200, _ = p521AddcarryxU64(x84, x196, x199)
+       var x202 uint64
+       var x203 p521Uint1
+       x202, x203 = p521AddcarryxU64(x97, x198, 0x0)
+       var x204 uint64
+       x204, _ = p521AddcarryxU64(x98, x200, x203)
+       var x206 uint64
+       var x207 p521Uint1
+       x206, x207 = p521AddcarryxU64(x31, x27, 0x0)
+       var x208 uint64
+       x208, _ = p521AddcarryxU64(x32, x28, x207)
+       var x210 uint64
+       var x211 p521Uint1
+       x210, x211 = p521AddcarryxU64(x37, x206, 0x0)
+       var x212 uint64
+       x212, _ = p521AddcarryxU64(x38, x208, x211)
+       var x214 uint64
+       var x215 p521Uint1
+       x214, x215 = p521AddcarryxU64(x85, x210, 0x0)
+       var x216 uint64
+       x216, _ = p521AddcarryxU64(x86, x212, x215)
+       var x218 uint64
+       var x219 p521Uint1
+       x218, x219 = p521AddcarryxU64(x99, x214, 0x0)
+       var x220 uint64
+       x220, _ = p521AddcarryxU64(x100, x216, x219)
+       var x222 uint64
+       var x223 p521Uint1
+       x222, x223 = p521AddcarryxU64(x39, x33, 0x0)
+       var x224 uint64
+       x224, _ = p521AddcarryxU64(x40, x34, x223)
+       var x226 uint64
+       var x227 p521Uint1
+       x226, x227 = p521AddcarryxU64(x47, x222, 0x0)
+       var x228 uint64
+       x228, _ = p521AddcarryxU64(x48, x224, x227)
+       var x230 uint64
+       var x231 p521Uint1
+       x230, x231 = p521AddcarryxU64(x87, x226, 0x0)
+       var x232 uint64
+       x232, _ = p521AddcarryxU64(x88, x228, x231)
+       var x234 uint64
+       var x235 p521Uint1
+       x234, x235 = p521AddcarryxU64(x101, x230, 0x0)
+       var x236 uint64
+       x236, _ = p521AddcarryxU64(x102, x232, x235)
+       var x238 uint64
+       var x239 p521Uint1
+       x238, x239 = p521AddcarryxU64(x41, x35, 0x0)
+       var x240 uint64
+       x240, _ = p521AddcarryxU64(x42, x36, x239)
+       var x242 uint64
+       var x243 p521Uint1
+       x242, x243 = p521AddcarryxU64(x49, x238, 0x0)
+       var x244 uint64
+       x244, _ = p521AddcarryxU64(x50, x240, x243)
+       var x246 uint64
+       var x247 p521Uint1
+       x246, x247 = p521AddcarryxU64(x59, x242, 0x0)
+       var x248 uint64
+       x248, _ = p521AddcarryxU64(x60, x244, x247)
+       var x250 uint64
+       var x251 p521Uint1
+       x250, x251 = p521AddcarryxU64(x103, x246, 0x0)
+       var x252 uint64
+       x252, _ = p521AddcarryxU64(x104, x248, x251)
+       var x254 uint64
+       var x255 p521Uint1
+       x254, x255 = p521AddcarryxU64(x123, x250, 0x0)
+       var x256 uint64
+       x256, _ = p521AddcarryxU64(x124, x252, x255)
+       x258 := ((x254 >> 58) | ((x256 << 6) & 0xffffffffffffffff))
+       x259 := (x256 >> 58)
+       x260 := (x254 & 0x3ffffffffffffff)
+       var x261 uint64
+       var x262 p521Uint1
+       x261, x262 = p521AddcarryxU64(x258, x234, 0x0)
+       var x263 uint64
+       x263, _ = p521AddcarryxU64(x259, x236, x262)
+       x265 := ((x261 >> 58) | ((x263 << 6) & 0xffffffffffffffff))
+       x266 := (x263 >> 58)
+       x267 := (x261 & 0x3ffffffffffffff)
+       var x268 uint64
+       var x269 p521Uint1
+       x268, x269 = p521AddcarryxU64(x265, x218, 0x0)
+       var x270 uint64
+       x270, _ = p521AddcarryxU64(x266, x220, x269)
+       x272 := ((x268 >> 58) | ((x270 << 6) & 0xffffffffffffffff))
+       x273 := (x270 >> 58)
+       x274 := (x268 & 0x3ffffffffffffff)
+       var x275 uint64
+       var x276 p521Uint1
+       x275, x276 = p521AddcarryxU64(x272, x202, 0x0)
+       var x277 uint64
+       x277, _ = p521AddcarryxU64(x273, x204, x276)
+       x279 := ((x275 >> 58) | ((x277 << 6) & 0xffffffffffffffff))
+       x280 := (x277 >> 58)
+       x281 := (x275 & 0x3ffffffffffffff)
+       var x282 uint64
+       var x283 p521Uint1
+       x282, x283 = p521AddcarryxU64(x279, x186, 0x0)
+       var x284 uint64
+       x284, _ = p521AddcarryxU64(x280, x188, x283)
+       x286 := ((x282 >> 58) | ((x284 << 6) & 0xffffffffffffffff))
+       x287 := (x284 >> 58)
+       x288 := (x282 & 0x3ffffffffffffff)
+       var x289 uint64
+       var x290 p521Uint1
+       x289, x290 = p521AddcarryxU64(x286, x170, 0x0)
+       var x291 uint64
+       x291, _ = p521AddcarryxU64(x287, x172, x290)
+       x293 := ((x289 >> 58) | ((x291 << 6) & 0xffffffffffffffff))
+       x294 := (x291 >> 58)
+       x295 := (x289 & 0x3ffffffffffffff)
+       var x296 uint64
+       var x297 p521Uint1
+       x296, x297 = p521AddcarryxU64(x293, x154, 0x0)
+       var x298 uint64
+       x298, _ = p521AddcarryxU64(x294, x156, x297)
+       x300 := ((x296 >> 58) | ((x298 << 6) & 0xffffffffffffffff))
+       x301 := (x298 >> 58)
+       x302 := (x296 & 0x3ffffffffffffff)
+       var x303 uint64
+       var x304 p521Uint1
+       x303, x304 = p521AddcarryxU64(x300, x138, 0x0)
+       var x305 uint64
+       x305, _ = p521AddcarryxU64(x301, x140, x304)
+       x307 := ((x303 >> 57) | ((x305 << 7) & 0xffffffffffffffff))
+       x308 := (x305 >> 57)
+       x309 := (x303 & 0x1ffffffffffffff)
+       var x310 uint64
+       var x311 p521Uint1
+       x310, x311 = p521AddcarryxU64(x125, x307, 0x0)
+       x312 := (uint64(x311) + x308)
+       x313 := ((x310 >> 58) | ((x312 << 6) & 0xffffffffffffffff))
+       x314 := (x310 & 0x3ffffffffffffff)
+       x315 := (x313 + x260)
+       x316 := p521Uint1((x315 >> 58))
+       x317 := (x315 & 0x3ffffffffffffff)
+       x318 := (uint64(x316) + x267)
+       out1[0] = x314
+       out1[1] = x317
+       out1[2] = x318
+       out1[3] = x274
+       out1[4] = x281
+       out1[5] = x288
+       out1[6] = x295
+       out1[7] = x302
+       out1[8] = x309
+}
+
+// p521Carry reduces a field element.
+//
+// Postconditions:
+//   eval out1 mod m = eval arg1 mod m
+//
+// Input Bounds:
+//   arg1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]]
+// Output Bounds:
+//   out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
+func p521Carry(out1 *[9]uint64, arg1 *[9]uint64) {
+       x1 := arg1[0]
+       x2 := ((x1 >> 58) + arg1[1])
+       x3 := ((x2 >> 58) + arg1[2])
+       x4 := ((x3 >> 58) + arg1[3])
+       x5 := ((x4 >> 58) + arg1[4])
+       x6 := ((x5 >> 58) + arg1[5])
+       x7 := ((x6 >> 58) + arg1[6])
+       x8 := ((x7 >> 58) + arg1[7])
+       x9 := ((x8 >> 58) + arg1[8])
+       x10 := ((x1 & 0x3ffffffffffffff) + (x9 >> 57))
+       x11 := (uint64(p521Uint1((x10 >> 58))) + (x2 & 0x3ffffffffffffff))
+       x12 := (x10 & 0x3ffffffffffffff)
+       x13 := (x11 & 0x3ffffffffffffff)
+       x14 := (uint64(p521Uint1((x11 >> 58))) + (x3 & 0x3ffffffffffffff))
+       x15 := (x4 & 0x3ffffffffffffff)
+       x16 := (x5 & 0x3ffffffffffffff)
+       x17 := (x6 & 0x3ffffffffffffff)
+       x18 := (x7 & 0x3ffffffffffffff)
+       x19 := (x8 & 0x3ffffffffffffff)
+       x20 := (x9 & 0x1ffffffffffffff)
+       out1[0] = x12
+       out1[1] = x13
+       out1[2] = x14
+       out1[3] = x15
+       out1[4] = x16
+       out1[5] = x17
+       out1[6] = x18
+       out1[7] = x19
+       out1[8] = x20
+}
+
+// p521Add adds two field elements.
+//
+// Postconditions:
+//   eval out1 mod m = (eval arg1 + eval arg2) mod m
+//
+// Input Bounds:
+//   arg1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
+//   arg2: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
+// Output Bounds:
+//   out1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]]
+func p521Add(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) {
+       x1 := (arg1[0] + arg2[0])
+       x2 := (arg1[1] + arg2[1])
+       x3 := (arg1[2] + arg2[2])
+       x4 := (arg1[3] + arg2[3])
+       x5 := (arg1[4] + arg2[4])
+       x6 := (arg1[5] + arg2[5])
+       x7 := (arg1[6] + arg2[6])
+       x8 := (arg1[7] + arg2[7])
+       x9 := (arg1[8] + arg2[8])
+       out1[0] = x1
+       out1[1] = x2
+       out1[2] = x3
+       out1[3] = x4
+       out1[4] = x5
+       out1[5] = x6
+       out1[6] = x7
+       out1[7] = x8
+       out1[8] = x9
+}
+
+// p521Sub subtracts two field elements.
+//
+// Postconditions:
+//   eval out1 mod m = (eval arg1 - eval arg2) mod m
+//
+// Input Bounds:
+//   arg1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
+//   arg2: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
+// Output Bounds:
+//   out1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]]
+func p521Sub(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) {
+       x1 := ((0x7fffffffffffffe + arg1[0]) - arg2[0])
+       x2 := ((0x7fffffffffffffe + arg1[1]) - arg2[1])
+       x3 := ((0x7fffffffffffffe + arg1[2]) - arg2[2])
+       x4 := ((0x7fffffffffffffe + arg1[3]) - arg2[3])
+       x5 := ((0x7fffffffffffffe + arg1[4]) - arg2[4])
+       x6 := ((0x7fffffffffffffe + arg1[5]) - arg2[5])
+       x7 := ((0x7fffffffffffffe + arg1[6]) - arg2[6])
+       x8 := ((0x7fffffffffffffe + arg1[7]) - arg2[7])
+       x9 := ((0x3fffffffffffffe + arg1[8]) - arg2[8])
+       out1[0] = x1
+       out1[1] = x2
+       out1[2] = x3
+       out1[3] = x4
+       out1[4] = x5
+       out1[5] = x6
+       out1[6] = x7
+       out1[7] = x8
+       out1[8] = x9
+}
+
+// p521ToBytes serializes a field element to bytes in little-endian order.
+//
+// Postconditions:
+//   out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..65]
+//
+// Input Bounds:
+//   arg1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
+// Output Bounds:
+//   out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x1]]
+func p521ToBytes(out1 *[66]uint8, arg1 *[9]uint64) {
+       var x1 uint64
+       var x2 p521Uint1
+       p521SubborrowxU58(&x1, &x2, 0x0, arg1[0], 0x3ffffffffffffff)
+       var x3 uint64
+       var x4 p521Uint1
+       p521SubborrowxU58(&x3, &x4, x2, arg1[1], 0x3ffffffffffffff)
+       var x5 uint64
+       var x6 p521Uint1
+       p521SubborrowxU58(&x5, &x6, x4, arg1[2], 0x3ffffffffffffff)
+       var x7 uint64
+       var x8 p521Uint1
+       p521SubborrowxU58(&x7, &x8, x6, arg1[3], 0x3ffffffffffffff)
+       var x9 uint64
+       var x10 p521Uint1
+       p521SubborrowxU58(&x9, &x10, x8, arg1[4], 0x3ffffffffffffff)
+       var x11 uint64
+       var x12 p521Uint1
+       p521SubborrowxU58(&x11, &x12, x10, arg1[5], 0x3ffffffffffffff)
+       var x13 uint64
+       var x14 p521Uint1
+       p521SubborrowxU58(&x13, &x14, x12, arg1[6], 0x3ffffffffffffff)
+       var x15 uint64
+       var x16 p521Uint1
+       p521SubborrowxU58(&x15, &x16, x14, arg1[7], 0x3ffffffffffffff)
+       var x17 uint64
+       var x18 p521Uint1
+       p521SubborrowxU57(&x17, &x18, x16, arg1[8], 0x1ffffffffffffff)
+       var x19 uint64
+       p521CmovznzU64(&x19, x18, uint64(0x0), 0xffffffffffffffff)
+       var x20 uint64
+       var x21 p521Uint1
+       p521AddcarryxU58(&x20, &x21, 0x0, x1, (x19 & 0x3ffffffffffffff))
+       var x22 uint64
+       var x23 p521Uint1
+       p521AddcarryxU58(&x22, &x23, x21, x3, (x19 & 0x3ffffffffffffff))
+       var x24 uint64
+       var x25 p521Uint1
+       p521AddcarryxU58(&x24, &x25, x23, x5, (x19 & 0x3ffffffffffffff))
+       var x26 uint64
+       var x27 p521Uint1
+       p521AddcarryxU58(&x26, &x27, x25, x7, (x19 & 0x3ffffffffffffff))
+       var x28 uint64
+       var x29 p521Uint1
+       p521AddcarryxU58(&x28, &x29, x27, x9, (x19 & 0x3ffffffffffffff))
+       var x30 uint64
+       var x31 p521Uint1
+       p521AddcarryxU58(&x30, &x31, x29, x11, (x19 & 0x3ffffffffffffff))
+       var x32 uint64
+       var x33 p521Uint1
+       p521AddcarryxU58(&x32, &x33, x31, x13, (x19 & 0x3ffffffffffffff))
+       var x34 uint64
+       var x35 p521Uint1
+       p521AddcarryxU58(&x34, &x35, x33, x15, (x19 & 0x3ffffffffffffff))
+       var x36 uint64
+       var x37 p521Uint1
+       p521AddcarryxU57(&x36, &x37, x35, x17, (x19 & 0x1ffffffffffffff))
+       x38 := (x34 << 6)
+       x39 := (x32 << 4)
+       x40 := (x30 << 2)
+       x41 := (x26 << 6)
+       x42 := (x24 << 4)
+       x43 := (x22 << 2)
+       x44 := (uint8(x20) & 0xff)
+       x45 := (x20 >> 8)
+       x46 := (uint8(x45) & 0xff)
+       x47 := (x45 >> 8)
+       x48 := (uint8(x47) & 0xff)
+       x49 := (x47 >> 8)
+       x50 := (uint8(x49) & 0xff)
+       x51 := (x49 >> 8)
+       x52 := (uint8(x51) & 0xff)
+       x53 := (x51 >> 8)
+       x54 := (uint8(x53) & 0xff)
+       x55 := (x53 >> 8)
+       x56 := (uint8(x55) & 0xff)
+       x57 := uint8((x55 >> 8))
+       x58 := (x43 + uint64(x57))
+       x59 := (uint8(x58) & 0xff)
+       x60 := (x58 >> 8)
+       x61 := (uint8(x60) & 0xff)
+       x62 := (x60 >> 8)
+       x63 := (uint8(x62) & 0xff)
+       x64 := (x62 >> 8)
+       x65 := (uint8(x64) & 0xff)
+       x66 := (x64 >> 8)
+       x67 := (uint8(x66) & 0xff)
+       x68 := (x66 >> 8)
+       x69 := (uint8(x68) & 0xff)
+       x70 := (x68 >> 8)
+       x71 := (uint8(x70) & 0xff)
+       x72 := uint8((x70 >> 8))
+       x73 := (x42 + uint64(x72))
+       x74 := (uint8(x73) & 0xff)
+       x75 := (x73 >> 8)
+       x76 := (uint8(x75) & 0xff)
+       x77 := (x75 >> 8)
+       x78 := (uint8(x77) & 0xff)
+       x79 := (x77 >> 8)
+       x80 := (uint8(x79) & 0xff)
+       x81 := (x79 >> 8)
+       x82 := (uint8(x81) & 0xff)
+       x83 := (x81 >> 8)
+       x84 := (uint8(x83) & 0xff)
+       x85 := (x83 >> 8)
+       x86 := (uint8(x85) & 0xff)
+       x87 := uint8((x85 >> 8))
+       x88 := (x41 + uint64(x87))
+       x89 := (uint8(x88) & 0xff)
+       x90 := (x88 >> 8)
+       x91 := (uint8(x90) & 0xff)
+       x92 := (x90 >> 8)
+       x93 := (uint8(x92) & 0xff)
+       x94 := (x92 >> 8)
+       x95 := (uint8(x94) & 0xff)
+       x96 := (x94 >> 8)
+       x97 := (uint8(x96) & 0xff)
+       x98 := (x96 >> 8)
+       x99 := (uint8(x98) & 0xff)
+       x100 := (x98 >> 8)
+       x101 := (uint8(x100) & 0xff)
+       x102 := uint8((x100 >> 8))
+       x103 := (uint8(x28) & 0xff)
+       x104 := (x28 >> 8)
+       x105 := (uint8(x104) & 0xff)
+       x106 := (x104 >> 8)
+       x107 := (uint8(x106) & 0xff)
+       x108 := (x106 >> 8)
+       x109 := (uint8(x108) & 0xff)
+       x110 := (x108 >> 8)
+       x111 := (uint8(x110) & 0xff)
+       x112 := (x110 >> 8)
+       x113 := (uint8(x112) & 0xff)
+       x114 := (x112 >> 8)
+       x115 := (uint8(x114) & 0xff)
+       x116 := uint8((x114 >> 8))
+       x117 := (x40 + uint64(x116))
+       x118 := (uint8(x117) & 0xff)
+       x119 := (x117 >> 8)
+       x120 := (uint8(x119) & 0xff)
+       x121 := (x119 >> 8)
+       x122 := (uint8(x121) & 0xff)
+       x123 := (x121 >> 8)
+       x124 := (uint8(x123) & 0xff)
+       x125 := (x123 >> 8)
+       x126 := (uint8(x125) & 0xff)
+       x127 := (x125 >> 8)
+       x128 := (uint8(x127) & 0xff)
+       x129 := (x127 >> 8)
+       x130 := (uint8(x129) & 0xff)
+       x131 := uint8((x129 >> 8))
+       x132 := (x39 + uint64(x131))
+       x133 := (uint8(x132) & 0xff)
+       x134 := (x132 >> 8)
+       x135 := (uint8(x134) & 0xff)
+       x136 := (x134 >> 8)
+       x137 := (uint8(x136) & 0xff)
+       x138 := (x136 >> 8)
+       x139 := (uint8(x138) & 0xff)
+       x140 := (x138 >> 8)
+       x141 := (uint8(x140) & 0xff)
+       x142 := (x140 >> 8)
+       x143 := (uint8(x142) & 0xff)
+       x144 := (x142 >> 8)
+       x145 := (uint8(x144) & 0xff)
+       x146 := uint8((x144 >> 8))
+       x147 := (x38 + uint64(x146))
+       x148 := (uint8(x147) & 0xff)
+       x149 := (x147 >> 8)
+       x150 := (uint8(x149) & 0xff)
+       x151 := (x149 >> 8)
+       x152 := (uint8(x151) & 0xff)
+       x153 := (x151 >> 8)
+       x154 := (uint8(x153) & 0xff)
+       x155 := (x153 >> 8)
+       x156 := (uint8(x155) & 0xff)
+       x157 := (x155 >> 8)
+       x158 := (uint8(x157) & 0xff)
+       x159 := (x157 >> 8)
+       x160 := (uint8(x159) & 0xff)
+       x161 := uint8((x159 >> 8))
+       x162 := (uint8(x36) & 0xff)
+       x163 := (x36 >> 8)
+       x164 := (uint8(x163) & 0xff)
+       x165 := (x163 >> 8)
+       x166 := (uint8(x165) & 0xff)
+       x167 := (x165 >> 8)
+       x168 := (uint8(x167) & 0xff)
+       x169 := (x167 >> 8)
+       x170 := (uint8(x169) & 0xff)
+       x171 := (x169 >> 8)
+       x172 := (uint8(x171) & 0xff)
+       x173 := (x171 >> 8)
+       x174 := (uint8(x173) & 0xff)
+       x175 := p521Uint1((x173 >> 8))
+       out1[0] = x44
+       out1[1] = x46
+       out1[2] = x48
+       out1[3] = x50
+       out1[4] = x52
+       out1[5] = x54
+       out1[6] = x56
+       out1[7] = x59
+       out1[8] = x61
+       out1[9] = x63
+       out1[10] = x65
+       out1[11] = x67
+       out1[12] = x69
+       out1[13] = x71
+       out1[14] = x74
+       out1[15] = x76
+       out1[16] = x78
+       out1[17] = x80
+       out1[18] = x82
+       out1[19] = x84
+       out1[20] = x86
+       out1[21] = x89
+       out1[22] = x91
+       out1[23] = x93
+       out1[24] = x95
+       out1[25] = x97
+       out1[26] = x99
+       out1[27] = x101
+       out1[28] = x102
+       out1[29] = x103
+       out1[30] = x105
+       out1[31] = x107
+       out1[32] = x109
+       out1[33] = x111
+       out1[34] = x113
+       out1[35] = x115
+       out1[36] = x118
+       out1[37] = x120
+       out1[38] = x122
+       out1[39] = x124
+       out1[40] = x126
+       out1[41] = x128
+       out1[42] = x130
+       out1[43] = x133
+       out1[44] = x135
+       out1[45] = x137
+       out1[46] = x139
+       out1[47] = x141
+       out1[48] = x143
+       out1[49] = x145
+       out1[50] = x148
+       out1[51] = x150
+       out1[52] = x152
+       out1[53] = x154
+       out1[54] = x156
+       out1[55] = x158
+       out1[56] = x160
+       out1[57] = x161
+       out1[58] = x162
+       out1[59] = x164
+       out1[60] = x166
+       out1[61] = x168
+       out1[62] = x170
+       out1[63] = x172
+       out1[64] = x174
+       out1[65] = uint8(x175)
+}
+
+// p521FromBytes deserializes a field element from bytes in little-endian order.
+//
+// Postconditions:
+//   eval out1 mod m = bytes_eval arg1 mod m
+//
+// Input Bounds:
+//   arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x1]]
+// Output Bounds:
+//   out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
+func p521FromBytes(out1 *[9]uint64, arg1 *[66]uint8) {
+       x1 := (uint64(p521Uint1(arg1[65])) << 56)
+       x2 := (uint64(arg1[64]) << 48)
+       x3 := (uint64(arg1[63]) << 40)
+       x4 := (uint64(arg1[62]) << 32)
+       x5 := (uint64(arg1[61]) << 24)
+       x6 := (uint64(arg1[60]) << 16)
+       x7 := (uint64(arg1[59]) << 8)
+       x8 := arg1[58]
+       x9 := (uint64(arg1[57]) << 50)
+       x10 := (uint64(arg1[56]) << 42)
+       x11 := (uint64(arg1[55]) << 34)
+       x12 := (uint64(arg1[54]) << 26)
+       x13 := (uint64(arg1[53]) << 18)
+       x14 := (uint64(arg1[52]) << 10)
+       x15 := (uint64(arg1[51]) << 2)
+       x16 := (uint64(arg1[50]) << 52)
+       x17 := (uint64(arg1[49]) << 44)
+       x18 := (uint64(arg1[48]) << 36)
+       x19 := (uint64(arg1[47]) << 28)
+       x20 := (uint64(arg1[46]) << 20)
+       x21 := (uint64(arg1[45]) << 12)
+       x22 := (uint64(arg1[44]) << 4)
+       x23 := (uint64(arg1[43]) << 54)
+       x24 := (uint64(arg1[42]) << 46)
+       x25 := (uint64(arg1[41]) << 38)
+       x26 := (uint64(arg1[40]) << 30)
+       x27 := (uint64(arg1[39]) << 22)
+       x28 := (uint64(arg1[38]) << 14)
+       x29 := (uint64(arg1[37]) << 6)
+       x30 := (uint64(arg1[36]) << 56)
+       x31 := (uint64(arg1[35]) << 48)
+       x32 := (uint64(arg1[34]) << 40)
+       x33 := (uint64(arg1[33]) << 32)
+       x34 := (uint64(arg1[32]) << 24)
+       x35 := (uint64(arg1[31]) << 16)
+       x36 := (uint64(arg1[30]) << 8)
+       x37 := arg1[29]
+       x38 := (uint64(arg1[28]) << 50)
+       x39 := (uint64(arg1[27]) << 42)
+       x40 := (uint64(arg1[26]) << 34)
+       x41 := (uint64(arg1[25]) << 26)
+       x42 := (uint64(arg1[24]) << 18)
+       x43 := (uint64(arg1[23]) << 10)
+       x44 := (uint64(arg1[22]) << 2)
+       x45 := (uint64(arg1[21]) << 52)
+       x46 := (uint64(arg1[20]) << 44)
+       x47 := (uint64(arg1[19]) << 36)
+       x48 := (uint64(arg1[18]) << 28)
+       x49 := (uint64(arg1[17]) << 20)
+       x50 := (uint64(arg1[16]) << 12)
+       x51 := (uint64(arg1[15]) << 4)
+       x52 := (uint64(arg1[14]) << 54)
+       x53 := (uint64(arg1[13]) << 46)
+       x54 := (uint64(arg1[12]) << 38)
+       x55 := (uint64(arg1[11]) << 30)
+       x56 := (uint64(arg1[10]) << 22)
+       x57 := (uint64(arg1[9]) << 14)
+       x58 := (uint64(arg1[8]) << 6)
+       x59 := (uint64(arg1[7]) << 56)
+       x60 := (uint64(arg1[6]) << 48)
+       x61 := (uint64(arg1[5]) << 40)
+       x62 := (uint64(arg1[4]) << 32)
+       x63 := (uint64(arg1[3]) << 24)
+       x64 := (uint64(arg1[2]) << 16)
+       x65 := (uint64(arg1[1]) << 8)
+       x66 := arg1[0]
+       x67 := (x65 + uint64(x66))
+       x68 := (x64 + x67)
+       x69 := (x63 + x68)
+       x70 := (x62 + x69)
+       x71 := (x61 + x70)
+       x72 := (x60 + x71)
+       x73 := (x59 + x72)
+       x74 := (x73 & 0x3ffffffffffffff)
+       x75 := uint8((x73 >> 58))
+       x76 := (x58 + uint64(x75))
+       x77 := (x57 + x76)
+       x78 := (x56 + x77)
+       x79 := (x55 + x78)
+       x80 := (x54 + x79)
+       x81 := (x53 + x80)
+       x82 := (x52 + x81)
+       x83 := (x82 & 0x3ffffffffffffff)
+       x84 := uint8((x82 >> 58))
+       x85 := (x51 + uint64(x84))
+       x86 := (x50 + x85)
+       x87 := (x49 + x86)
+       x88 := (x48 + x87)
+       x89 := (x47 + x88)
+       x90 := (x46 + x89)
+       x91 := (x45 + x90)
+       x92 := (x91 & 0x3ffffffffffffff)
+       x93 := uint8((x91 >> 58))
+       x94 := (x44 + uint64(x93))
+       x95 := (x43 + x94)
+       x96 := (x42 + x95)
+       x97 := (x41 + x96)
+       x98 := (x40 + x97)
+       x99 := (x39 + x98)
+       x100 := (x38 + x99)
+       x101 := (x36 + uint64(x37))
+       x102 := (x35 + x101)
+       x103 := (x34 + x102)
+       x104 := (x33 + x103)
+       x105 := (x32 + x104)
+       x106 := (x31 + x105)
+       x107 := (x30 + x106)
+       x108 := (x107 & 0x3ffffffffffffff)
+       x109 := uint8((x107 >> 58))
+       x110 := (x29 + uint64(x109))
+       x111 := (x28 + x110)
+       x112 := (x27 + x111)
+       x113 := (x26 + x112)
+       x114 := (x25 + x113)
+       x115 := (x24 + x114)
+       x116 := (x23 + x115)
+       x117 := (x116 & 0x3ffffffffffffff)
+       x118 := uint8((x116 >> 58))
+       x119 := (x22 + uint64(x118))
+       x120 := (x21 + x119)
+       x121 := (x20 + x120)
+       x122 := (x19 + x121)
+       x123 := (x18 + x122)
+       x124 := (x17 + x123)
+       x125 := (x16 + x124)
+       x126 := (x125 & 0x3ffffffffffffff)
+       x127 := uint8((x125 >> 58))
+       x128 := (x15 + uint64(x127))
+       x129 := (x14 + x128)
+       x130 := (x13 + x129)
+       x131 := (x12 + x130)
+       x132 := (x11 + x131)
+       x133 := (x10 + x132)
+       x134 := (x9 + x133)
+       x135 := (x7 + uint64(x8))
+       x136 := (x6 + x135)
+       x137 := (x5 + x136)
+       x138 := (x4 + x137)
+       x139 := (x3 + x138)
+       x140 := (x2 + x139)
+       x141 := (x1 + x140)
+       out1[0] = x74
+       out1[1] = x83
+       out1[2] = x92
+       out1[3] = x100
+       out1[4] = x108
+       out1[5] = x117
+       out1[6] = x126
+       out1[7] = x134
+       out1[8] = x141
+}
+
+// p521Selectznz is a multi-limb conditional select.
+//
+// Postconditions:
+//   eval out1 = (if arg1 = 0 then eval arg2 else eval arg3)
+//
+// Input Bounds:
+//   arg1: [0x0 ~> 0x1]
+//   arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+//   arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+// Output Bounds:
+//   out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+func p521Selectznz(out1 *[9]uint64, arg1 p521Uint1, arg2 *[9]uint64, arg3 *[9]uint64) {
+       var x1 uint64
+       p521CmovznzU64(&x1, arg1, arg2[0], arg3[0])
+       var x2 uint64
+       p521CmovznzU64(&x2, arg1, arg2[1], arg3[1])
+       var x3 uint64
+       p521CmovznzU64(&x3, arg1, arg2[2], arg3[2])
+       var x4 uint64
+       p521CmovznzU64(&x4, arg1, arg2[3], arg3[3])
+       var x5 uint64
+       p521CmovznzU64(&x5, arg1, arg2[4], arg3[4])
+       var x6 uint64
+       p521CmovznzU64(&x6, arg1, arg2[5], arg3[5])
+       var x7 uint64
+       p521CmovznzU64(&x7, arg1, arg2[6], arg3[6])
+       var x8 uint64
+       p521CmovznzU64(&x8, arg1, arg2[7], arg3[7])
+       var x9 uint64
+       p521CmovznzU64(&x9, arg1, arg2[8], arg3[8])
+       out1[0] = x1
+       out1[1] = x2
+       out1[2] = x3
+       out1[3] = x4
+       out1[4] = x5
+       out1[5] = x6
+       out1[6] = x7
+       out1[7] = x8
+       out1[8] = x9
+}
diff --git a/libgo/go/crypto/elliptic/internal/fiat/p521_test.go b/libgo/go/crypto/elliptic/internal/fiat/p521_test.go
new file mode 100644 (file)
index 0000000..661bde3
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package fiat_test
+
+import (
+       "crypto/elliptic/internal/fiat"
+       "crypto/rand"
+       "testing"
+)
+
+func p521Random(t *testing.T) *fiat.P521Element {
+       buf := make([]byte, 66)
+       if _, err := rand.Read(buf); err != nil {
+               t.Fatal(err)
+       }
+       buf[65] &= 1
+       e, err := new(fiat.P521Element).SetBytes(buf)
+       if err != nil {
+               t.Fatal(err)
+       }
+       return e
+}
+
+func TestP521Invert(t *testing.T) {
+       a := p521Random(t)
+       inv := new(fiat.P521Element).Invert(a)
+       one := new(fiat.P521Element).Mul(a, inv)
+       if new(fiat.P521Element).One().Equal(one) != 1 {
+               t.Errorf("a * 1/a != 1; got %x for %x", one.Bytes(), a.Bytes())
+       }
+       inv.Invert(new(fiat.P521Element))
+       if new(fiat.P521Element).Equal(inv) != 1 {
+               t.Errorf("1/0 != 0; got %x", inv.Bytes())
+       }
+}
index c3141b6ab4de0b00ec7382cff55b2d47b8ab1d0d..b213b273d23d887b5c6e6d888e29872022d45f3c 100644 (file)
@@ -5,6 +5,8 @@
 package elliptic
 
 import (
+       "encoding/hex"
+       "fmt"
        "math/big"
        "math/bits"
        "math/rand"
@@ -312,3 +314,316 @@ func TestP224Invert(t *testing.T) {
                t.Errorf("p224Invert(a) * a = %x, expected 1", out)
        }
 }
+
+type baseMultTest struct {
+       k    string
+       x, y string
+}
+
+var p224BaseMultTests = []baseMultTest{
+       {
+               "1",
+               "b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
+               "bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34",
+       },
+       {
+               "2",
+               "706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6",
+               "1c2b76a7bc25e7702a704fa986892849fca629487acf3709d2e4e8bb",
+       },
+       {
+               "3",
+               "df1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04",
+               "a3f7f03cadd0be444c0aa56830130ddf77d317344e1af3591981a925",
+       },
+       {
+               "4",
+               "ae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301",
+               "482580a0ec5bc47e88bc8c378632cd196cb3fa058a7114eb03054c9",
+       },
+       {
+               "5",
+               "31c49ae75bce7807cdff22055d94ee9021fedbb5ab51c57526f011aa",
+               "27e8bff1745635ec5ba0c9f1c2ede15414c6507d29ffe37e790a079b",
+       },
+       {
+               "6",
+               "1f2483f82572251fca975fea40db821df8ad82a3c002ee6c57112408",
+               "89faf0ccb750d99b553c574fad7ecfb0438586eb3952af5b4b153c7e",
+       },
+       {
+               "7",
+               "db2f6be630e246a5cf7d99b85194b123d487e2d466b94b24a03c3e28",
+               "f3a30085497f2f611ee2517b163ef8c53b715d18bb4e4808d02b963",
+       },
+       {
+               "8",
+               "858e6f9cc6c12c31f5df124aa77767b05c8bc021bd683d2b55571550",
+               "46dcd3ea5c43898c5c5fc4fdac7db39c2f02ebee4e3541d1e78047a",
+       },
+       {
+               "9",
+               "2fdcccfee720a77ef6cb3bfbb447f9383117e3daa4a07e36ed15f78d",
+               "371732e4f41bf4f7883035e6a79fcedc0e196eb07b48171697517463",
+       },
+       {
+               "10",
+               "aea9e17a306517eb89152aa7096d2c381ec813c51aa880e7bee2c0fd",
+               "39bb30eab337e0a521b6cba1abe4b2b3a3e524c14a3fe3eb116b655f",
+       },
+       {
+               "11",
+               "ef53b6294aca431f0f3c22dc82eb9050324f1d88d377e716448e507c",
+               "20b510004092e96636cfb7e32efded8265c266dfb754fa6d6491a6da",
+       },
+       {
+               "12",
+               "6e31ee1dc137f81b056752e4deab1443a481033e9b4c93a3044f4f7a",
+               "207dddf0385bfdeab6e9acda8da06b3bbef224a93ab1e9e036109d13",
+       },
+       {
+               "13",
+               "34e8e17a430e43289793c383fac9774247b40e9ebd3366981fcfaeca",
+               "252819f71c7fb7fbcb159be337d37d3336d7feb963724fdfb0ecb767",
+       },
+       {
+               "14",
+               "a53640c83dc208603ded83e4ecf758f24c357d7cf48088b2ce01e9fa",
+               "d5814cd724199c4a5b974a43685fbf5b8bac69459c9469bc8f23ccaf",
+       },
+       {
+               "15",
+               "baa4d8635511a7d288aebeedd12ce529ff102c91f97f867e21916bf9",
+               "979a5f4759f80f4fb4ec2e34f5566d595680a11735e7b61046127989",
+       },
+       {
+               "16",
+               "b6ec4fe1777382404ef679997ba8d1cc5cd8e85349259f590c4c66d",
+               "3399d464345906b11b00e363ef429221f2ec720d2f665d7dead5b482",
+       },
+       {
+               "17",
+               "b8357c3a6ceef288310e17b8bfeff9200846ca8c1942497c484403bc",
+               "ff149efa6606a6bd20ef7d1b06bd92f6904639dce5174db6cc554a26",
+       },
+       {
+               "18",
+               "c9ff61b040874c0568479216824a15eab1a838a797d189746226e4cc",
+               "ea98d60e5ffc9b8fcf999fab1df7e7ef7084f20ddb61bb045a6ce002",
+       },
+       {
+               "19",
+               "a1e81c04f30ce201c7c9ace785ed44cc33b455a022f2acdbc6cae83c",
+               "dcf1f6c3db09c70acc25391d492fe25b4a180babd6cea356c04719cd",
+       },
+       {
+               "20",
+               "fcc7f2b45df1cd5a3c0c0731ca47a8af75cfb0347e8354eefe782455",
+               "d5d7110274cba7cdee90e1a8b0d394c376a5573db6be0bf2747f530",
+       },
+       {
+               "112233445566778899",
+               "61f077c6f62ed802dad7c2f38f5c67f2cc453601e61bd076bb46179e",
+               "2272f9e9f5933e70388ee652513443b5e289dd135dcc0d0299b225e4",
+       },
+       {
+               "112233445566778899112233445566778899",
+               "29895f0af496bfc62b6ef8d8a65c88c613949b03668aab4f0429e35",
+               "3ea6e53f9a841f2019ec24bde1a75677aa9b5902e61081c01064de93",
+       },
+       {
+               "6950511619965839450988900688150712778015737983940691968051900319680",
+               "ab689930bcae4a4aa5f5cb085e823e8ae30fd365eb1da4aba9cf0379",
+               "3345a121bbd233548af0d210654eb40bab788a03666419be6fbd34e7",
+       },
+       {
+               "13479972933410060327035789020509431695094902435494295338570602119423",
+               "bdb6a8817c1f89da1c2f3dd8e97feb4494f2ed302a4ce2bc7f5f4025",
+               "4c7020d57c00411889462d77a5438bb4e97d177700bf7243a07f1680",
+       },
+       {
+               "13479971751745682581351455311314208093898607229429740618390390702079",
+               "d58b61aa41c32dd5eba462647dba75c5d67c83606c0af2bd928446a9",
+               "d24ba6a837be0460dd107ae77725696d211446c5609b4595976b16bd",
+       },
+       {
+               "13479972931865328106486971546324465392952975980343228160962702868479",
+               "dc9fa77978a005510980e929a1485f63716df695d7a0c18bb518df03",
+               "ede2b016f2ddffc2a8c015b134928275ce09e5661b7ab14ce0d1d403",
+       },
+       {
+               "11795773708834916026404142434151065506931607341523388140225443265536",
+               "499d8b2829cfb879c901f7d85d357045edab55028824d0f05ba279ba",
+               "bf929537b06e4015919639d94f57838fa33fc3d952598dcdbb44d638",
+       },
+       {
+               "784254593043826236572847595991346435467177662189391577090",
+               "8246c999137186632c5f9eddf3b1b0e1764c5e8bd0e0d8a554b9cb77",
+               "e80ed8660bc1cb17ac7d845be40a7a022d3306f116ae9f81fea65947",
+       },
+       {
+               "13479767645505654746623887797783387853576174193480695826442858012671",
+               "6670c20afcceaea672c97f75e2e9dd5c8460e54bb38538ebb4bd30eb",
+               "f280d8008d07a4caf54271f993527d46ff3ff46fd1190a3f1faa4f74",
+       },
+       {
+               "205688069665150753842126177372015544874550518966168735589597183",
+               "eca934247425cfd949b795cb5ce1eff401550386e28d1a4c5a8eb",
+               "d4c01040dba19628931bc8855370317c722cbd9ca6156985f1c2e9ce",
+       },
+       {
+               "13479966930919337728895168462090683249159702977113823384618282123295",
+               "ef353bf5c73cd551b96d596fbc9a67f16d61dd9fe56af19de1fba9cd",
+               "21771b9cdce3e8430c09b3838be70b48c21e15bc09ee1f2d7945b91f",
+       },
+       {
+               "50210731791415612487756441341851895584393717453129007497216",
+               "4036052a3091eb481046ad3289c95d3ac905ca0023de2c03ecd451cf",
+               "d768165a38a2b96f812586a9d59d4136035d9c853a5bf2e1c86a4993",
+       },
+       {
+               "26959946667150639794667015087019625940457807714424391721682722368041",
+               "fcc7f2b45df1cd5a3c0c0731ca47a8af75cfb0347e8354eefe782455",
+               "f2a28eefd8b345832116f1e574f2c6b2c895aa8c24941f40d8b80ad1",
+       },
+       {
+               "26959946667150639794667015087019625940457807714424391721682722368042",
+               "a1e81c04f30ce201c7c9ace785ed44cc33b455a022f2acdbc6cae83c",
+               "230e093c24f638f533dac6e2b6d01da3b5e7f45429315ca93fb8e634",
+       },
+       {
+               "26959946667150639794667015087019625940457807714424391721682722368043",
+               "c9ff61b040874c0568479216824a15eab1a838a797d189746226e4cc",
+               "156729f1a003647030666054e208180f8f7b0df2249e44fba5931fff",
+       },
+       {
+               "26959946667150639794667015087019625940457807714424391721682722368044",
+               "b8357c3a6ceef288310e17b8bfeff9200846ca8c1942497c484403bc",
+               "eb610599f95942df1082e4f9426d086fb9c6231ae8b24933aab5db",
+       },
+       {
+               "26959946667150639794667015087019625940457807714424391721682722368045",
+               "b6ec4fe1777382404ef679997ba8d1cc5cd8e85349259f590c4c66d",
+               "cc662b9bcba6f94ee4ff1c9c10bd6ddd0d138df2d099a282152a4b7f",
+       },
+       {
+               "26959946667150639794667015087019625940457807714424391721682722368046",
+               "baa4d8635511a7d288aebeedd12ce529ff102c91f97f867e21916bf9",
+               "6865a0b8a607f0b04b13d1cb0aa992a5a97f5ee8ca1849efb9ed8678",
+       },
+       {
+               "26959946667150639794667015087019625940457807714424391721682722368047",
+               "a53640c83dc208603ded83e4ecf758f24c357d7cf48088b2ce01e9fa",
+               "2a7eb328dbe663b5a468b5bc97a040a3745396ba636b964370dc3352",
+       },
+       {
+               "26959946667150639794667015087019625940457807714424391721682722368048",
+               "34e8e17a430e43289793c383fac9774247b40e9ebd3366981fcfaeca",
+               "dad7e608e380480434ea641cc82c82cbc92801469c8db0204f13489a",
+       },
+       {
+               "26959946667150639794667015087019625940457807714424391721682722368049",
+               "6e31ee1dc137f81b056752e4deab1443a481033e9b4c93a3044f4f7a",
+               "df82220fc7a4021549165325725f94c3410ddb56c54e161fc9ef62ee",
+       },
+       {
+               "26959946667150639794667015087019625940457807714424391721682722368050",
+               "ef53b6294aca431f0f3c22dc82eb9050324f1d88d377e716448e507c",
+               "df4aefffbf6d1699c930481cd102127c9a3d992048ab05929b6e5927",
+       },
+       {
+               "26959946667150639794667015087019625940457807714424391721682722368051",
+               "aea9e17a306517eb89152aa7096d2c381ec813c51aa880e7bee2c0fd",
+               "c644cf154cc81f5ade49345e541b4d4b5c1adb3eb5c01c14ee949aa2",
+       },
+       {
+               "26959946667150639794667015087019625940457807714424391721682722368052",
+               "2fdcccfee720a77ef6cb3bfbb447f9383117e3daa4a07e36ed15f78d",
+               "c8e8cd1b0be40b0877cfca1958603122f1e6914f84b7e8e968ae8b9e",
+       },
+       {
+               "26959946667150639794667015087019625940457807714424391721682722368053",
+               "858e6f9cc6c12c31f5df124aa77767b05c8bc021bd683d2b55571550",
+               "fb9232c15a3bc7673a3a03b0253824c53d0fd1411b1cabe2e187fb87",
+       },
+       {
+               "26959946667150639794667015087019625940457807714424391721682722368054",
+               "db2f6be630e246a5cf7d99b85194b123d487e2d466b94b24a03c3e28",
+               "f0c5cff7ab680d09ee11dae84e9c1072ac48ea2e744b1b7f72fd469e",
+       },
+       {
+               "26959946667150639794667015087019625940457807714424391721682722368055",
+               "1f2483f82572251fca975fea40db821df8ad82a3c002ee6c57112408",
+               "76050f3348af2664aac3a8b05281304ebc7a7914c6ad50a4b4eac383",
+       },
+       {
+               "26959946667150639794667015087019625940457807714424391721682722368056",
+               "31c49ae75bce7807cdff22055d94ee9021fedbb5ab51c57526f011aa",
+               "d817400e8ba9ca13a45f360e3d121eaaeb39af82d6001c8186f5f866",
+       },
+       {
+               "26959946667150639794667015087019625940457807714424391721682722368057",
+               "ae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301",
+               "fb7da7f5f13a43b81774373c879cd32d6934c05fa758eeb14fcfab38",
+       },
+       {
+               "26959946667150639794667015087019625940457807714424391721682722368058",
+               "df1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04",
+               "5c080fc3522f41bbb3f55a97cfecf21f882ce8cbb1e50ca6e67e56dc",
+       },
+       {
+               "26959946667150639794667015087019625940457807714424391721682722368059",
+               "706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6",
+               "e3d4895843da188fd58fb0567976d7b50359d6b78530c8f62d1b1746",
+       },
+       {
+               "26959946667150639794667015087019625940457807714424391721682722368060",
+               "b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
+               "42c89c774a08dc04b3dd201932bc8a5ea5f8b89bbb2a7e667aff81cd",
+       },
+}
+
+func TestP224BaseMult(t *testing.T) {
+       p224 := P224()
+       for i, e := range p224BaseMultTests {
+               k, ok := new(big.Int).SetString(e.k, 10)
+               if !ok {
+                       t.Errorf("%d: bad value for k: %s", i, e.k)
+               }
+               x, y := p224.ScalarBaseMult(k.Bytes())
+               if fmt.Sprintf("%x", x) != e.x || fmt.Sprintf("%x", y) != e.y {
+                       t.Errorf("%d: bad output for k=%s: got (%x, %x), want (%s, %s)", i, e.k, x, y, e.x, e.y)
+               }
+               if testing.Short() && i > 5 {
+                       break
+               }
+       }
+}
+
+func TestP224GenericBaseMult(t *testing.T) {
+       // We use the P224 CurveParams directly in order to test the generic implementation.
+       p224 := P224().Params()
+       for i, e := range p224BaseMultTests {
+               k, ok := new(big.Int).SetString(e.k, 10)
+               if !ok {
+                       t.Errorf("%d: bad value for k: %s", i, e.k)
+               }
+               x, y := p224.ScalarBaseMult(k.Bytes())
+               if fmt.Sprintf("%x", x) != e.x || fmt.Sprintf("%x", y) != e.y {
+                       t.Errorf("%d: bad output for k=%s: got (%x, %x), want (%s, %s)", i, e.k, x, y, e.x, e.y)
+               }
+               if testing.Short() && i > 5 {
+                       break
+               }
+       }
+}
+
+func TestP224Overflow(t *testing.T) {
+       // This tests for a specific bug in the P224 implementation.
+       p224 := P224()
+       pointData, _ := hex.DecodeString("049B535B45FB0A2072398A6831834624C7E32CCFD5A4B933BCEAF77F1DD945E08BBE5178F5EDF5E733388F196D2A631D2E075BB16CBFEEA15B")
+       x, y := Unmarshal(p224, pointData)
+       if !p224.IsOnCurve(x, y) {
+               t.Error("P224 failed to validate a correct point")
+       }
+}
index 3ad8e729926b8a5bb893545a37f1f8ff4752e006..b05febd5ba980c7bc321a06b98f2a6e560f39b22 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//-go:build !amd64 && !arm64
 // -build !amd64,!arm64
 
 package elliptic
@@ -326,7 +327,7 @@ func p256ReduceDegree(out *[p256Limbs]uint32, tmp [17]uint64) {
        var tmp2 [18]uint32
        var carry, x, xMask uint32
 
-       // tmp contains 64-bit words with the same 29,28,29-bit positions as an
+       // tmp contains 64-bit words with the same 29,28,29-bit positions as a
        // field element. So the top of an element of tmp might overlap with
        // another element two positions down. The following loop eliminates
        // this overlap.
index aee065b38331336c89026867ba0e012d95c0e214..f53017860aa20942e944c126c5c14579cb21d232 100644 (file)
 // https://link.springer.com/article/10.1007%2Fs13389-014-0090-x
 // https://eprint.iacr.org/2013/816.pdf
 
-// +build ignore_for_gccgo
-// +build amd64 arm64
+//go:build ignore
+// +build ignore
 
 package elliptic
 
 import (
        "math/big"
-       "sync"
 )
 
 type (
@@ -30,11 +29,7 @@ type (
        }
 )
 
-var (
-       p256            p256Curve
-       p256Precomputed *[43][32 * 8]uint64
-       precomputeOnce  sync.Once
-)
+var p256 p256Curve
 
 func initP256() {
        // See FIPS 186-3, section D.2.3
@@ -412,53 +407,7 @@ func boothW6(in uint) (int, int) {
        return int(d), int(s & 1)
 }
 
-func initTable() {
-       p256Precomputed = new([43][32 * 8]uint64)
-
-       basePoint := []uint64{
-               0x79e730d418a9143c, 0x75ba95fc5fedb601, 0x79fb732b77622510, 0x18905f76a53755c6,
-               0xddf25357ce95560a, 0x8b4ab8e4ba19e45c, 0xd2e88688dd21f325, 0x8571ff1825885d85,
-               0x0000000000000001, 0xffffffff00000000, 0xffffffffffffffff, 0x00000000fffffffe,
-       }
-       t1 := make([]uint64, 12)
-       t2 := make([]uint64, 12)
-       copy(t2, basePoint)
-
-       zInv := make([]uint64, 4)
-       zInvSq := make([]uint64, 4)
-       for j := 0; j < 32; j++ {
-               copy(t1, t2)
-               for i := 0; i < 43; i++ {
-                       // The window size is 6 so we need to double 6 times.
-                       if i != 0 {
-                               for k := 0; k < 6; k++ {
-                                       p256PointDoubleAsm(t1, t1)
-                               }
-                       }
-                       // Convert the point to affine form. (Its values are
-                       // still in Montgomery form however.)
-                       p256Inverse(zInv, t1[8:12])
-                       p256Sqr(zInvSq, zInv, 1)
-                       p256Mul(zInv, zInv, zInvSq)
-
-                       p256Mul(t1[:4], t1[:4], zInvSq)
-                       p256Mul(t1[4:8], t1[4:8], zInv)
-
-                       copy(t1[8:12], basePoint[8:12])
-                       // Update the table entry
-                       copy(p256Precomputed[i][j*8:], t1[:8])
-               }
-               if j == 0 {
-                       p256PointDoubleAsm(t2, basePoint)
-               } else {
-                       p256PointAddAsm(t2, t2, basePoint)
-               }
-       }
-}
-
 func (p *p256Point) p256BaseMult(scalar []uint64) {
-       precomputeOnce.Do(initTable)
-
        wvalue := (scalar[0] << 1) & 0x7f
        sel, sign := boothW6(uint(wvalue))
        p256SelectBase(p.xyz[0:8], p256Precomputed[0][0:], sel)
diff --git a/libgo/go/crypto/elliptic/p256_asm_table.go b/libgo/go/crypto/elliptic/p256_asm_table.go
new file mode 100644 (file)
index 0000000..1d957bb
--- /dev/null
@@ -0,0 +1,1473 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build ignore
+// +build ignore
+
+package elliptic
+
+var p256Precomputed = &[43][32 * 8]uint64{
+       {
+               8784043285714375740, 8483257759279461889, 8789745728267363600, 1770019616739251654, 15992936863339206154, 10037038012062884956, 15197544864945402661, 9615747158586711429,
+               9583737883674400333, 12279877754802111101, 8296198976379850969, 17778859909846088251, 3401986641240187301, 1525831644595056632, 1849003687033449918, 8702493044913179195,
+               18423170064697770279, 12693387071620743675, 7398701556189346968, 2779682216903406718, 12703629940499916779, 6358598532389273114, 8683512038509439374, 15415938252666293255,
+               8408419572923862476, 5066733120953500019, 926242532005776114, 6301489109130024811, 3285079390283344806, 1685054835664548935, 7740622190510199342, 9561507292862134371,
+               13698695174800826869, 10442832251048252285, 10672604962207744524, 14485711676978308040, 16947216143812808464, 8342189264337602603, 3837253281927274344, 8331789856935110934,
+               4627808394696681034, 6174000022702321214, 15351247319787348909, 1371147458593240691, 10651965436787680331, 2998319090323362997, 17592419471314886417, 11874181791118522207,
+               524165018444839759, 3157588572894920951, 17599692088379947784, 1421537803477597699, 2902517390503550285, 7440776657136679901, 17263207614729765269, 16928425260420958311,
+               2878166099891431311, 5056053391262430293, 10345032411278802027, 13214556496570163981, 17698482058276194679, 2441850938900527637, 1314061001345252336, 6263402014353842038,
+               8487436533858443496, 12386798851261442113, 3224748875345095424, 16166568617729909099, 2213369110503306004, 6246347469485852131, 3129440554298978074, 605269941184323483,
+               3177531230451277512, 11022989490494865721, 8321856985295555401, 14727273563873821327, 876865438755954294, 14139765236890058248, 6880705719513638354, 8678887646434118325,
+               16896703203004244996, 11377226897030111200, 2302364246994590389, 4499255394192625779, 1906858144627445384, 2670515414718439880, 868537809054295101, 7535366755622172814,
+               339769604981749608, 12384581172556225075, 2596838235904096350, 5684069910326796630, 913125548148611907, 1661497269948077623, 2892028918424825190, 9220412792897768138,
+               14754959387565938441, 1023838193204581133, 13599978343236540433, 8323909593307920217, 3852032956982813055, 7526785533690696419, 8993798556223495105, 18140648187477079959,
+               11692087196810962506, 1328079167955601379, 1664008958165329504, 18063501818261063470, 2861243404839114859, 13702578580056324034, 16781565866279299035, 1524194541633674171,
+               8267721299596412251, 273633183929630283, 17164190306640434032, 16332882679719778825, 4663567915067622493, 15521151801790569253, 7273215397645141911, 2324445691280731636,
+               9262509587234749312, 6377906816499461739, 15415592259881792841, 6113140067088447267, 17505803833889144731, 3922849788840338823, 6180172597177093790, 7272741317181956640,
+               10883262735810583709, 17399134577381480315, 12750035195491397119, 13953097270363313998, 2485196748577282439, 393430759246706702, 3408702096065201083, 16993508724217005008,
+               6863012803048745338, 5403358912802668606, 12029756355518540153, 7447472859343023066, 7395681837001497117, 5416243410959797052, 2749045697176435642, 7813683613416962381,
+               18350218749545913064, 7509253999860752750, 13295789896366834092, 18326374111226872828, 3258048562491844971, 6342797029666289605, 9612474478300039361, 17807494771134060923,
+               9986610307523639857, 6419466267862117340, 324428332031706042, 16344106992423140174, 9434790811884847197, 11733262517030341550, 10475871084940451430, 6836751077061091536,
+               6209985515928007176, 8422208926220809341, 7866188125456775984, 17071696982741312252, 17482363193291892153, 1949968206030126177, 8823961512355572132, 13873010936602132387,
+               1136614876084383862, 14528605954969250458, 7641208364604111421, 18286716654189762724, 10711679476846124804, 7209187038097309348, 11378652158954714549, 8736575389915992180,
+               17651988839102959720, 4019365809979531118, 15024676458991206505, 12622721674297982786, 243375780477240745, 16572583194372185930, 5189991834753707889, 9498206494038386287,
+               7870185149723322393, 7858065912377481781, 7050328012468471455, 17977001023138181397, 11912539230960339911, 1290924823368819542, 8532615064753763585, 6439520053123840906,
+               11863354073576605599, 8052916203396229040, 16399182063316628399, 10837704607074036270, 5444229620349428264, 10866168931038804304, 1298875461760659950, 8904898233335519592,
+               7053953350607273992, 16629865408105641272, 1929728580699289339, 11046110151029488400, 9569890690274721816, 6501378768832742664, 1512621765961532661, 17084264658609527495,
+               300662505135603380, 15234062183651308307, 5319536121171934679, 11496182741145732970, 10520610739189276272, 4310163027157056344, 3285324287508696251, 3261468597637865009,
+               5427469457023618335, 8296698312021944466, 10882999905197052907, 16825284839961451415, 2106903142647479713, 12008841566652934760, 5361688498494289694, 12228623597691228792,
+               6799789383171367218, 17419525584795621504, 10685476378747845090, 16314000862057872712, 11014509959317588121, 10396318154903722147, 9986284919279346079, 4005974039875805723,
+               12980531573372269379, 11790791377897350561, 14264262096731994829, 14999393269362129980, 15405842559289002684, 13147503876582120266, 15449556979080143937, 5047767509783027570,
+               16354606995222167433, 15941889353688553446, 10301254747221876749, 10704428461746587572, 15702361407127630489, 3283718562982354984, 18081088275079496700, 17549094608770385733,
+               15620168851912893400, 13762314693487747007, 13577625382054330775, 4116976667540664996, 712200332640207605, 9098568002202933512, 8905476951567380032, 7075673514150314660,
+       },
+       {
+               15811459837282651008, 4038049993244767161, 9054218236388056577, 10807376403937048775, 11113869110590438959, 10336442539492421506, 9228056645601479672, 2983388754829658480,
+               7189376137127712298, 9147574701720272724, 3983921661449444789, 12479790317447783959, 13221020976679959405, 13001868979553711359, 17918176319017234744, 18030393246529651080,
+               13903368497828271814, 8050546449078305498, 6932373216915935575, 16010012759059004304, 15451708272653450375, 211711129247219149, 10435723642185827585, 17790507800712341232,
+               5218985848865375996, 5835476376320976237, 9096499658845542933, 8952489298840360492, 16605895184424459659, 505731104315931813, 17784248872812610986, 4151555707609374291,
+               2650786429127545939, 15186825834659456704, 6983758297535957561, 1268007525252235269, 11433489869282443481, 12352824209154665189, 14555720778982121964, 3578659908492218328,
+               4038120750249579469, 8304001815287976437, 251700810512667658, 17170873737273596918, 12809642145843734737, 5765073376623244019, 7923401246629348462, 5401634486288115286,
+               12830329023522940651, 1302336131164509751, 7011936976469244509, 8446680306499168806, 1386043952588989461, 9057741950701319559, 6719607413978812889, 17371065020414280890,
+               4963953120977916566, 6585250545846301109, 4490972754776862709, 10674499592300479120, 17494988318349821345, 1814042777264686189, 8938395423478059768, 9062966010283426056,
+               4683683785459765575, 8782133909400988812, 7201726172249963453, 16855412996123591560, 12016536526053703526, 6004686128951599125, 4323130180079993082, 7578596978943754924,
+               13272384473390546409, 15052793429857194942, 3597944793474963009, 5659515835454510338, 18013102402609680655, 15096936721974473248, 9096406212198787674, 948405832772983882,
+               7533214627823316056, 8009521942734148665, 15370181949218639901, 17395801240657257383, 13217990616373936619, 16323510521919428293, 10737557422966235859, 11113837024463125316,
+               3879469818714011415, 11493820457829716643, 10091807027724827301, 5032134849078736052, 18015749204009276046, 9667758283246223357, 4629693773460610802, 3807196436109718946,
+               3214144211600931504, 9454007581819416365, 15275469051811991033, 18196204074031746058, 14853793468372596948, 7707818604949749658, 3266782539036976530, 12810995382868348472,
+               17461133192060813135, 16870745208936545685, 5903437034120721004, 9683544852742219696, 7903581348090948266, 13461951083275541722, 2454715926022970060, 11781268272016425522,
+               3026443193966185195, 8027125782547146632, 17998666917527163386, 17214321347454260227, 10230244243647560419, 8728893474426972780, 16205038544687771303, 13771356055080873468,
+               5724217930909760221, 15420221591912350415, 9910465013739250802, 12511683773790779491, 2841532862707547306, 16614426471009646589, 407574220261191228, 17422057170120224031,
+               17151505459068312604, 2041124098660595410, 3221606782120899146, 1382742171848704850, 17222534050501711510, 3195635935311449393, 17295393886051199723, 6296241746423654238,
+               16510537668852450348, 15650518534057329304, 475704671950317376, 782416820485820540, 10970369699990900408, 16601298147057372792, 1599283701215392453, 8464446359559369186,
+               602848212987973622, 9275953159572178443, 15133444738457385545, 7264639569553811785, 14831517002293569763, 4277078717758211028, 12880437544322007232, 16339691585101354857,
+               3725101809714764432, 2995111022132376824, 9338883729618021504, 8824923738291347476, 3745497072215538317, 3576446898425965872, 2350077748663612773, 15793255155885543355,
+               8020669822852194733, 5865488997462325879, 13508617967776537887, 12934930135071898613, 11708185641249600577, 14265801329217514207, 10451671488560352734, 13251349632343744236,
+               10155392082337432799, 16725751190167983672, 17791070776350679280, 6653785531179322348, 10087876256887835780, 8422365820961469204, 13614411778251983480, 11687935452237305960,
+               6094298050768263419, 13949448434836272414, 14194554169090099223, 2625524360834828424, 2823844915913169919, 14077211807091283985, 15592587505996634401, 6562949920171518305,
+               12904339001067417585, 1972265247859388742, 8908590936681392405, 10320719400504224158, 8298368064038407143, 2105745729886511647, 16509751074757847095, 15156289751671616565,
+               13922601558154971179, 10541544592627074316, 9996345160543671471, 2956094548427827774, 3384122842786043431, 7003441038438960180, 11945730502649377204, 14797331669618433927,
+               533287349958250211, 13929395807878461602, 10036169742264959424, 18402398814900480008, 8793706913568807269, 4438954128288889267, 13996827050589647592, 6637236830429213437,
+               4308464751705576538, 12193581114161194913, 7322672375339219540, 329737085274484939, 15312435499764491079, 1530264129038944128, 1545025965426980152, 14559433923601957161,
+               885617946245226760, 17871561572095909264, 16413308527330544768, 2938750343525834336, 6332736376778563648, 16772687696658236231, 9760470695949399178, 17420556823805232882,
+               15040671962589188567, 5841393164221253498, 8923415548773111750, 17449640982747951473, 541686588805328549, 9579487672246868564, 12793813917570150236, 5744918442591934533,
+               12406806484060734474, 4655292039647906135, 5745141229449178147, 12923621608907306732, 1329768221522217568, 16293616079741201891, 16309603918079351385, 8282635243638078478,
+               10842935462043546322, 9397166878596340773, 5807145729199489911, 17083242467628861919, 11473470924584853882, 15220945465200609206, 10470712526179658906, 8129601297261864071,
+               4407657041250297528, 13832960959347315977, 15056546959967740939, 4350443362134191429, 8013419913016572733, 8888684099801298477, 15401479253620745715, 18279947201669400847,
+       },
+       {
+               7454214833719424418, 2128900810399984335, 8254953962723841408, 5341529923812819418, 11486532916552139238, 4528331821405917357, 5048485034448492541, 4189495710753944825,
+               9223539587116638677, 879142711399260546, 2878829560233905572, 13081522393987952773, 3067261963348061547, 16008150780594711643, 5466468631453287640, 16659147898971349582,
+               8047766502132608624, 8715815570878148809, 9093649079884580138, 3437267783531715968, 17562225708466062266, 3512667182749067601, 9223059995161026858, 1366690634827047376,
+               17929132376737482163, 5565926714491294456, 5252303555134107501, 8169975563698132305, 1829326230943509100, 13780918661853274468, 17736665596871232627, 4246797342334307384,
+               5113556452592134569, 7304867793218750141, 6016631926489320290, 16471860203547627727, 3444471410714850041, 16571738096215232488, 2003912224952639024, 4203884000388032492,
+               16858425223672505353, 3192567884201479579, 1688923188642613263, 4159042130811153987, 14900413503869744297, 7521485042788722327, 14038093805562042641, 14713051866364662650,
+               3738774192924465076, 14037618828827556145, 12882915396530927286, 10882862194263941815, 13115222579444494605, 18244214260845794346, 17217867059738274194, 2458870331386500577,
+               8768788172344064509, 2761897497254272960, 1400167175024837359, 2591319596670212133, 1499652044223484974, 6820326453941021707, 9701009499879906773, 6897435972338565418,
+               8314355711464256163, 8435944020779763783, 1814803522962187872, 1875253356755380905, 8214588085484192137, 18062045700553127821, 6649947905482043494, 3119726140944397531,
+               11881571666857493523, 6300786026612414187, 4928573492087752294, 18343550313462089203, 6770642120472453960, 11296815027803718740, 17312916793783562794, 13028515123652649961,
+               583508939637547757, 3195115082527873085, 8497784022800549923, 15135719419829981016, 1180291993378114150, 5447281494912347899, 4710517655176242215, 606503081693490000,
+               17732293765863716052, 853971165248416821, 2022886284923413326, 7522564752651732633, 1417954193520965954, 5046659528429172066, 11426939225844711305, 17687206690616539318,
+               6518552374736169438, 7940416740434530770, 15228615103587329007, 10662504584317997513, 18370800756791469891, 5564085264882124489, 51043856061444814, 11996026931884728651,
+               7009195269496826002, 18330778751427846129, 7903886241001925539, 8198930484643879628, 5453546027419466587, 10378692433982210944, 2242412603379120569, 14762161396393277464,
+               6146718865488327808, 8559779132928137805, 14001994895150170346, 9915701789711858841, 17119408219089522083, 4345363585985782988, 7559492126634131602, 17074565022279033371,
+               1081257522368061155, 16144982029632101790, 2280210790959566458, 5000326950136078873, 10441086845859171982, 5717080014740953823, 16816253740467637151, 5185838557034755093,
+               5835900675852976641, 14850646160621635240, 7784412869482958370, 2550282385659033114, 5102457400165153071, 16480738116286616710, 10726825595752219296, 3297564208881065856,
+               1801069609044825811, 12940364451588241698, 11725236374887225564, 4731241880784054295, 8874695411069669852, 10719836334830130110, 12983549127094653526, 3498884940869443564,
+               5044718241380586525, 9152928988998314956, 13274353997717834972, 5731942246653336838, 9453579625340936273, 6013700107129234092, 8535405089994224035, 12024982282827680252,
+               8296339816955798913, 17352704937535250450, 11768204246645005024, 263391795317009517, 6622964609352808474, 14563414288208376628, 17887389278697258458, 1552357122641071119,
+               13193447428787140357, 6701071088186218635, 17090465712567125397, 13844922841372559745, 4526664599449630663, 11321311100342816810, 2490532976442445147, 12506579957986846905,
+               15880983134955361922, 12396434033732989105, 16113831675045409693, 2288598422068078002, 2992425583703267972, 5056435264545116829, 12961420259857080621, 3600697676136115398,
+               12817090821406743193, 18109694174173693756, 17050997692981853333, 15796663317536421728, 15462568940214327094, 15151767385082666402, 17711108405932879054, 4030072071760424157,
+               15725012875727498089, 7622633481063722008, 2241559275264867670, 4018985714167034871, 6507661741395512701, 13435865773135624096, 9564553262368888543, 2283482276790194513,
+               2968718708369505078, 5001470555537559034, 985353756026354700, 3145435598301843880, 16410370922030326027, 13981261173663429189, 12565590835494971812, 222252377400865123,
+               3096505383227168071, 9129898186148780825, 13266305466206099845, 16135309871416543685, 17993464782237414425, 8124413037611692960, 8497190057115012501, 16568064870411415344,
+               7703394153241465824, 2740794419858297964, 4228931976096177316, 11207299659959318490, 3319492324515199082, 15611937984154016609, 3431896575019701337, 10686234123352138088,
+               9979039962499030832, 11759414020433216431, 15164411293105859178, 2834464820255498467, 10716371968480406389, 2722055037405581557, 9240657586762413776, 267811388229104916,
+               8385388272348876655, 16035999427286017211, 11255427708348651444, 18402964994101916340, 17964277099260928049, 16377129731672778885, 12034488763192562427, 15854195461740399790,
+               14134352329607480415, 2406779189916280288, 1148342927890148438, 15859735140823564382, 12055096645840568482, 16044304241162505738, 7466809979198503617, 4519925955244504432,
+               576546655711744206, 7729660311499709518, 16864252562359023573, 10537888397995064025, 11828992107618549830, 875843272290362538, 5328675038336932433, 3162100370899364658,
+               3897734650128449985, 3892478283047854402, 153850176068596076, 4448963435449755938, 9911011406822436713, 6379744721342779297, 360324666931028426, 8002086405015565067,
+       },
+       {
+               18068291112584812890, 10288580446655316879, 16866690514199445805, 15458664010538199871, 17175925202246173890, 12208778610361755998, 927739404697616036, 10330183209424493139,
+               17095781462759061506, 13984950766342782369, 7038608479806172868, 7073471193601880894, 9212126909381119712, 15865851343492198107, 3874039137971369196, 15366505242302572319,
+               3235058267792568155, 8030551941244615429, 12851363585510555514, 9786973022560471711, 4901414898060251968, 13240438628487941170, 4707852389766057435, 6503805666511566831,
+               12081034000518110752, 2773740877021737013, 6429475399936543899, 6804412599792308979, 16082860502313571182, 10013838454082912732, 7176778953927883654, 8065751639278576331,
+               2577328127707636877, 17299987330349518428, 15104751346159263209, 15422444943335124822, 7934601464470854115, 2803659700354182364, 186161376356596699, 10049927908892587253,
+               14226302346438044875, 11259466681405724608, 3945860952925292329, 3287876564263331089, 9461394118536996000, 12404803552046013762, 16569223065554335449, 15881973563254196893,
+               6665552777203645232, 5302850683863152336, 7778922028047389493, 14212904863357452615, 15966527672828304861, 3802704091320278344, 10517530714917238300, 3742971938824724276,
+               17741525051518363144, 1374267330336191942, 4677891169679898540, 9639823611685431337, 5482431056894095950, 6629146695374718376, 3884574854221819712, 13266790928096813258,
+               16028684877412556061, 13405436055762225966, 12268280467958284214, 17956874998292211440, 8610745336676661311, 2945210828327041653, 7889492068658434371, 8032335517518163423,
+               17096678157067198548, 11751872841896846778, 14951591239724148110, 14946797103632354342, 15001812923533485850, 1354666869219009884, 15934246013528228877, 17674533676709494379,
+               5120889077991995845, 1349360562851394781, 7965752316528770369, 16276575673105864366, 16613052983770261287, 11454051240568463780, 16146905806612132291, 15806571503343623359,
+               17505459029376928465, 14087658194607915364, 12240552390931686885, 1809009366037859941, 9468395484396723291, 9446052656478984520, 3720796795453397330, 18035355127900871187,
+               10937782812576841853, 2203021845094443505, 9622750764486021477, 5518948515641487288, 8021555402800950130, 8884074473434139094, 3925095588129480413, 6199533424090268508,
+               3824657730049729815, 4646911366274335188, 5283751816651713473, 16396970607630079440, 9102362834410101425, 3641728106404110497, 5923630184251416230, 13179374259571264822,
+               656781601862662976, 13284523818709348938, 14255949685810234815, 17662122984572331094, 14005272187244763785, 2769973460677437621, 9745740172208222044, 4399769039990314590,
+               18221138344920380175, 16761112742545021198, 14421639991115588619, 9419167563943683547, 6237248361283446238, 889754338720059891, 2289880386545166424, 4280148734121099084,
+               8456687949810928719, 6224977199672540221, 9826855484829367341, 10345583292656523462, 715642447678891171, 10791247680314230673, 4390153264475025171, 6710036254773432312,
+               11434352627810350015, 2720291857616706675, 15035363195148805272, 2358906741960696657, 9439888337759970778, 9654563570832962181, 6013570511081660799, 12742404245236356978,
+               16538557679183724426, 6137267799072203525, 13879005145532324670, 14569289845201353615, 13784903266526414562, 1051135786146476033, 9343275973150690259, 18338317230916899584,
+               5259165122317589354, 6306061166879114159, 2622163270351284906, 15212813592118086979, 11497359168652342849, 7085380391293263482, 11799059272489792659, 4912160901181298022,
+               10956239956289671191, 12649697329483184719, 17174497942073298839, 16454040570484021598, 1964314354536023134, 15533681501854792750, 11384243972598433754, 14387731385073008825,
+               1627256545355657442, 9010013556811110994, 14616120598404631231, 8391972858400276155, 244817907132802237, 1484397967210729699, 2663560284299448875, 4820353472962713985,
+               6567121006858416952, 17119959301239619281, 3965303761563489817, 10211688306206007722, 724618943950031080, 16749575186941231354, 9181397347361086360, 470616631211702666,
+               10512473611770099290, 11735037909076331019, 2922606398008539984, 2599799834378751770, 10226702495047936424, 6109026252412854338, 15572556822827169237, 11993701786788749663,
+               12951512375864063487, 9270845327881823041, 13198171264747338719, 9240466821667660686, 14918848310897324032, 10111918274408213257, 9869937817792431868, 11316967879062014936,
+               5691364106926740802, 2782311978438620206, 13067832493996441150, 12682941211395745221, 10515041347274706648, 9910726429809603026, 10540072260993990483, 15078586909891471233,
+               10892036011159420575, 9833543566604313963, 15176473361412960115, 14504845496732895720, 15845034940445278100, 5364672156984348678, 308167090528488415, 12390239901799634313,
+               5106897453764491321, 10540479232768400094, 3938246597140945859, 13156157265138481529, 4932443191001849637, 11374218582626530502, 2907557293167002437, 6807344711257391317,
+               5413712686694380670, 13147753106081951274, 2960292187746417883, 13977097845105551070, 17642067093469099040, 7699556298723812469, 11597002672863564976, 12392265705126521509,
+               4607947077536257852, 17763906282816835996, 11288463953418287893, 18299911648497821660, 3194698850612319839, 13371221457376435780, 10047718724723936081, 4488868185988157408,
+               13742985513958274859, 14201726926009534105, 2183997556320958457, 2564950343266657518, 8846625471673389624, 10147673280504740463, 186524308060896613, 16409126738088317791,
+               3993197157612782947, 14810882170056329119, 3476738916713041107, 1512933700383846542, 17820889751141311776, 9132720567660500233, 17598924894608972696, 9704537908665702455,
+       },
+       {
+               15695265447782578013, 15506558718447241194, 12341861439298989232, 18400958156300100845, 13704811286967591150, 5802260047239067846, 3266013253411255445, 9892957742319181954,
+               6053458788987550519, 3243549259991905443, 17990025476026266205, 3918149716414968130, 562225565996136148, 12175287017902713154, 16317970834262634990, 5431198806775607012,
+               15123186170178367264, 3054913246068400920, 8130663466272395280, 2852812622149318730, 6747630551931917110, 18302049774259156971, 3663865061939346221, 12340091610704678811,
+               17453312277789785069, 1148609799196055657, 5931758962926317381, 5297597381576544508, 9136842287749269744, 3007653173299649609, 12364677607049679091, 3656932227466449489,
+               17732801126130995365, 16093023291975796560, 17028512234142609413, 6293028118993952199, 4019599708379609715, 3557632583507755601, 16737140015288442165, 7041678499288317736,
+               5187842645752673199, 14914432544387315508, 4944360914161982641, 4177329533692612281, 18423887817846407126, 11935898134550505219, 9191754399457615042, 962223885189306707,
+               5467152559317256227, 13407023128339380091, 656806207084558176, 10823228592509573890, 282802378108427873, 13003319652664166176, 11501612671901244594, 8595770155487539951,
+               1805255869285898834, 11676967700876044626, 3486630203654875772, 8366336693945605431, 17874084888474647879, 8803709150655606891, 680993178667234696, 1603785777136148315,
+               3637712241808318043, 1673622542455477465, 14468899013751477571, 6607241816357171779, 2332200248940843815, 14077155355848738174, 17298155509321457563, 13624623885136011130,
+               12550073596584561722, 13898852145577133829, 31360866049197404, 12629522544897401454, 4563446134761510332, 7272813487383198495, 16767195814334178362, 13600498026689482359,
+               5170414136067325373, 10875290278133558518, 7331268231382198947, 4082234313337835514, 11725295114019619895, 6488017511603508543, 11399466652931338200, 2898113599278666684,
+               7553418756944942759, 2324485560009697358, 16004009784734101843, 8345371056076551939, 7377284629098981027, 11049718262343754276, 8021605820736410979, 8175349759714152494,
+               805625092558946929, 11996029844853502332, 1725029464967101849, 8189609560660709539, 10396089572662865065, 1756007811373736605, 7645529329516777410, 2608132938055260111,
+               17014595621244604813, 1574499958190108567, 8684546755761322906, 9997538531915911005, 5652402150243592363, 6315865356369667235, 8687115108443972047, 12369176255146729475,
+               5117004045853299762, 2238407612548002914, 12392667457861900490, 10614312910576266709, 6446577503758597410, 3767883614425995197, 17954966454260719539, 5233322901463099,
+               9194523390605857831, 2335161171394626054, 12290490336543843159, 12464172604156286188, 15842196578033029974, 9081285134201585379, 6123406461662038242, 5504260508195082396,
+               5345718195770885739, 10397124463462860788, 13439280718993427040, 15556816356929214653, 17286785976489019906, 13891416634083443852, 16346644312573564447, 917629419222512011,
+               7892626957952656865, 11229871638807701267, 5249460237065799805, 9529842808650392581, 11803106868201977918, 4600784567377577444, 7178870186583927975, 13829108773971861655,
+               1289703927368007546, 16175369390684210381, 2195306032582966573, 11284704298115036296, 4385727852306374408, 6915138269030006111, 13440775052829788601, 7742359656861485339,
+               1418252737937945274, 10664598666472920539, 5146625453081549320, 7716408631061669307, 15481216546649435253, 9087869057854823101, 8438781502742166926, 16066665509570633845,
+               13091912700111633391, 15443255616678375884, 11338466119311799740, 9641919445273031117, 12359044485240987114, 7665168466660756789, 13845183791692700257, 10700410793152785934,
+               8528578803314347534, 18126789418189181716, 6819229450418907940, 10542951903574211724, 10335954505229790439, 773396809431100386, 763679854573261611, 7782804492252573047,
+               14102889564247144327, 15479515297699126743, 6400257822506917934, 12400211936189844586, 8190162441518233318, 16489757979266243333, 11074854544980782334, 5650848136444824725,
+               49299995316533601, 1658812626798186796, 14321322055030354, 1062750633396640947, 11458188738562323084, 10319462683954522885, 15398455357851813321, 9473384090828584828,
+               17723857482947114516, 17563952877363564604, 3160294749187111891, 15485369139883303866, 7487527166185553604, 9661144290316674030, 16387431126208996705, 7499766964252214921,
+               18331281993562501191, 16034836629143884193, 11149238385567891503, 1413880911197321245, 513884082842080653, 462183409527465946, 404977499728878854, 1459875951423441439,
+               17249202826373649180, 11151860661862313351, 13606113651347187963, 13653298062695357606, 12346841931589648448, 10659825520992339734, 17857177794617595021, 12846976930859175746,
+               7421386827645898229, 4567141110780940726, 9022716764262477732, 7287282267953917487, 12950322172330872807, 2675202024861592519, 18339036521791481203, 7003909904344391740,
+               13539440097944399044, 7108271818419613260, 13229113021954558930, 14920952138366964142, 11082363944167072746, 16156446445495173622, 15515349862819133984, 12359827931233605745,
+               17013104138257181849, 6982996767213561282, 16259302607976830987, 1579942890487532721, 8635464047344487404, 10435012080572068738, 2976844365866972753, 9471858478345924179,
+               2347775782107812070, 311367032040459687, 10852128873404113998, 1338612296059509077, 1599132038614432432, 11533828746166635650, 14264087792956755961, 13004615331499537807,
+               9599159247384506427, 13011559959971256245, 6331802547989957841, 2642320882309956905, 9140255367820630480, 6883541786494880896, 9560822438260750771, 9273862677291701694,
+       },
+       {
+               6185067974942684922, 6452325785873503452, 15247257292915812252, 3689324664200339196, 3264129576054154137, 14977721630214750038, 10720913377937894256, 15914487080763816378,
+               5498621600689515064, 11498885804037952971, 12697073118321478539, 13999008478737234463, 4324885099420360642, 14021182496192299466, 10763088992583373843, 12898585157666243299,
+               11622402383521841588, 18271726976204770291, 4805501248621435402, 13483122453682180759, 9288143526654965614, 4688427612851085031, 3280806057528512375, 2249349779106893174,
+               2317249352525369754, 15030797481081533168, 12237590576308284360, 15660076992611440873, 11341015819700735887, 8280257602754365719, 9212501234696283343, 9673375202141178099,
+               1576552382781604867, 14644873134348781157, 9860879950368557094, 12941927431704225849, 11959666739052502184, 16171152369226594315, 18364294470656574060, 15172859394935215584,
+               7521577570681641021, 410124023045579310, 13806534589183327176, 2731801491329207875, 9959087943014269549, 16205635445474657221, 12069145915768935630, 14906463509471682144,
+               13803661539609326912, 3233094883493439444, 13409742688319755923, 4298169788674760921, 12847636671560067434, 6702365884489797170, 5650404576647289813, 7380374625644226212,
+               9762534010701623728, 15349113802811029024, 8305297169667044246, 18013018210154476198, 18414050009163335761, 2190126859433916996, 5444481274452218807, 13415988647365667724,
+               12538763466834894269, 1385338113050483955, 17489001033590767373, 12734464941837886525, 5762578105750980174, 1466528690684075875, 4231060025049573530, 11218444849081704286,
+               13520439252664960951, 3770430920651384098, 18274623217805904547, 11545267616883260257, 4084783424859113779, 13863968977657663867, 10237835480648574698, 7395611844854084274,
+               12891185742908997266, 2889148203703402614, 663579373261619221, 7616112456816883701, 9002890885722034437, 10753730807791931375, 3553894671829778441, 4368240432504457389,
+               11641532224340210206, 71261001011952801, 2321745415903209397, 6595984444855093239, 10341299657770272718, 11529878689049370930, 14381510695605158203, 6869272773579747365,
+               18407769999912340511, 13801873415230385184, 8080153703167941484, 14143463895182697871, 5248006623352376562, 9271982788122934275, 11225161179021692620, 5076519449784098178,
+               2388868518767189674, 381125256886459269, 11316805024982236485, 11671355336111917711, 3564177948445768908, 5245093046097324328, 16144139891410041039, 1201010948447708436,
+               16591032462856670656, 533850935988668408, 2263232738784171066, 5572124915367282948, 12583782854491678471, 15015562207264407653, 1167486851113549964, 2987176661273439670,
+               1073778278665127828, 301289653767944933, 11482324780950168317, 10626716202328004967, 7258024014655363102, 12597648090458567878, 2617914106162603499, 12324652644266476584,
+               3803745429517922765, 1699256829990081513, 2179986933466617785, 4330084096014112280, 10403896221616386733, 11682369673591069651, 3879392495596713886, 17249085256521020624,
+               13938687445393525296, 13822790166673492712, 13216892716897321740, 2165870280409061482, 9147830602451471293, 16339144108911449834, 17837507766320968023, 15340710005345158245,
+               4485838034764604283, 8426970493386126530, 7709201418726935942, 13468796449943783583, 16441091014185628843, 2374269830239737237, 13423059086148485716, 17132218391020520330,
+               13957732574177025801, 1100344278733481546, 12156946932617203965, 2007756425747006287, 16454508610548016441, 18058668363064769203, 15619001054652658323, 1201476243910931863,
+               1292412381963708933, 10908631677673353277, 15138649576688192753, 10741579086621436813, 16534963566169304684, 10228646729525192055, 4256608246548223655, 16176814322718522963,
+               3012125536603284881, 5466178753014623970, 16598422155702380175, 9902071731736699653, 13861556771123036741, 9534711573278556274, 9805898455743897538, 14683694395093520838,
+               9125214754744730198, 143353181770418225, 8976042597473555858, 13405481215779362056, 2863125481657826330, 12333764090388731260, 15250359513836914002, 5086706595778559056,
+               16341334571424533804, 4657494880554316004, 18092783076286521475, 19832895869027143, 8667365497283429486, 11501953273367138162, 5832487631687776985, 664754160781757174,
+               13604774408440609080, 12660956565879820101, 4535452877362385626, 8063311919592303330, 4591511734775484245, 5164119991271568303, 5282209033000495913, 15181017218549722334,
+               5070228782679699429, 277881850788922387, 17424210585510719837, 13586569401109299583, 16661809787463692974, 11543434536078774133, 2062889565117549061, 14261113517104795690,
+               17683343658262519228, 13727986689138309987, 9352982220536939533, 7578301410191413286, 7970586266869249410, 14357824150096386968, 4381700479561442130, 13217807763329274501,
+               13524719886605363170, 11553593166914861649, 12034020205580665813, 985175984881624722, 11040631342644137311, 12107496606245418129, 7328748654066365904, 14741972847454326011,
+               9790251609380109406, 2449588380962781369, 4694893010228180943, 5172145489692928848, 5411277023198532852, 12752098113265127406, 4559500999103209672, 14921033543082064351,
+               2248082728820243864, 8720404853152831367, 12431505213690884811, 14883031570121462817, 2278273022936639560, 14988529405400451352, 16732922988142595529, 1071232319627396164,
+               8793441611217807824, 13198147137434605751, 8167936709747999601, 7685928882032231744, 8779182451658438210, 8059106577297479923, 18394590909567718507, 15508315617300242773,
+               12828567388121500364, 2264959796189127526, 6222205589523394088, 8827682270015065013, 2619170858745203321, 14835030117099398518, 5960028394532808010, 2233397097850889639,
+       },
+       {
+               16319476863352440541, 10283930715856640343, 17675054544532098447, 11261132162985242084, 13712716897981761400, 2681907143459288706, 6930256922080133347, 1445069157579547822,
+               16928574868467385886, 166417019993787654, 5882811520342817815, 14106304179344008065, 3747123724781081800, 197109533566874475, 14303280595714789450, 15457633026018307066,
+               10773597511592584859, 12552868588431074640, 13500771767160426835, 8002499270056378440, 13792839099998553174, 12949371255843262119, 1713974340992291550, 16150173130483658061,
+               14745984256428057001, 9333707338036985191, 15365925315303462, 11789129028059619744, 7873100217437235208, 5289763977161829145, 17731215200358323788, 8876377479309635703,
+               265950821974454804, 5047467530470542278, 17523044368516619801, 10054436503372765176, 10321185867287373431, 1212061937729015591, 15311258419138633926, 11236518538207084768,
+               10904693956407098222, 9013418755007070130, 15510005599846320670, 995378633446250700, 12234095025518917836, 6689106237771514188, 2809193993744369126, 548124799387888260,
+               267350765778774337, 2853877351938464055, 3677119082593358544, 7685335121077514739, 6491980094762370981, 1384870316654548002, 10568872345228996498, 241629538659623878,
+               5839400175629113441, 5238299193248381245, 16787876416022887315, 6051613843621920008, 9219569873668974552, 5916753090530931032, 13390630214643423749, 3265335490455191268,
+               1507475744849985303, 2597075068965622770, 14968669113917266926, 597606442423659891, 44293923912414886, 3832651144752540816, 17438860065613195810, 782112340603343331,
+               9050896199196733903, 6427608033444590004, 13787696679536621857, 9682087046920409188, 4519093754155995429, 13564098392055667371, 10512507082236058799, 5289934424008191746,
+               3477191607403300916, 18283244229745029067, 8462159792484018099, 3056576498976014760, 7259283167233712785, 12530251965039903998, 10232104933720625111, 14190745998092156987,
+               15759362035410895911, 16075598437961371531, 4651513528876405575, 7694151626503869614, 14468862724637972284, 1838601521755586245, 4168957446435305706, 8694905613027663664,
+               14825552838983151434, 8639609968952840931, 15547914584352392016, 2313507499500708287, 6902543375698033684, 9987468886016348918, 9068175779860656258, 6899641689193116297,
+               7449110402827616954, 5689206471789540768, 12722069021950813669, 16017131401246233663, 2240977975275954837, 4794705713606614946, 5734937900461809607, 118285984764445639,
+               13917685647531721740, 2432096911145792817, 17733637484624159521, 3848601825403209903, 8192433211051054683, 17388066421914150767, 14336306308847565282, 7501625553608785022,
+               9844707592410952215, 8167497709587672711, 18115463401502884199, 8471563375691441535, 17525405040226359165, 2460181803833371342, 3375780580907171205, 3024376384135966552,
+               15446204978718816914, 10131769697256428720, 10937168660849553757, 12174257400309926241, 4774490771219074715, 13764876998736771340, 14299051476546774038, 11409551629093945893,
+               5471366060803425265, 5927845172343647238, 13321967429805195545, 1981489848211999240, 3657997933879283852, 1341488083977381854, 11001000434984172675, 12666440712128450303,
+               2127920575549495889, 8861781778185702064, 10501256952986753134, 8967441017586595593, 12224364761159418844, 11856305587178745520, 8176487286367052930, 4988165299911239066,
+               12279712962388998309, 7552494563001503282, 7388800608466198128, 15704167671257743517, 17781278773093632973, 6688613358271814698, 12261263098366698895, 2585757657252460656,
+               17064077609211627595, 14437064866605257652, 14386408901468621215, 14935685266532365200, 16350265985491822570, 5195856143474093260, 4623415440658404410, 2936315929072503688,
+               18399447684263070219, 11294713679768342649, 1600242588657342501, 2841752419388937826, 15111313732750279467, 8179471361906256467, 10611923788752807866, 10823997080784081293,
+               15607034385960553579, 6934034624930683639, 13318618594774430459, 7552865293216027192, 13692640408995992185, 11143313220936824014, 16721999332340829387, 6993089466645938014,
+               1749509641415861857, 8597876492914031095, 17942224190138398306, 1760222146515426983, 1030117883582412628, 6655464189981098460, 14222900139576809037, 13041171493967200019,
+               12415333505074758067, 16988669193263876033, 10482573641416551070, 368049292090348794, 16109255925523895167, 4949934055388640387, 12038479532506656790, 10829864449693781036,
+               8355401100656399994, 16963696462538033761, 10131652431024537917, 4166156454906166144, 12888240412190236596, 8396312458335953166, 445297814986468978, 10512295830234020744,
+               14405236772348157690, 6950094157338825845, 13379457125020057613, 11396720859761560260, 14063367153572826959, 4476298515903789197, 12708437873915498860, 8163633089770520638,
+               6432708226771955694, 7524978005081948959, 6442046223716866789, 4082077252385606982, 13626979819841658005, 4264573835620574342, 14788317690584235128, 4710414518172449402,
+               9592766374657389840, 3206081438027351157, 16013702689312533501, 15788528722601567812, 18314198451066123850, 13236688692074994659, 3229858297074852748, 2968037605940641303,
+               148470760067500612, 10319937899190593880, 7185467485673911733, 13041030391924988650, 17119842693824847662, 10989053172849710331, 16048294708726813099, 6612710923681979611,
+               17408606709137505005, 4263600430695220256, 8941719936291239640, 6115030817534063286, 838024703679813150, 9772071103323550178, 14394690179107421621, 8621372196164819917,
+               18138724984190926809, 4154767406604950048, 5209478936276366634, 15469512148904762872, 3613429290324777670, 12631812917445459751, 10280179062385049041, 19656860716268566,
+       },
+       {
+               12030193727051241373, 13981191132445467472, 18205169646206905593, 12162181194046583886, 10929925499200074058, 15291772758590352491, 8452344520852919320, 8199821440451878776,
+               9876482463501409337, 17331045017548147052, 17542726936580732548, 8299195336372136083, 12891767721269002608, 14062358772374813347, 4165127680073507756, 16350672737379495431,
+               7595271959296927018, 15286771623821390629, 980612661413312852, 5738158184597378995, 6972117550390447038, 6246497134979772260, 2935831443692029059, 12837371529160496660,
+               10228366644420455452, 12084265406352277347, 10265869676493821892, 3560143954870272139, 14368775225608592689, 13173522067191372913, 3592475039513249949, 11243554718624931135,
+               15959892157814064696, 1882528744932347842, 3354709518288681174, 14147909176429982637, 12969888425264095514, 12509610747258602648, 10437226619684632037, 7605683691113295811,
+               5697384515599291245, 14896081221061315030, 4329502046122948975, 16301954510440819492, 5191621061031169335, 12944691824816066027, 8080452646904372453, 793075614214301908,
+               2662373477940179766, 8950125653339535995, 15717799081080898304, 7088593450282143511, 11723351531494404904, 38673945663198753, 5289769381065195334, 1742280067441486108,
+               6543255501112359319, 6063422531520498671, 17228726254778244409, 7570754775709645369, 18222396492501523182, 14903937974816691813, 1216646642383641441, 7602781158453005929,
+               3007861146695764376, 8267227185027440857, 3177625538211272080, 3144345182124760000, 9215753228267875296, 1342253891473772992, 8185239004636232247, 14951188427081280984,
+               10569785547248986188, 3109435167722572449, 13661123218513357442, 4646373703143839998, 9712828426076586682, 11389514152975496268, 9796826623781200498, 234067627740956181,
+               2188380882990542468, 9914251329861595119, 13616219875099353594, 16135919125023820218, 10732193797566088293, 7172996278550642736, 8531638916719074975, 14749121691457005349,
+               14568782576170814716, 17582848432122737506, 1079387064102681806, 17278567874821675408, 3094302191119669899, 3730448048895347901, 3508894590334961422, 14091660942919228106,
+               8414395549498864629, 370884714015114625, 9859130251236103342, 17120282094084970181, 15213286581037020029, 2737545283554254673, 12422648607044275574, 10601123825482591606,
+               7332173975514924017, 6689389428877729175, 15162654177270425320, 17333672210015736765, 10717615330136876266, 15245080807947386155, 9830331968044142933, 16156512094344185621,
+               9151817936103586393, 3495709317444898385, 10881665308947458223, 7087755261386867019, 18372828768905212167, 12873774245490293443, 12750361906770763255, 17688389897350887716,
+               13329033749048978810, 4765695903433858377, 4452680451529163940, 5638854187414651620, 7897503022043776206, 17187635538005569019, 17766753195497526986, 13201529234556380285,
+               3638940913491383692, 16533217388164981609, 4668956005988168087, 14053696531704823982, 12029006663244142834, 12043309283447175601, 7840964186868745782, 5691369519440953069,
+               8500871974974230561, 6371833132372813539, 4002756625312698938, 7281624589760047276, 8813214993155334737, 7738842112797657395, 12616064385239668311, 11875709199633531753,
+               13080663957403320059, 7305658810888170771, 12002632153917673214, 14713338572031413494, 11629178662016777533, 11669230410217642326, 6563025945717173284, 15889630204666511658,
+               8934119620399766972, 4226481091885914732, 16000709195004445297, 14687868180928846933, 16269913392757896907, 18294005838441325342, 17625669613551023126, 10864307042201644469,
+               1539179629859629979, 3357767843775461146, 2101360073251832751, 17234081431682678130, 10847284171622250162, 2314478515498414576, 17530153382031867644, 16210890762511619844,
+               16932765725476234252, 17974885539458965712, 40892050255466590, 13934027942808790590, 6621543269907021363, 11796852321134174354, 16673775773384613137, 3370296079966463186,
+               16962514259432373133, 4639769064050336100, 16965148588326727680, 2922022742538957808, 16752379982369550296, 12896050752492664079, 2708685629936199207, 17894058559833424187,
+               14722530431277419104, 12333728409662476827, 4162946257347548625, 7052045338975163666, 16435875989376103923, 527141841571514699, 8480360258792897962, 4322786951393806781,
+               17366230017999184054, 3121469063237497918, 16903979375392804254, 8204447732627807538, 10469007462907301028, 1938243801077680483, 10156223751968769092, 14290141776757271674,
+               2576841693080637380, 17952976066680364360, 4927209893946473523, 12406446420948698970, 18104668447274679200, 11321546081935789882, 11763004760954725540, 7488613143173641394,
+               7566233859107262691, 14065899052643539237, 17156645465457086529, 11936850757897686493, 17529993825395532749, 17145245039398670236, 17597009579379584432, 3472628483897995694,
+               14380803034817149259, 11042134597430846555, 9992762805140200547, 9895143575678511242, 3228768306004664915, 16153114680219541243, 12036181641761325912, 491369524302296324,
+               6378343037075212083, 4634622317247307316, 3415247351446435530, 5939760313513758783, 9540802244218497398, 2134082884335789009, 15623633842188443713, 6824600547587227473,
+               2021901489047050575, 4365578779519871721, 8603845379677060773, 8929020214929242215, 13010370953605249273, 8071113541575997356, 10681914788594101574, 13369522272664029829,
+               4241327321249984516, 12810477007632864750, 16880581634097860698, 3630333431846970294, 3439918565119627078, 6613942714960548236, 8647431674406387604, 13352599355545805355,
+               12320933424684960076, 8906954611339502145, 16931708732547376267, 6446897311644431583, 13749563256713530203, 11522599770043814384, 14455556215959342791, 9022955938835504923,
+       },
+       {
+               14734199666349771791, 4159865781008764547, 4413963548436270853, 4489431649937855880, 2824856157476907519, 5111945927271461159, 9825486821405155220, 7657332565522279292,
+               8798422177670065832, 1250388939918922012, 5145324733132743026, 3716299737175574168, 14387202892738514375, 10255681359895407489, 8563822744122397080, 18430417713920116013,
+               7857399215288147901, 2593284350589299949, 10086687882410147351, 14407837835956327624, 4469878646287387405, 6845712208092605310, 3019047164798827279, 2760591274816994522,
+               10930605176025081830, 5850835312463207607, 9603163404664606781, 15623771803942139684, 4096748595672894276, 13060617166821837740, 11222939712741281346, 18445178894593253710,
+               7976335583419810431, 16568954524837045521, 5581116346602990350, 18369129318179031997, 1930478946186473631, 14255806344323769850, 5302512325798050097, 10008570767203424472,
+               929118050943456183, 445163760697913504, 7208246135487165437, 13565354217377841149, 3835063466770003968, 8214155842021576753, 2078717035803259674, 12502657820500987763,
+               17741004372977419914, 16320851348541958575, 11853008901690968430, 9954777341381304447, 14274892887030297417, 10721339848307167540, 8731332510371325649, 13676383433520290197,
+               6251805914672095769, 1063060143452094078, 16647397170554915088, 15454955736319919321, 11509235104607349098, 8441647766544589978, 956121464218389431, 10752793912033728149,
+               14879603883666664508, 11158422912437249402, 8667988090392051507, 12702057193823135575, 13234479167199208223, 13752955092077643608, 1117550756888145931, 1184967682872965330,
+               7004802666964716824, 395433501626287206, 16674151908279399004, 2279551165611331131, 18032555740803644790, 3573953642384243989, 9892480504006025100, 2397759375236735831,
+               15032723931727013905, 4176673226777913017, 7270920367565154969, 8867675920919464620, 8174119413251699506, 15030539680120439131, 12325981936900309518, 2932283844656871802,
+               3227890727136855788, 10772277744280338071, 10065219931092397730, 17233706446636791341, 1372997838851103811, 14430098741859995846, 3290287064497023581, 13054133915521430696,
+               3404625123065318735, 11884832674715736469, 16513753127836546671, 2355202492840722899, 2182039060332057784, 17942518439766613327, 16731345075928062112, 5501869092504492134,
+               15704211025163561149, 14596679078416770266, 10262177146233936833, 12443005669252298316, 1541294166390346144, 2952804996209068760, 15358481016273272880, 1321729586231860999,
+               6862865331233391228, 15106279167311639122, 3283008666555627541, 13405610967904725343, 9845239597399801983, 10764942720093673542, 6506992344666983370, 2483131164245259278,
+               9508384588323002196, 4786531415304518048, 2690306308552249535, 12208815515689370850, 5145548243685871201, 1536915039528215765, 709289946127949333, 7152734178531880864,
+               1555309551759198315, 13156609441579560529, 3264147002083956017, 13629162110016732793, 10295903344220946201, 13835148808782379287, 15646840234722388037, 5850505683234532491,
+               13348528763144385986, 8174978337870000956, 261860806345683810, 4561309263594732686, 973813267913726588, 5812176512716041479, 14361848397565071235, 9009461390894364897,
+               4179825720483458009, 3146850391122074949, 16612045757277946305, 5253713786583408340, 5426943015912173764, 17275032103121420023, 8467860410750483621, 18150546576917688519,
+               12762630566060098764, 9762645120146998728, 3635705124656800121, 3295681695622364165, 1764654124266477879, 16610065552429288987, 12182970194869512424, 1144643512390613083,
+               10286763540130161498, 3400614528650953395, 16801086752981339314, 5746334081386875705, 4489937467701177898, 9249554406360134002, 8258038249111147700, 1922443676251769427,
+               5981893063992017591, 11780456280008557800, 6865399120670384939, 6192294124015342683, 12388377965276278882, 754882660516751393, 13476094069874573591, 1000347292494612314,
+               12753947115797128456, 1864834899756446490, 12873792436322150068, 15420857687427067065, 6214698061215951246, 11174167031334850459, 16378107708672199269, 13073812080094584194,
+               3531275996684891316, 11764951512033875164, 12239314899306115751, 12701224435273087197, 152051042384837402, 47099568832954431, 766394328496626388, 666084094458729910,
+               145223485883456390, 2445564470200462527, 6482144922631612251, 2316071592874761856, 16548688346252111305, 342430477320199814, 17819268336019413198, 9112976726726029531,
+               8272548370610798443, 13910434751574602849, 4252192981011400377, 9590519351704710983, 4172183866405471444, 5567646223402949380, 6059725713353637560, 7169982539312028092,
+               8422701298619809502, 5749403137850675219, 16696307763582818287, 7683947097864552851, 8685161999810728314, 15931494353777534155, 21629333141204286, 14374464903502564030,
+               2354260355218724624, 2822702976206523812, 15817484232297668127, 8389777239766813455, 7962301702220496539, 8489354871723216960, 6637394823950686331, 5853452396705295777,
+               5949957329602421631, 18059540496274524007, 301304345046470155, 15775279105880040289, 15979581939040500554, 7142046514802237176, 9965619645220287167, 14369754349691428035,
+               8777708254369249245, 17882304730732025188, 3127583543205765491, 17274466425160820249, 12870181470212293464, 5881181695848312122, 15338161852429951632, 7245877162563127935,
+               2634466441339054819, 13057158409330115380, 7410310056430957860, 16362149248469660371, 1435827663585128427, 8005375008235415486, 10865470829924734253, 3177600727860863968,
+               9627905753364576437, 12776456422166281355, 2851899644189834214, 16998174196920379994, 9001602524188761177, 8960294999163663712, 6580949973363012183, 7568306074815116797,
+       },
+       {
+               13345381996769253014, 6278048669175242345, 15990349685835870151, 16358261962292186792, 8505261070637963021, 9396725065098564446, 15331953351049782155, 16194796339208321205,
+               7076257175157660597, 13221730879315432464, 4499548735964119085, 7559253754663705944, 10196808438730350168, 2391718471837563931, 914409564589897387, 6649744842278078706,
+               5502356275170104522, 12750322860129485966, 9581277511584938955, 3872282844937972630, 13668854758739140874, 15020438121087800965, 4581631138384430657, 13296613956093963588,
+               14380343880230315251, 6834909096379668102, 15975839936772635678, 7738230945027714388, 7971648870467745046, 8320128435052726628, 10820026056424631461, 7058118462476293754,
+               7264036154081699231, 1304060579978677195, 18166928140052040308, 12593450560996175288, 16027666629366472835, 3677101504316839585, 1477956412235870359, 11566116495906585190,
+               5990066097615398579, 2092999434824845091, 774626818169813708, 12815491981614523669, 6993666706115136402, 17707947501239782961, 4907798919001453899, 8644498548438963907,
+               10893744790193607860, 5425031394266373727, 7829758685118664025, 11448863214220512751, 12538690882574195219, 5021176303769859871, 5820297470465439264, 5119144562842414323,
+               11165438517321289842, 8661037418831619311, 4401480924846865713, 9355650368902126256, 14352422544185763829, 12268031594529744663, 17607497268577344783, 12698954426769962214,
+               5383780168621648368, 3613813760948797485, 5757643543708300439, 11434310585555684688, 2345981080034027974, 17817292757133028083, 18327982597027759229, 3812144950722314021,
+               8792386854586041066, 18039588893139878329, 5501406599000558473, 17117814302557684702, 7341401626090786647, 13233670006052290433, 2192568639640447778, 8946253989965365943,
+               16557600339807647183, 3024845786116641335, 415867109882960964, 5024769423994345740, 6707880221250244075, 1889203596997453159, 2063004021323938442, 15149146696320496954,
+               5091534986326281709, 8005812102849517353, 17366496686564185717, 3658878980438307796, 8455810244524637026, 7649393961871195909, 8629386422022530934, 507133797409068858,
+               8757568869745664865, 18237318628906764926, 3340648953867756474, 561136277959994100, 7271097445297070958, 2011054670254573698, 5452809131990689118, 13469888024447314143,
+               609640447772904263, 18299734743899574512, 9082773418653747144, 17312950936823165983, 8565594704932296493, 366163155689429929, 12596423288683198842, 6787120926470876217,
+               18404298100226778075, 8425329164435445437, 7431919288426595458, 10680902470574406179, 7944931189168061880, 9822761000408762356, 794258562727155839, 14627123549563592012,
+               10098955144981013765, 4095621933458866623, 313357785962326778, 14880249056209398407, 10605627454111004262, 7841561005378789988, 5015399193497762029, 5818383539901203899,
+               486788682374900660, 17535646661984222270, 10786441143551223569, 9744277172896797168, 3600223448942144865, 8847805713765285452, 15255336563751266306, 14792236445425212896,
+               1569380763811592357, 16850350231819425451, 14974316825768144065, 2974893813338477794, 16726324408135381195, 15000665607479486464, 886632233152598796, 3783793991897659851,
+               17267037371866619240, 16498595171305365582, 6453906744948258368, 17267405673163971478, 1676214913570622682, 5051819157163581842, 4315279707026326708, 15525840981760267164,
+               829322392873083372, 3459913121476606612, 4547714508342797986, 5801286056105229312, 11591136160675314269, 17965845487226778560, 7022309609363885527, 5990586084398664157,
+               17415594387520595717, 1453256163777911406, 8242859112004661961, 17561205531134219898, 4881570838375824387, 8392772608437744175, 8797957464506597080, 3142154188155936579,
+               6248409301753564092, 912147011448492506, 10413108318416902948, 3349445377400918439, 15887909530347096066, 5138859116738406557, 10990929831134698266, 5911273060564729281,
+               5197581879950405305, 3001975514736631403, 1919678782193534342, 16811100109848336275, 13086769249238533805, 4351245282425706500, 18281601243717625371, 16799537683941038764,
+               6288277991521986035, 12231480617236286340, 8633990423689180869, 13535190275290488690, 13419223868164389899, 17622732596713666209, 10071779220640400024, 9451660464882303005,
+               14029940454474238624, 4957972603307996503, 6311878080193524221, 7485203809274562760, 14450074580092843779, 16845073066403496624, 15870387052570816676, 15700883809468229388,
+               6623653867803819118, 1037643671564549885, 1236506073247459642, 2997396263933967582, 6182371056378366305, 9773995232878719062, 3356495419149379609, 10710833980055523526,
+               9965766500412107699, 16895652751136174589, 7310937934566947318, 17649841370865305295, 5052693369483848536, 8093060855248113928, 15777336335257114359, 4642979535698186085,
+               11761084765182152401, 9226969173242076459, 5445719591917489914, 9371133174853825566, 18381867235964583187, 17262888224001222346, 1934253649802391267, 3574888052111089863,
+               7862401495691359736, 674970329153306547, 14447324101549742216, 15408908436196428001, 5339840774639473099, 15542473999923245378, 17353380999887736706, 17787369898686553525,
+               2301964326759931592, 17775852221342579469, 345763078096690431, 5079606662887837532, 14863722102334084051, 8905941255852264870, 3806200576416892831, 6668327519801544161,
+               3672519063263749482, 11898207454593385701, 2364050348970898536, 3761861796987022528, 8159458273489411574, 3231262679605967088, 17179214124164291006, 8770284079122589350,
+               15270079546607712667, 8471883658965202468, 10333206241569264742, 7414741159725097798, 7709713706668701850, 4461310100162632915, 10099194304024685274, 4760203118683828795,
+       },
+       {
+               7237168574323016859, 17908810107504968137, 16225708127838178121, 11127095986977103648, 9346291308317410251, 7381283458277047010, 15168602815371846943, 9193719743691734294,
+               9607254959726458411, 16837156817186931862, 16178143308706847393, 10970721795101931539, 10840376278605273092, 8298765077094727469, 15520543037910966843, 11484620381947762562,
+               17395070963094117711, 7608132718922490881, 6531178971071758016, 1302814667007331361, 4002629363862769670, 14649492495298089937, 6868174210142585697, 15456170652716048683,
+               3688308493559609536, 5123828159813683938, 6245436817220183971, 13062234263274605325, 1313395302496832996, 4961840797708687855, 4990192311341859196, 5283131006216350959,
+               16952735659396950704, 1249482796824289329, 17859504101404809981, 13260403650830168625, 1583343855370236084, 11389120333403185826, 13676599385745755008, 5066667130137739346,
+               4799264864906918301, 18347145714884655971, 17034125441088681346, 11828378178487279470, 1759038296522081901, 9582407833575609381, 4195817009050503354, 12618256395967210055,
+               6486755100213398364, 5270923715575268322, 9268255346880651103, 3147724493117082267, 16710318779269985633, 1240462642985509644, 2400811796254219369, 13670743068809614358,
+               11437779990773246594, 13609113239383378152, 31268927496646090, 11618772705165035208, 3078024460365036167, 12138983306908962712, 4779157919015181380, 11901698850260672002,
+               14642787507945832432, 16258081639927585935, 2560321462542164242, 16286882196975458174, 4328159372518768969, 14313553865397841147, 13769372656320240568, 8950675126435331579,
+               1309709344837422378, 18403288028608342631, 17102350491414677993, 1133523394849437315, 12526496222782003755, 5447309058259018864, 17311120581405946631, 3760058661125144368,
+               17891474172606596407, 320094264574086461, 93927075222964142, 14355817838636249140, 1777882427773785068, 8237021421587560510, 11520559469641852991, 10567910693910023157,
+               9164300764173563614, 12322279811717869943, 2768902015676238485, 7761799112151133995, 5740162933856370894, 8043946608495226840, 8923704438836381869, 15189322655373943849,
+               12046275966378825708, 5909386969214935556, 1201990704907881028, 12128549009950617306, 10773478878317625320, 4554854625564648958, 14029736945871573056, 1353247251064221090,
+               11909123603272307101, 5517949035179831783, 3295386484950432959, 5605137795524476293, 10718654547602473221, 4984952409581272095, 883267724006996723, 17328431094026829348,
+               13671210467347025770, 9980617617519781731, 8339868735163579231, 2150724314757661915, 8571153021065445899, 9146903697769397191, 9122246102814640373, 7744779513085605450,
+               5733697799130763963, 962857090393715865, 10538932452511329419, 3413281437172590207, 6635428480179771287, 4404718679994229138, 329074170931436370, 17746708206910902139,
+               465623292609655544, 12740391094094156750, 15600221933467635716, 10712500242632508096, 4760789577759901270, 408323003115848014, 464706673403009712, 11801112998381624421,
+               5545681129476190458, 8725689673989867696, 2143812364199804063, 12133065347666807143, 14072918710585286097, 9027361966934517640, 12608281386782336413, 2053972384317260152,
+               11862793362110657447, 2615766363986534825, 5065170482898519596, 2878903691735623036, 5204682974850023849, 3382494556217615091, 15421437169807703253, 14936317525837021790,
+               12363228588136583724, 15035239525394825264, 16312817933687103988, 5294641777817034798, 1197907056067071148, 13084871057903003628, 5240492218216802394, 13798739245031559476,
+               16167519903361647970, 13106036157861122437, 2112866661358918425, 941609107359251234, 7240286582201258992, 17783018133711208779, 10433192833270769862, 4303514224506582113,
+               1549168540255262874, 7958641388293572779, 17867057222043259063, 1752211085999288773, 11828273580240483781, 11712913016012991853, 2373360154803731890, 6779610934665321824,
+               6633997178003959408, 145323909693817907, 2198452664824754574, 2920221908918689777, 11047294234593305837, 16840329825128198329, 5479733463453508239, 14054694221361300990,
+               7908792292118068471, 2703859967221946473, 6268006869726038724, 9406994672213611166, 12424098071734234719, 11900750387777467409, 10724482893673149484, 3191937460539390989,
+               7635348735946750413, 15019610708452651937, 107671898858364780, 16808612119435524257, 6120109999123152232, 2251481693156523545, 10792076820325151003, 12924551065805570215,
+               11225852067204798645, 7665324911993544151, 10402215331683389905, 2856131542917118235, 14152013119539822346, 12731746180172488022, 16402457225039188820, 11129045951416314666,
+               13009066459618795885, 9636541685854928780, 4783713672495759319, 13224924194053497016, 8044695420996588716, 4054951559323242873, 8718047667110955699, 13479622910466265834,
+               4333570709684826136, 3188483692974505359, 17976757824852085147, 12585927226835238762, 16665346689006249776, 14033419552450595393, 12216049696243171604, 447536030797427204,
+               14100792221456700414, 11757964686555543320, 3971513799111193530, 224065891283865758, 1282520657830780512, 9120233956471705454, 13711191981326748211, 3725543277190035504,
+               12094220323799678341, 16876894723130932646, 14806566188177921577, 2283878370700345373, 12254260799985999571, 12764268124075139223, 2425316412794046071, 2088679341162220742,
+               172600248248909168, 4338060849169481673, 12046085844143054569, 16220699277291497444, 10358794035289405365, 6739081270984238196, 16079387007561085178, 13471688054064884318,
+               179238781994802586, 9017860544212172426, 16179187983079961859, 1380105261896053495, 6187003332254463653, 9896593306091975718, 17181949235068293496, 6820143159816507763,
+       },
+       {
+               11156900805411912784, 1737275748212365168, 16993486692205800040, 12538938066475152524, 13167476167764338790, 17373319366642541595, 6054831428930905282, 7118452124011953000,
+               743288751022377974, 9226164090128370715, 17669221687181604232, 1117842260351396541, 17697784451833850722, 14382209306891991103, 16951372733687268016, 188390802712613066,
+               13268209255833199938, 16633146482265079265, 6044233937395578074, 1733872861371247406, 14239198956565602758, 4036306057099495106, 1778912298053970082, 6174082695927204648,
+               6390361653475754940, 1093882175267357438, 3784079074949811167, 17343872969822169769, 3359715652121662979, 16808529787251986583, 5169730697018536870, 52766949850965558,
+               1403521870654810721, 11668153767441183906, 12890534559297323775, 13255750643204945388, 8838011266491753399, 8488733891344199335, 7468199299966346977, 10645543722243906719,
+               17019046551094178629, 3055711824867115856, 10841870683594132444, 382072777978364200, 725450988418371589, 12501774248954630111, 10130164067258601487, 7823254091037946722,
+               1866199290196467180, 554488389245696218, 15654194385091454776, 6131785419830586829, 17856850737824439617, 17602611196814472081, 18244498160243832872, 5819736122106091373,
+               13147212495082910072, 5628914243538540648, 439989514095330941, 7620472329041817834, 4272251824771633288, 16564977601507013119, 5441117136715882317, 5622571730905974389,
+               8706277077547369587, 4848592786700984858, 11350018329458740004, 143688324288835298, 16536982722430328270, 6522962371020150117, 9511378862712142567, 18221873727623821967,
+               3985496688414455558, 11118602672015528143, 5383196298446424580, 6116994806363767576, 4051800833472889243, 12236802048340231756, 2619572929682123355, 6008593592518397571,
+               18159379849046931840, 11283007389905902377, 7465803490016928282, 7730454089227756796, 3569936088077890000, 2804205711716327520, 14107136042131448408, 12050401455009236937,
+               4207421531032215145, 7924589143024019458, 5496622772676523695, 7061817399179278712, 7371689806847905735, 8282663810521090335, 11422487361383982601, 6397294642072086677,
+               15924576759579234055, 9923512276109397968, 6142441356128988365, 11189756906743802872, 17790684027455851021, 14143953977451478354, 4002828116425422775, 7521923183240026608,
+               8349314793194266723, 8850246337652136896, 16635419760398709839, 12466509089914036008, 2686508850003621675, 15822032015692543407, 2211302095278204426, 12550915236378020964,
+               3844358527917324404, 15045102416646491178, 558560187822263769, 119801275176287297, 15593003307431898979, 12817356186703401527, 531419248069516921, 7957931139148417935,
+               960381383357168877, 16774709963697143275, 17896181076874992240, 1150415168189819777, 5498481130530161530, 6895900060791069290, 2079514944189747822, 3428689507902936354,
+               8525743843643076774, 6014251588524085384, 16423924202355808346, 2605496565158241796, 16676209604549923678, 4870342652354143869, 8337072895802905281, 2478197702680510974,
+               17076629945963768258, 7647523525256473652, 3999707005939039144, 9578933944626939348, 10469359763046002307, 17515033080264359276, 14272203721184987484, 9979666177276073145,
+               3896303254672567310, 17167309259158926479, 13231865857998180315, 2260217573257466310, 15465674863730076330, 4460025914284098438, 718707264700157542, 7215235109325196153,
+               12056920178557394302, 5131253251712581899, 16251877995882633963, 10883064494054484051, 9473274815269607947, 8874308005470196739, 4412709653190846630, 16469366225886156991,
+               13309932065155297376, 11504232979548718747, 14366229841750030472, 12797870458094162590, 12894694064456675527, 16977997035748966590, 15080606548583635864, 9292471759789693596,
+               1226107676031264801, 2683510924831720521, 4344623677417870872, 6581244316153602113, 12516966236091151915, 6758725397469564403, 3190083750600883646, 13018714111448482165,
+               877612159223846777, 1550479938877814973, 11850498481046386377, 18144061425551419288, 6811504328538189985, 16351446194603329949, 14495016749549056145, 15394017693349630053,
+               3547198835521135552, 9940690805769919242, 15170549880149605690, 10701681269101530298, 5914809102954412895, 15790219349994701461, 13664049285300230863, 5735249081148743651,
+               12395092509541605535, 2320592554345067500, 14213227630916688382, 12847883717490005600, 10192971941898238362, 18392117086623245662, 14369915478097042954, 9636190568462370402,
+               13308009076055104849, 9679299541833059768, 1512845037409468381, 18211703514703978816, 8337549295001075127, 15882458005321062689, 1212364284844818969, 13856780176955551126,
+               7602636613718406141, 2678224565451628558, 6976331354727208830, 7414684104929828967, 13536889690553324858, 13086024708711030952, 3748455179863046304, 1853373561223967487,
+               14753645881295168970, 9410794713982813264, 13485977523338061503, 14267793994973767571, 15813187206361118954, 16449603969001878152, 17705410933007144731, 10960511750491378082,
+               42380674434071200, 10068881872338405083, 14327149378182272744, 18264050153181932597, 8600790433943161385, 2952021171158508784, 13461070885471956301, 9633226987835715039,
+               10360728550079953555, 8471248683929284652, 6673003382103023756, 8972723925695500528, 5941683993959582947, 13500073059240140624, 17856131583218769324, 16799784995825923732,
+               7292102941225494742, 4807816512907139693, 11271815982004383122, 1065441269547643077, 5279915279332961503, 12100441009657772185, 10448964764090871372, 2944169874578456259,
+               4669722990542640772, 10017368027073540045, 13392819319228640800, 1070815632453829996, 7274130058405640448, 4460835865761538026, 15283885107956150892, 5815884817303156137,
+       },
+       {
+               987127652983079722, 6872208513691823695, 10110578719299008714, 16457381243184327116, 10779072738879347999, 5965282398006505989, 18251577267494363268, 9321323379108563422,
+               6119049170407437179, 12938407708038792521, 10105420405825346383, 3416306788177016826, 330648587825212481, 125568991290568141, 13857127346570918649, 4376080986981308805,
+               5930434126597036589, 11240994623469578584, 839346533006694594, 10015087329724081709, 6285097815938761787, 17244606485954860090, 11523249727882012981, 7178451948850151803,
+               16733615335426327004, 14833564736134873977, 15736159435317472941, 17560193966711884894, 4670172300306758374, 9477713670983496835, 14243955354032737980, 6459864769649694970,
+               16053517698989562256, 2069464650596796670, 18305730134729303993, 1090863611964008044, 10595928817546105363, 11743183506441120484, 8584767248013363683, 9187452830514379903,
+               6938579711827578880, 16268282168771714072, 4567473305742437221, 754548046014059669, 7773636946295303572, 8132380485366854656, 5054542590195827722, 6074347500754248128,
+               3955857908381474930, 11852678900999621852, 13783017203403417097, 13616745777931267488, 13189924588414196918, 14519927295809952876, 9334100965942760501, 15172548734242885286,
+               4869852132020793901, 14921212823114724347, 14342559113353033349, 13336827701782657309, 11168346789878684452, 9790480725902426052, 9171116079841529936, 9268902731763220711,
+               4417372365016540659, 17280138652899703220, 6650972319709075180, 11252221422799491438, 6825784270383052414, 18308562203755695191, 4237445205082731447, 8485872406483449772,
+               11718726714045105993, 2624508790343569765, 5794111482300008213, 12819216567095091385, 285329842793152354, 17257707863943097374, 16912487373614458842, 9501952033607497057,
+               13074643344738491288, 8505193022029238118, 9932652098552590323, 267408114280737600, 14802861246220332716, 17506028737327736269, 15929083591675282371, 10937680132245212187,
+               16688733766460131050, 12777635326299184071, 7769405825716531061, 12435979606514844725, 2767987141420672349, 6723940414217341603, 16114182069580717377, 4541113259200434040,
+               8506371389960537559, 18031198550689409305, 11510251852995503442, 1923472385053944821, 6189904387119195613, 345664413118550356, 6439003191582953600, 18344385760549575361,
+               5320548958745018096, 8341561189829530680, 3327828110998403156, 17981346269177513223, 14254804273025688074, 11111147827704077234, 9093333670517437191, 7272552282364063165,
+               7587268797387514088, 4402481408866840263, 11260815389095334885, 14391444701764948710, 4224880318604689771, 2472148458660279030, 961218007313548745, 13826356220879831691,
+               4477325369345373420, 299141931133875776, 6787652129916359301, 2498016036564260464, 13342319943892943548, 11124287719737492205, 2456333599771808442, 5084719026388755304,
+               11208298545009109072, 9361672558653085726, 11597473974277116433, 9123409098329262113, 2315750487079392743, 14788891796020803799, 16477373474431052867, 6394267218565388055,
+               15099803091969065643, 7815556206466442264, 10304177785190927723, 6493522556494567776, 14386173575053274652, 4399768637448990408, 2996083572119906777, 9762267038999270167,
+               204205141115459509, 15145142808374731170, 1678672167166598389, 12032976094920574395, 7472791648310888425, 3687068899306742850, 2661021646792225638, 13705804163602287184,
+               9320611303424530507, 7295004960403065170, 15749376924513664173, 11543669941217924178, 3710258597217352196, 11371260298937340150, 3902566672028686120, 17983841473999282668,
+               11814188798674654097, 13017429106091059634, 11079902218909650978, 9064898043690914606, 12023954026861289442, 3592879256613061321, 9997625973577562433, 16073808232708438680,
+               15365030910001289574, 8789654976305207659, 3460532362538090307, 12992239135084766157, 11449242863169591803, 5418502644558230048, 7981056000757137731, 13021725301900406539,
+               7782773734814780443, 9390379677704432300, 7130223982341575476, 6496906770393189740, 5095392170846288421, 11058865093605824851, 11021902438459302094, 6088242418938968652,
+               5966014717657529537, 5136588784988696205, 6360472729290909457, 4447169061266082500, 12506934948427595318, 16433395045878253504, 5116318868244944213, 6640832565780621049,
+               4132920736998081103, 11827975663170283136, 379030309731223785, 3149051804072184938, 12035317616979166548, 9642536337674500310, 15531497803043399747, 14399049832547796531,
+               5493097462539196248, 1629980144571354138, 13641173578972112594, 11096917099468924214, 10934169048860132281, 11269991112518485434, 11206050457519414207, 7939067479736521906,
+               3806755078949823895, 15988975666336042818, 8246267395645554105, 9703363749164024623, 7795606269507901456, 451102251659512683, 5865831186929065346, 81064915983990550,
+               5810137226573964106, 8424253088401255706, 4543883508937971494, 7386148745257823512, 1348150366217548727, 2103092839740150931, 8353010273955146981, 16831854467863536537,
+               5095778754322493440, 16577416628492146129, 12288076721910512064, 10563487622054214075, 14620553808255752273, 8159958565993701874, 6712100880095874267, 13203797993773281759,
+               9640010815039549413, 17460773950401928956, 18229977265837445092, 9252634318278265623, 16798979334068219458, 11731856767337519419, 1551975378671663669, 14320102155496153821,
+               10528988339881191052, 3808685834232068820, 1064376960475785008, 6466670187430364599, 16860839938395945578, 8876458447995837267, 7897541112736965607, 10283235741250763328,
+               12246932755942887931, 10842213418139067847, 1827392608284960926, 6961756951208563550, 14626966634382828071, 12653808277900379805, 3359368990539585596, 1190255644328095727,
+       },
+       {
+               10836955050615624183, 6228108794259714192, 3769609579318360527, 1481673673659326756, 301329772189110029, 3574710782304999603, 3037244905687722509, 14442941761397229485,
+               7739110373965523311, 11019153332996240080, 7346010155518751797, 14853737521111213548, 2542883237207113209, 11015136828834421504, 1998601666328316353, 1540417751495800469,
+               599034134015360884, 11263317530774995092, 6667501365379084069, 9844276013103312691, 7566306886180438990, 13702768345615509363, 12525031963170717968, 8463786212988210464,
+               16430555432520738762, 11225321696360643709, 11777973654353154098, 13133115227828884393, 17678738157022850345, 1586660156856830642, 840647763693221003, 8645742354464326466,
+               8067725618510810414, 6229041032854057836, 8025364837156161898, 1290443646630661359, 10991323655842003728, 9346782840170054789, 8939059450584871902, 4772347025802041241,
+               8187379062828795656, 14744366698824202673, 17014663804743197103, 7704635785366672415, 17162645929628468457, 12942442527592695216, 13291710923558633295, 5800071247768119960,
+               3552067877931717181, 590108493628737243, 497390871097272557, 12785795808441396281, 5561451613221796230, 14263823913216836845, 10481729699001112354, 7818094022046194698,
+               3598736754916501501, 4827022662021197854, 8203180748141933720, 10283251600632599041, 16186680658340956808, 15183393398087319142, 8714402370450665212, 13217902016653171217,
+               13766344083396522552, 3843491774288631026, 1174164282483810421, 6398024882371290634, 5459580537585379131, 5871096222069618377, 9611875286525007701, 1940221124144536452,
+               11598781954647517543, 15695098933552070478, 14976427118847622464, 7147358677856872160, 17135524627354123951, 8338407198954935663, 18099467407613897492, 9025371359994313919,
+               11451018285787631498, 11710749546511767589, 12969419493657624536, 2338911230088800542, 17492614411321910750, 15274296072504110502, 1258801445108685875, 15178229640559232741,
+               11743016372336018414, 6125536020759642301, 16563280170798047733, 14529052521060111789, 15253502329174644388, 1556763737841306861, 3041940064290508531, 18020881359462953336,
+               3035547704692483898, 462291414338050452, 4209186193642705826, 929930084709639338, 5246348806539841852, 16407585218848843770, 6076996892610687611, 16547395936238439809,
+               7781914900266335582, 17967080065814694611, 14677062197599091614, 6667353926398988267, 5658765839564756939, 15807817354312473921, 7476371642206655552, 1194561222317134506,
+               10645607622061780068, 11583886495890779582, 6879987349345299140, 5119348262235800038, 6546217876212430196, 5534845503308945424, 2003680599532879233, 2824480091030475274,
+               2297585344913389180, 13965959247788377604, 11341378863608387800, 9890953382689640379, 10443523266835246852, 9631856696811288063, 6944503116553031744, 10030824122780966395,
+               2699238910420203023, 13176131497943324759, 2961070701879546988, 1511208990650977146, 13153451530298458944, 254163587562261430, 6668642257003911712, 9040693998431169077,
+               5596789796292416136, 10505785820531892681, 3803057245175025164, 13601446877323203658, 7939638174866660891, 14141848241206986005, 13782885912650943563, 6287188921995938212,
+               12999700407775352603, 2664314004284450753, 7085329252118415126, 17472483363754271126, 15550759073378819069, 7572177503239633527, 15705617684783232308, 8586972133880335199,
+               6636244234467769744, 18284390012667441869, 722929822219329257, 3274166388651987221, 13177791837760949480, 2568122970128111127, 3477167651270374316, 11371867850093288299,
+               4065583279544717744, 15575999213135020408, 1319417044854511604, 14713082471342741360, 9399053450949627084, 8900637792268080986, 13511414538589410393, 601556817111475086,
+               9243142430859561073, 14638657859832212223, 15324499241122936340, 14477761753578941934, 14699832840191454785, 5114873517253108658, 7427057898915535537, 12536800031182849473,
+               11775949216482616439, 9736654184925478086, 2941126957776086651, 11331303510371804917, 3535865528819665754, 2488682969529955908, 922100556888217739, 17904958255578472855,
+               12876460969864886954, 4692925517843901006, 17390372170975588763, 14692578774429957295, 1759864963511373267, 12016553435172103063, 13015881292003590351, 16187569590073958370,
+               15154092100094191059, 8103665941237580228, 3265383210728928809, 8341136973870067643, 17281635732314163959, 16433737305161442677, 9130496888060417111, 7070932927684908859,
+               2129695226164849659, 15163429615374108928, 2225893409909150746, 7870945454511315288, 11525457118388411301, 10519485231888976311, 17601979933176863246, 5257431126828903605,
+               8898009465920717074, 9418463821940622934, 3166596280515383312, 14529914354665032916, 17743784337460844568, 15964972678726654742, 17116339264937332927, 17098426671353029801,
+               5868176722765418764, 8429364877332796959, 7785756492654137899, 14975349488807886278, 3272010964035218775, 8946396491617515063, 3774503492701710541, 2113917870331282160,
+               8185651664029868180, 7343199417670698200, 16586532029502206227, 1531724981369431299, 5596507566645246686, 1033673521199123313, 6075312368002387319, 6988496924054716781,
+               4604669688530289732, 1867259042549585024, 16180237500272383882, 3296394050993129267, 4326520583229998770, 6557569103657179065, 4126356691591689646, 8674328613473447843,
+               18057076842177382833, 13020419432300857029, 13646402493577420410, 16962268104464192344, 5358581430340252761, 16443104373870300795, 10099216829282619724, 14890543634568831960,
+               13276631120161396750, 16968574704982977753, 2376454925072971568, 9477134218094425043, 13784622991820528988, 2074505569780291922, 14294803056569335889, 8759684036994631222,
+       },
+       {
+               16549155412115374305, 75977962737081600, 8870825488941031605, 7403557657089993256, 5825394234709429518, 11978746413791918409, 1876293130790608838, 9416631623519692610,
+               12346821858361333862, 6352722970730511156, 9920942104315084988, 10492373916708072181, 11163323626947992791, 17035282992056675772, 835685192553490421, 12792459312570503983,
+               10447922451077327640, 1515090998837129975, 13498807582085718212, 1212623301098019779, 11573518650162536086, 4823461685803772444, 7289704908733783271, 13167881392748327839,
+               16959954449957105311, 11051594981465026138, 16062472412226411858, 1976004115345602080, 3630495248560019222, 12698191555196404138, 10107923614229901155, 1597725222698864118,
+               3416019089997140849, 3011417601086561495, 6275242351124667286, 14197557183081060761, 5633711018871057458, 9723496411345030748, 13910057756335530832, 7285051335492395815,
+               16774605620279328247, 10223834398868957807, 15781733027568799739, 2607095622729296315, 16499590296954181006, 7576646116121533069, 16638313875339315529, 14296194207652471696,
+               12874411821611501068, 1998417862388106640, 13882642435422318946, 5791129521978463837, 7512934139125398199, 6966283273373526248, 5475728301311080129, 13542211842758381589,
+               7798993150530415596, 3288770257171840452, 13373286069558329631, 9784279046496345014, 15725032660238528813, 16038931923358478835, 6921788930154218900, 6093507035435214187,
+               12194839527972802101, 8376199250979271449, 9055995864116790217, 8125030124567662718, 1070812422878398727, 3950906148308170707, 10121516919638719072, 813471384549762068,
+               7610605259962047827, 14617655900985224117, 16089669078196617440, 10594009761533811214, 3425971360520359121, 1245021768718221594, 16690372892586114152, 9933179766195044175,
+               15142732720676276463, 17435583143726694663, 6030257647680338377, 243683009289621849, 3064238900429394982, 7655019927497549159, 4484400084400458429, 11650860345018651068,
+               16203650576183697977, 17614744533772112337, 1119292890050870301, 4574885263986729787, 8108207498737924504, 9708434439316056191, 10676823369888368482, 1078311554675991883,
+               6876202174636220158, 18057502510666060150, 7821730895845187783, 8882321799602877790, 16220624224336230256, 15562800387021280583, 3043825293109091520, 697130162105054983,
+               5394549491776704087, 14795348078061113966, 14206080764200897220, 4623073019242398493, 5850602047109930316, 13783531993760979209, 14764346975698048641, 8951680172224205890,
+               7302725075484262769, 12572584665857403749, 6499691362933905099, 14476353114356185371, 7381716148644532401, 1573798302334388880, 8128390307766282880, 14547454176248589604,
+               12109367644744157376, 18037756988516427980, 814572839386760074, 913616818805172815, 12974490864633240943, 5228203788953366069, 11458421156905635350, 14534725545904442520,
+               7717994192616957513, 12204841747568567286, 3911093871228418198, 11236736110419819217, 3283907124458179474, 11742518530965881218, 15033771683298452989, 5201173013910789542,
+               13950307561490203211, 2109530041534182225, 16966608361725322273, 17050013487213560977, 6582524050666171954, 8348662591649610062, 18257068567217206885, 12084557407109908164,
+               18134052713971906645, 13522834551049471624, 11796035797088472898, 4408384297249203940, 13184035659663315829, 10318594606381671372, 43784547091343099, 5864759723778872652,
+               273751009786971880, 17433500308695913052, 14095169299451888252, 9384697581863180516, 3670310635026975567, 7512955195757960238, 1061441390592395566, 8687976820410979119,
+               5847434943730572861, 6139588162124989313, 16640425042872222986, 2868461478718351559, 4582082172412426839, 15999623457772192080, 3911979819012561187, 2157661418664981538,
+               1679437503202036379, 3357369754420384657, 14227038694942012893, 10849243658636382261, 14698996273665673323, 15473144682787301630, 12886363027445513063, 4218522843946321369,
+               4305571301049736163, 7569433164869749160, 9286896219015408706, 3061813620853218759, 13836461093317197944, 12893856993043908140, 17368798334120212403, 3507360881370918016,
+               17887381848254057882, 5080557806347717197, 10977337278063191668, 13725230338861893934, 12618602415751234016, 7913767807930932665, 7119689779124353718, 14253582440914432409,
+               16180079775228731323, 7952167928403988663, 17529082815577219791, 14568667835887326401, 80331144542697157, 16190739578357987369, 8688615216852085496, 16668129019590270615,
+               7430615013050690552, 16490141830322172211, 9793941851666815428, 12678643730925993658, 248986629347794843, 14250412400606998841, 7671639316274744213, 198890803142183275,
+               14099347485199617889, 10490379547566026579, 2979540189595374423, 1947868558918413664, 14807112327541983728, 2275659819146309375, 14464189275380358394, 11448352451702208893,
+               6508543885912264241, 11768683250765503158, 10952591955476802447, 13816638967602836229, 15422608700909569544, 2270147616630940233, 11179267547770249728, 10448962907285827304,
+               16734703714440778657, 5221611440144584595, 14517195248502569256, 17256223341936104100, 13260411672715241049, 15406026631864099983, 13737383554048659263, 15455560302156741675,
+               1751310744149771156, 13066379976997527874, 3353407191478085130, 1488844206746128853, 5630044290904406795, 14205180196532348798, 10021323252656730909, 4177092513333669169,
+               16120743770319899284, 12307096057555293266, 15459231763664176764, 889710173957193674, 4419259815443372538, 17256024223837463177, 6105822529166486288, 14459703836399905847,
+               13918155529832261002, 12953608416498491778, 4285102780598248527, 15853935066983430239, 2610351403194505517, 14905969693015035277, 12043976761492019990, 3883507340167876094,
+       },
+       {
+               10994470105201067642, 16033352651464686189, 15774427704233149170, 4596106024708523955, 8854068685612048031, 13529126595187822090, 11509928293490788309, 11620850709434334690,
+               2068337952936280662, 6856444059219131741, 17213926210819196459, 513413453513211652, 5520465604253824995, 12970886588014924605, 12296275668437451137, 16808287251356954962,
+               3413637388791433603, 16937929882486384885, 11215805046681294327, 11559398419268924015, 11697258172757450737, 6137795229387768085, 3190984692021653574, 15347236891154706739,
+               17955247196574331290, 285928599571507431, 11902987704297070981, 2841167725097799100, 9281167410796848363, 16444340476026142274, 3423202423051178709, 9101021305726472246,
+               7129792976024548817, 11116052691850916690, 13765136177550464799, 15815419857669199536, 3490265904262366633, 3075105190264147815, 13090337405102529529, 3772589223509323910,
+               1865569627339845981, 14405510401062639678, 16548248891153314376, 18134729633170718083, 7342289204282809135, 13678804825671892797, 11309594694670555920, 6482941613725556691,
+               15861081392207208208, 8373665453512079014, 1489270058265748447, 3594001972161344915, 1115942979837741628, 11080512787291988167, 8129036993725083225, 3358115086982889477,
+               8869273893561412239, 10349812081309865197, 8913824872487209090, 3148808685596180274, 530908416884501807, 10284103744075805979, 13606889938905754722, 2418062398586758364,
+               12413212040240282991, 7478703750955930147, 1623142090654002287, 3800351594986125089, 483782039790230646, 7823394007049468275, 7643246613581822171, 15001087565682987468,
+               4027740097060141621, 11299467443664320327, 11151439614540606708, 866223440636939151, 3440384894029167420, 3873155505711856537, 5954029035616033594, 15381861683078360474,
+               536906646315848696, 4762701494256722953, 3244970900590282998, 13809219136128336072, 6259009038800226590, 15448401588227595780, 5228638796256712654, 52817644221507266,
+               2298603653884322501, 601221199968240092, 1285112712738261659, 13882709760355308533, 13563254433762438170, 13447718334658435053, 13493687958886238103, 11032778298151679283,
+               17130548285854289846, 13389656739579236890, 11825243553071488462, 3295650559395515332, 5681593832990094932, 1986112566735995333, 6900923912677810734, 12885634718618182763,
+               5991348986251844787, 10652959958005297329, 4727138097613835700, 11665606181484659859, 17818486388489237050, 17381457056943650121, 11483713831771420728, 14346336385265122549,
+               6806904066777263417, 13464056321884738018, 6982639430167685380, 7669355554060154277, 5859444273628884163, 13073052226541367148, 9082949662405155834, 12390918296713433257,
+               8626760324117733843, 16403951745962159364, 5837394731212322914, 6847167719031297053, 2888142337636247281, 3409818743436360750, 1677113113408664401, 1222157560539217476,
+               2099068961815044779, 12562181036171628906, 16101890713848274666, 6017764396716978009, 13064414845499489050, 8419967306079989759, 18212218073753486044, 1008986649080828268,
+               14883940931343463293, 12319376897638542821, 12367185247284838739, 5861252096374912155, 10018798299303262817, 6422772579819453330, 2070123940915480886, 12141302052520620302,
+               7347211048650261526, 4324486111460763452, 1238262417801832007, 7620393213816116173, 13629115925647807355, 17975185632155863015, 6751253893269214002, 3530207280414557051,
+               2294668553308381923, 17165287249067859297, 9897724011823072967, 17409851874231284314, 13888575318617508639, 12092766090379658603, 8412268183255186961, 8046572777745318483,
+               4493498909328627892, 14652253245762410953, 5345262207345951514, 3970988687199074488, 2208768899312608620, 1510839623981662369, 642580537527653605, 14940785106713466054,
+               12480576687390709541, 11249304546887636239, 6075047530003410694, 6121669232248820705, 10309256543424460776, 101796817907499847, 2110451750984093184, 10778335615512351243,
+               2885395260584376454, 612553588199732392, 17978615338185945515, 10414937982597482385, 6078565000469652304, 11381998957121196965, 1536418226678270090, 15114446343888525079,
+               13178439025428734594, 16388038968589028071, 16165750006742628176, 17903639397633243161, 9560319088110737392, 7888974492854359310, 16116323630343158496, 10177829649622711030,
+               12866004572891901059, 10190228418101288877, 4717913135317392922, 13460871068228811018, 4756401774767581561, 7711771325649205249, 13695132008344052711, 13361851345229950778,
+               938191787235564236, 14328703178349042628, 10217257468952800498, 10415924210674864240, 7171739159943819214, 6502538915112206091, 3300616451202954689, 9576887970605726107,
+               17259872866446195810, 3694244894150718459, 3214322135693408389, 15571503654130046642, 2332159362399220208, 14087696453363417437, 14318693886833071484, 6131092646618026480,
+               2378363646789710539, 494954399989334038, 6915496914984330558, 757197055392642378, 9097171378505823650, 12104288338329241488, 1905673690814481722, 13011078677095066032,
+               8123217305309052526, 2527408826476194625, 10072980201182378784, 15489255866670747761, 12978131276673936002, 8312787524887306087, 13561211528259491689, 6311660759462081662,
+               16247831307849916845, 8654394682758927217, 1180998443932568506, 3847327552938166714, 17658215545137701161, 11975413369861829206, 10679985684889599173, 14928266362876119222,
+               7605162785889302718, 5718899840342120733, 6057249397801266401, 9486440247354542717, 10618370743126190918, 16153494357430969850, 16785070420314699787, 11277000340020413902,
+               12712274459771886808, 15748114764509451764, 1994630377849062253, 564390855806287868, 135493276425567450, 4305883520257541088, 4842008929542073044, 7035106970720249617,
+       },
+       {
+               5757832545805155636, 17609080533053427627, 13855662030602089892, 9622498683452213297, 12281586442064581946, 610529441714948581, 14740357477019436626, 16983190111725558863,
+               8470173855499872166, 15915210069852758660, 12368087246231545517, 3867174158581293223, 9082358201271846042, 16663463402757176964, 13740908859955866819, 7748969412274962298,
+               13375424826931892789, 8508645806391261552, 18359272328758476903, 16433208398005282080, 13071423254987294580, 7999383023651164492, 14514701556577587750, 4848295889377673720,
+               1020519568493754982, 10467781020270669620, 17607771250627508499, 6620300538436640218, 3858527175523168333, 13798129597334232823, 12495322651937391008, 3926713306087152023,
+               5116038770086590715, 9943789276328255827, 13715439407309914230, 4887040860130243503, 18288477612078228131, 7640050573721350378, 14537362862524718973, 1658575506924200900,
+               18400486168653423966, 18026904540891591040, 2037921821724043966, 18010956304511658647, 3751340308708032971, 16275459031633957091, 17177866831427164840, 1635431811339422016,
+               3897330996014812355, 14347736534650088376, 16862404119462964612, 12216005411754788835, 11561909516001453735, 6261639657930189859, 9101978764314050064, 12280333151331067982,
+               910276569977357717, 2872810615152156462, 1942106118995935911, 8734004121981822024, 13862118436432879698, 1912639548162720505, 13060137938875924732, 10642216911059510120,
+               5132232031613377471, 3053931945527415993, 2695169719602504430, 11855046366025891084, 16462491222215366712, 16664416596202206835, 3077124688577987843, 7109495326459366311,
+               3858762384693274897, 7520194928987242278, 4496744297661574884, 16159343214247089321, 6441167128044578145, 3604951495694157848, 3072075325567814428, 1964798869371174506,
+               13689578474000942304, 8998724267038772595, 3350174507425430811, 15015413657749135511, 4848907595494161497, 7935644131326131098, 385849363817229511, 10087353746314516691,
+               6067717601858189468, 10438404859927821308, 9991403870358837471, 17728358586134467771, 13476949968946830198, 7311235997042381570, 4429835371823736972, 17463216455983091974,
+               3446799583712077997, 6763499387263152328, 9231082163128267527, 7733182914440272884, 17225092062157610409, 8163842076250628108, 14230171836718858439, 8195740716303697476,
+               57759226194841354, 14962480748390190557, 2047254208877381876, 2830450574091058648, 14905486147404440754, 15792397930637469157, 16383409053580142957, 8686506861607761226,
+               11120178572139812895, 11534611317577597022, 10437856602660752754, 13925966850017814278, 16776862023867799947, 17362554889424346260, 3408825299914455645, 2606150045870067742,
+               1119490156854665483, 16772836556735128526, 8607715508817325509, 9931017263385440911, 8799481055779587022, 11740562709785257943, 1956849872282864970, 595288629437737005,
+               2281206023740505682, 9926719762453358166, 4061056930877891291, 15576657447058286418, 2614863633636977404, 2206334532799385250, 3474210873232711865, 8477734925846980028,
+               3340305349427486363, 5188523629566097463, 6160790887356413747, 9863988255192204305, 14066826366866912046, 11932779567129411871, 12863116515340321220, 15222969978942513045,
+               12758642615291604404, 3209096496454847183, 11182564090025111575, 1931382908005123647, 15151007707308352245, 5954868822601995640, 15742433078711209582, 3347972315985628205,
+               16490337555999239547, 8990885971520264447, 10360258506616249745, 6630482203535351500, 16999397485942558889, 6788531264412870316, 7229988042452941955, 9856917486277085502,
+               10734804718395003162, 14385908274213668346, 6022876926209575383, 371182857232839872, 7412466195447558077, 7961511694540082231, 8030758761844457080, 8046696009323575767,
+               6399666206029163609, 17663811097734928631, 11470778017516778751, 17702646621253134508, 14876192013866833082, 12935280981291312476, 1467399042175927183, 8848908916563618579,
+               14359906986235888744, 4587839368531771442, 10497105860390751463, 14244616431904836676, 14906421794748569105, 7955760173743833219, 17152550002849021490, 138081467951201370,
+               2349932829525749283, 14749355610935637731, 14751838563606808702, 18058355029195133983, 8461199524627795693, 4219910612621001507, 12776964042319070094, 15905069451612157329,
+               1355498131832429384, 15975585519420207244, 15757549940022310945, 11357394570768845273, 8197697208897202922, 1901621009956576265, 4290101364365692172, 11947148614241269523,
+               5840762872471677309, 7514977007446174348, 1527060545570586419, 16609099121469101859, 9320342325870097548, 13965331598495025936, 9683433385601741715, 8845290689278472178,
+               14119395813630029665, 8634138112335652518, 4658233985292819043, 9622846971166516113, 996353694479629398, 7404001202059682426, 18145845493517798921, 6449664057746980028,
+               16521775738375440178, 14142357232938693849, 10990147202113110230, 9959066954415780230, 13034621383041722634, 5025797339352139456, 10322111864643366459, 2614961497496501105,
+               12557910439954509999, 12230084394391362713, 8427020226737465235, 12518021396913122088, 7134271418642259845, 3905501389650646356, 15707807001177039585, 2909191175572717037,
+               769225015796913609, 8753059944613840368, 1611869096690868003, 11449828005116201197, 11517191665323762104, 2697717476879599241, 11188965056705006770, 6249359019890699508,
+               15594613737645580981, 3037156291483237329, 5604071908229825169, 1604475019228431078, 7766918222574600204, 9339455406279970318, 16266564745812517195, 4799424886612563329,
+               11601570184515356415, 11247678357869162156, 8415095559389686315, 9625816053586466047, 11807876143163335372, 15690209134241397733, 8684637224468015605, 15974968144193406020,
+       },
+       {
+               11275984449259340674, 14922638629881602958, 17186426309348732477, 2094500549052461127, 1245672419927595636, 7529921141299797945, 3181089597449057707, 7749529014968942143,
+               12842581296013847382, 7845624487558348664, 8747439372999364825, 849305823897878133, 2217292264321907974, 8173534404179332054, 3588643190593022889, 12047811416592660080,
+               6959527445237219799, 17170778245769606301, 807762173031474321, 9151445233487017286, 15103411489939446333, 7976669669591851659, 14824323986579638641, 1535817133122800221,
+               2365455792963674834, 2249234228455309648, 5237136544555745182, 8814246419234451463, 13017813702607013347, 2241193992640629733, 17982226236989862510, 9800528153239873634,
+               14106286229675768856, 13210380707737857536, 8049798856134302097, 9734560649539497957, 1623205786926824588, 14287958304696241706, 1800854015662052826, 1212925137572581937,
+               3026947385483276729, 13169758424754896088, 6834174387382969128, 7206544572805916922, 6934064062491731757, 10620406409375153308, 5194048681860016706, 1469688754160716493,
+               12993558037376222988, 4669474265806332952, 4832324179281001408, 4413085485243863075, 5405837906169635761, 10091776239975644239, 5290719555562061144, 4213669820858776415,
+               17271890190678399664, 284117971978206043, 14999643475704678808, 6264699496666119083, 8859934981351804429, 8300880062060532031, 3667839168820458685, 17133003164910522197,
+               2997449698566957466, 7884833253198684528, 12498695470674374226, 3115564300965505022, 13376506794876055601, 17895331353362057251, 16990581103090492269, 4674862843410794096,
+               5006430925084708381, 16053115139414023422, 7049813739763202517, 6676629839394309180, 2410666182773729148, 8945309185393628712, 17674821778351929167, 2683163960153153804,
+               14505459891908974624, 1849503921080779239, 13990490450160111440, 5181610498614712941, 8653117877167770474, 8814499350344722617, 5343755460620184433, 243401361005198353,
+               17791633957402883820, 5938849497629314459, 8356801465373786047, 3163889445599730677, 9723709910898285412, 2841967670768995554, 10896757438566636700, 7434996874241771203,
+               7372440365321345784, 2862880403174214663, 8420116322934238724, 2818552325655576635, 111342786192022359, 74705672003306783, 6591511741514218962, 13124391319573921957,
+               9931074113040228488, 15362193958291437280, 6613002366394890474, 5258448208225327677, 5126245224005997831, 8755434042915330962, 4405830479557957055, 13343591337768921462,
+               9242810916685205316, 2838356272544913798, 10099476622515682546, 15551100165305852662, 737838832976059770, 11188026425234857295, 10166119013055947704, 8628233674684143419,
+               14086272070125896854, 12009239107306499026, 6592816798466831203, 11371087141421707743, 16277593907837607793, 16449564916599232060, 17471042072158213549, 11953382410698485455,
+               823047236880870350, 7830286704456953572, 6464058012664717582, 15521380082330968365, 10182202815901986450, 18143527955004661429, 3207725716803325445, 3193887560605396493,
+               15569872930692175382, 5346306686087630019, 6632365629111827330, 15865883909120927399, 7200040798106687333, 5723169387900917854, 15027071603483375844, 11018037359110138454,
+               741009114382240162, 13879961246490269823, 4790141947869766711, 4479737908710468090, 4979904969974036721, 634413885118778288, 101727670723732801, 3160663692354720401,
+               14613304240735929191, 7658770973133328064, 3028731168325633068, 1486737152001467114, 16715835021406106944, 15214200823642287507, 18441898204110447697, 5669963154424393607,
+               4313074171267006471, 16217697149498819074, 2027993870023154350, 18018610229517524263, 117205923522590215, 1784380715025232199, 307956084870608716, 4140912860495129528,
+               3938313265660748839, 13018885466029447230, 12461354215832959401, 14495299413345669177, 16234805331742830462, 1578184208291171741, 17168468892394781152, 12575003872292801090,
+               10424668870965277693, 8952352824982702795, 18017430252932614600, 14101949308713937413, 16342352613992153502, 6862842966642668923, 7238655696295295374, 11216037980129705353,
+               8381651800836461905, 275661552864412688, 5548629401959193001, 7174991431295718071, 7441251258233899268, 14052832476485122412, 301250917807487282, 17797202428295526090,
+               5173263645506172639, 7621852612520351243, 4670271322283433581, 8663786927624336026, 14433502423455668413, 6926265712671351075, 9776903322968672826, 542207238644018218,
+               9588056942118198784, 14024040464098859998, 17712446698584877455, 17945455593410056285, 18104078100936060946, 9565731894604896153, 13213845893767817606, 16043575675737450101,
+               3436179376183792489, 8124476612946977721, 2169106928994773725, 8589833084708985039, 15137137534993478994, 12789920909097626916, 6767184505234754407, 8369097443031908183,
+               16448089571044203401, 1396460397790470601, 9796571033221459545, 8162511506983092708, 13893406727199803081, 16188892369453405032, 16023105002157964343, 7061289566170423383,
+               10448117565485426152, 8145533940921335838, 1579413779055052019, 14761309857236492983, 9815666466018583851, 15131106965446764630, 16986514923298225288, 3751380281663155649,
+               2224143503200162255, 9410177163066991107, 7157489123570995878, 13420515130397093319, 2675717750075873421, 6702938999067232257, 394050047437199204, 11922372120263518221,
+               9930837889018815244, 11397955329795684905, 6931891256005909739, 516538601500853702, 923444815286512108, 16665363217941733257, 1377231042965759902, 8439923996651310778,
+               8743817608749172620, 7804846024944300667, 507107926259802795, 5258061329638283805, 15071070675288472598, 1848743106176521296, 16295570828486620412, 7409462376590083349,
+       },
+       {
+               10223936123327786454, 2321887803300626936, 13607747528117965743, 10456421630388400123, 3266519591187534953, 1053691207967834494, 7151443045753788549, 18124688636664828399,
+               6946488664257064464, 9775328903143754150, 58700362449753229, 7901817271072273406, 5074738678159003249, 18397239731906005785, 15911102965988125888, 9277654580204145348,
+               1874700306906525099, 7337351570334852732, 7954195906114335343, 17230226427261850070, 5181329498860909261, 107167242193237170, 4364856176182710332, 14611171841443342914,
+               10990327814895720476, 16588412771027628390, 2850177278998422188, 11569813740328484871, 3922148781422941186, 3581659216490446242, 3646872304052351376, 10887870617200051198,
+               8175121141368087217, 15079393830876652065, 16766987879267543828, 10582796406546815217, 16832256009371376870, 10042650470778064892, 17867163453935683780, 7123418345572641116,
+               1782651072016504775, 11033882508408412333, 11105300284232190625, 3276372405089292929, 6399472468041061588, 15319690780388315076, 4928530863063375966, 11596222198340277418,
+               5452424185619067445, 12050433097586021281, 15018766900844679217, 273234254926088220, 15426383635547379531, 5213762666043737626, 2829185842069118470, 3230799283770935127,
+               280030342772428106, 17354882606189694746, 17455445295460080284, 18076709382926018941, 9895982528034548913, 13681172423928175330, 1656433131309057012, 11935757350437721114,
+               14437472586336929440, 17387041914242263390, 14861577074379746687, 5146556788377906297, 13036814755814090195, 15108836859245573802, 1667563994642521213, 14722845469958372258,
+               7781061995240980266, 2066078418484154391, 4089376589847114892, 2434843609506038666, 18376509832460312721, 7187709121160627756, 2455436656049651823, 14419116837518875372,
+               1270185079976403265, 9214436628411717184, 15450450827683432913, 2880014804806096082, 15448799931519826757, 10080240282127928735, 10673974088219619287, 12998944469117087518,
+               18028691745165748687, 8931519595829275195, 18379893031942930865, 12120980098075498008, 9596371470855895261, 4133427878071274570, 13159312399982591699, 1639865074052258019,
+               1661696187746428348, 2656198437014978712, 13769477291975851694, 12512848714492869444, 5980926616932344693, 15821983893144953005, 5816015630031200526, 15887565799959254415,
+               16463929919291729278, 14920112063826664828, 10056471508435050704, 10696267144984026763, 12049530292963090991, 11926086636123189182, 9464890378472966538, 9719194510330239601,
+               18110249193861022779, 5612784685592189906, 11360454032996393150, 6795401682138043705, 1961398978248902107, 8999847457729547905, 8941741619641401180, 6086938661427918241,
+               10153847769616409178, 16591913677701651064, 11369151065084080884, 9493662847124813178, 14299126668179023903, 2451525064998641745, 16055696673728703463, 7600736037142850105,
+               3331094657189179723, 8579232659787725167, 11007434086335446933, 7488529659250917009, 17217317841029490639, 7202184784979805220, 10955913831459448069, 9000508720500651545,
+               12966352809478736412, 9643078159289928329, 1577471789984999485, 3065864601417367655, 13683627106599504109, 12782093364215596525, 12883456287502344466, 384144415368165580,
+               2010495664660209855, 15520744321638216967, 5385447087428594566, 12897496516555487055, 7343279016502952747, 11323820480524965410, 3414484402519450292, 2497721392671865580,
+               16065061175628739123, 13981641072236579791, 6942197664821630380, 1667302033233547783, 11254994815452647404, 5265777633437443003, 1242523090981771320, 11333562630675377559,
+               13967113064180443992, 10679621597408504672, 16223869620849920309, 8813286726524283182, 2000697484240530777, 5417120625530117302, 12109041278382745291, 13257693171778388584,
+               11737174095432286870, 13459661128718998448, 4655386724404378836, 3119616752887818891, 13324285182058113375, 1078137740985006431, 1610820303976884986, 10433300853468291587,
+               13552049979590080822, 4379357932546858489, 7594644709024650108, 7268811721525297059, 6728671136192921869, 8183021491392757516, 6569378188404015319, 6481294988812800823,
+               6071501855022377789, 3805172128285889052, 6802689634429908933, 11713310861536728752, 18291420299754708339, 7582277238191809023, 6183429490206797252, 10452668103640934631,
+               16083971675285095468, 2965035896159234764, 9379493912871845724, 13109394112987303523, 231416620515766991, 630445729708227114, 10015412267172773636, 18104521419340860951,
+               13169770634232644390, 12462964563528956096, 2689434882719314440, 5936289129999384022, 17773436345927091892, 2631892834965929605, 8167719122803587721, 2458223071457452931,
+               10744932251818515465, 13367480890778627284, 15909410072235544918, 9252559547875570290, 16355895225285344183, 5115003811789024567, 7369371640924666845, 4586532908333332092,
+               15999516281080615520, 10972478396135936147, 9002100275598932738, 9043399249857967875, 4975188939801806064, 14240375126510021504, 4497218436093285729, 899858725260616391,
+               4788026362409273347, 8940774760122210910, 66616358927988247, 13054723206705508289, 6256911511259454580, 589353691478007084, 17831732841616807303, 10847300659030294141,
+               3016120727980669767, 340560476433708073, 10516500208515875331, 14933811541787518485, 9941997565508314935, 9752941942651093949, 1928238223054143159, 16147782066840428568,
+               8953947187833770878, 6627103431982157573, 1279114735725952920, 5378128106441279737, 15447712974588571571, 10552843735673449739, 14956126644414569830, 1994513099978508850,
+               3339871688614476269, 2937156932445032796, 2071344655111136329, 509603454456841298, 10929109734329673813, 4531629375826317764, 1802431569220697099, 7971315018970882891,
+       },
+       {
+               4307546666223047416, 13914498777427309061, 6812156124789414732, 1680174913762530491, 6756325174405757110, 2535144759174364990, 11263393915003278429, 14767595249676286403,
+               6981289090623415465, 8930069945493884157, 8223216504978132408, 796477795300774057, 3120155459209743472, 14825603392456550470, 3711879425019804830, 11041054473536223927,
+               14135544350792474553, 6171419888118563156, 12495035851387242130, 2843310747449412555, 5668766087526340552, 10117858698838396246, 5181027414039980750, 13247490124270426,
+               10847249691051757241, 13332329214721571156, 12457628412284474075, 17044657510482764070, 5218221397478351943, 6922630493693541156, 6207927102810766143, 5644846665334649748,
+               3169200533952511826, 13123046990387029463, 10303462306703730135, 3315008874027436174, 12427067008037332041, 13190195608614554888, 11930408619792340463, 12881268563913740396,
+               6700154625941523096, 796110091507466427, 5388163944686450548, 3113104467109529928, 12930558649635882086, 7536049463980825715, 11851825635055645132, 2654888532632283214,
+               17530163750522835336, 9722612350417778827, 13244522480616169491, 13740964907388846002, 793235549667461791, 1998252773625399730, 9697911491069876538, 3365596945186794622,
+               6506371904134856034, 9541373683805144018, 3149037850125132851, 7111810601994573897, 16732445693192247884, 4994069681898274622, 7223719243730104348, 5649174084086150712,
+               4640203560336739679, 9900565149463137003, 1093715346388527458, 17169722430093991108, 14911871124664548213, 8091096017016862097, 2911569128494944136, 10192934055727569503,
+               13251895658744991883, 18083873142202267221, 8241707078409323349, 5240943892375002838, 7329419846032881810, 17784005510850539551, 14034072243705748841, 10459194866755836024,
+               16396304393792022741, 510358226971662693, 2002127643935690257, 14681425695950046262, 481902649451190280, 1717807040845239061, 3358903321435525144, 12361252150277163759,
+               16562962997045986629, 1977585352264948582, 15588655103333244279, 253344970359156714, 12939363813291366775, 12548224526376199974, 14450582788883748364, 5869541533939881460,
+               15346378007864735078, 9904337403373774864, 17933855382993937953, 9391248304932723816, 2250334275383247202, 5978804056136420670, 1528238852592364099, 6491566547950141733,
+               8439860020828526478, 8674532462170555517, 13889716766953024111, 1166696901054897271, 3599113965286446905, 3276801695553601157, 6631284861504552600, 757022358659145685,
+               1117291222568805017, 7148845117809308441, 4044258438241699262, 16593433123496068718, 13992202310165134218, 2998204381658279116, 11137382784909083266, 11972581616612094469,
+               13970586842647892965, 3680317572634289692, 3416494470839852757, 8341497967750607131, 5522860734580749818, 6847292760525096386, 9317394708872196559, 8522252330730808934,
+               7951036477225560362, 3718789111033607646, 11667291286820266731, 6927579620295878614, 6796746225018555970, 2070061401518338268, 2452626412419851405, 6130352643925327785,
+               128317967134069640, 18241952544586374251, 10689311587315723515, 16537482248073764435, 15914436258832414511, 15518344078557945167, 15883120902045970449, 16251109112716994957,
+               11957637677355945602, 8965882791601648704, 9390723380463051523, 15025038333096274711, 14983844148312808973, 14488574793452236487, 15795526425513195718, 11651978879566144360,
+               6838341670149165895, 12326189699069923388, 9258908232339348843, 17297038041466207989, 5242182985453021593, 9648294165629935142, 9715128265517308395, 2662662536493743894,
+               11289660454922592938, 470300170724369955, 4571871646010841181, 8724229358245178735, 10173959190953118810, 3611286966550223594, 10810806064515103403, 13571898391208639897,
+               6782514579206442308, 893150666351200058, 2099535232722538223, 300696716419619813, 4778737709473194628, 16786610674618434170, 1751624209281870237, 1677055321500839173,
+               8950755642341912951, 1974922263791844623, 5333377426024439800, 13909803085973342843, 7639604505882407937, 16195074617613125552, 8954461446680048430, 6823359994465290754,
+               6790869670806738567, 4499989093713728199, 17496748050437205626, 7194829324969293638, 18432532588985091708, 12041300075343806904, 7788543067151959941, 13703334460383638224,
+               15088053026772564466, 18172984562199594382, 3119317310593433742, 13835498717175822656, 10015747176747842576, 11008571041665092033, 9377877781626879674, 10465443099481589185,
+               8933481722931715231, 10811948483433850165, 16314247813274714890, 503147444786527544, 2533443680646505069, 7617720894972668760, 12477410920355308950, 422423516920457876,
+               1501843276089632258, 18180777013307233967, 2535426997299341256, 5318958493284100856, 16758265544916918856, 8118598628492446123, 2511013049335776232, 11181447982017705826,
+               5996381448168274884, 8108757135223610234, 8067369725584584297, 7184925262427750366, 8199341143188441284, 13031376443169557016, 16036606349050125404, 11958720833222295864,
+               15336831835795822898, 6806921200736832713, 5959923980569572002, 16835674225684329982, 9985579070716031367, 6517360043741716503, 16609518082836868591, 15878184747124924573,
+               4786224758360153905, 10283234398763800487, 13695837902615591472, 7260571034197533442, 9225062953237806971, 5969706575516748564, 6537573986766117532, 15754484267739133126,
+               5004791824134844360, 4971286291135250424, 1811371968353107289, 15772458387007519716, 17381493577383518445, 14326903440006940586, 14237922492359728234, 6234116464684325431,
+               9293668142017263584, 17134656749295164870, 5879480323258506465, 4788695233340705697, 17809277710857366810, 15157733645094688870, 14143869691462709080, 3162286338158090229,
+       },
+       {
+               4471613312912718060, 13601785177495103328, 8083849806888905297, 9053545412554844461, 1876605639999952155, 6124537911475118673, 16877891074567085688, 16541720065079132344,
+               18138305348849897995, 11498878557125400853, 14125346336359365201, 11991638807788804369, 13935355764550912568, 16209147067155729660, 11086190285777019292, 16727288863943596410,
+               8873152377611229668, 6260821826956744083, 11489383533808918262, 6585112195310961861, 7365821041919648819, 1936165695028211587, 16164747634991415711, 17957320776652490392,
+               13065030057172289846, 7278765836407486850, 383827150208081081, 7832055893191054601, 5249323286889945617, 1631661912887095912, 4431088469837785451, 2866263172993336891,
+               6140213328062333551, 16704025329777067037, 5839832043209342792, 9196354634862869885, 2735762290983671190, 5323501742548818139, 3199127466610501482, 6719610946615763192,
+               4032564124345275293, 240208626666701335, 10264845378648897042, 15608289126091352415, 17866864241918154829, 6207477318890336372, 491708931325462670, 7002400618323099260,
+               11507747783030541234, 13683043390668171754, 9924966309328785763, 5549516466627385909, 3724001483041449858, 2408778220985427590, 10510707601023430105, 12862520912519186496,
+               5012372868660694231, 12033652755433827667, 5960732801180177919, 6089487525155575261, 18400192045204062277, 12754175136438960528, 6170965736016609163, 10141374482047067946,
+               11781193922347227447, 16937876011211881637, 2982972111293427964, 1728244726890919596, 3327997232304084768, 4754833121145407334, 5871027825507908591, 15772493911709624273,
+               5862944033912881884, 11132730978666088350, 12167180155548291888, 16449838286695349787, 14399676610730016345, 17071083123672650337, 13727728787831175379, 7507765123422748291,
+               4883057314704644529, 6606742732149784343, 16070555141087563722, 8408294891669305261, 4298316003054547788, 1573237855902568238, 5357176885445018289, 5855732582172939202,
+               11721126538980357625, 7216004194033429913, 12765889884935948315, 6003399149613653734, 4571046290325663920, 15023470461830485075, 11463513436288928362, 16135217522406374542,
+               14300855104129153291, 11491527690078786162, 5674183453812271017, 5044682546652747711, 9153978680942338831, 400454762074409409, 12351470849648616331, 10559229320903248832,
+               11839166519633311143, 16489041153719856002, 4820713204385149226, 13768001962143023630, 13107713406478328396, 15471245828032402460, 6733652296473831544, 7665657127090105428,
+               6114372925011600760, 13061069979571997963, 12156991017966837826, 12403009591138383583, 5761958709898299258, 1907771304051897263, 3007439379929412593, 18410854883912163962,
+               14408045416865494124, 2442199381796557002, 10475326303775862953, 13637445125954159957, 3778313603630758744, 9247460369874272772, 17572237597883145087, 11338350096360776602,
+               16486104352829691584, 11856560607954368882, 7574789609701925021, 12240083183242127118, 9872957337376856275, 11508929285199799229, 12084460294902152451, 5537978390111837838,
+               17987471707896681874, 13038244305326284081, 6130570860032709721, 13697749322780057427, 15250226813583295859, 11214437899623632196, 11227424166765094355, 16073863048822462466,
+               12399110995748365941, 8259021120978314016, 13249466772279340115, 11201772702582865107, 6680428295197296613, 14825065014187212998, 11638499193934854444, 13944483483619391536,
+               12792956896156056673, 17521293339475028823, 5738513258925006248, 7070317930523546296, 11175557000762820214, 15356683721815441509, 3038847573301969409, 3712495274059632476,
+               9703339902904468931, 6903532388259237787, 6598718994389707957, 3524767540333384210, 17230409287786477986, 398508689507908728, 12956323124513250470, 3050411724956364887,
+               9936181795041159997, 16502578966693139346, 12331385558134766329, 16368402633574222539, 17549179704234998175, 16732353056786161257, 7018642409136068141, 13907639522324102590,
+               3202436334590923936, 10521323531132496064, 17087322194145514933, 2557934785422493682, 1054672647095378624, 13197226692868722325, 1089249862965154915, 6479925079582112772,
+               3880905381896902231, 16702686708922296685, 9815623322445801304, 3275100382267252573, 6882533095211022198, 11000715667767797665, 17615808190378608947, 7418883369171949489,
+               15109802007060416273, 6172716471862133951, 10675428021956965140, 5719399515177959211, 13414568332401128475, 15437234656470291881, 15174397947571718085, 15093134682110367825,
+               12767354263003560893, 9423701226679222965, 15980976879563466685, 16370172902785037004, 8843543841582241065, 16817827501960591898, 1524531339915785994, 11624580276885598157,
+               17147068462804570503, 413038056092618151, 5178874804057490245, 6267545065511948977, 17573054445714024932, 7120476833739422223, 5707115123830922617, 10971108972695387841,
+               12546478152711337402, 3213958910433616233, 1066524299473173792, 6276669942370566610, 14816818963020520773, 7372806616674468946, 12220278123497641030, 4953625488417522128,
+               9443607421568920607, 2583030461169574647, 9900905053299561307, 15892418329702922907, 1184158607153919924, 17842123060489837980, 2681791639846598155, 14394984710894548047,
+               17363678829105605076, 3907856148144141388, 7535915338133892356, 4354053943074081189, 9644954727645503986, 6816908226661921388, 15867806610099035654, 13874346146744695721,
+               2654416582410062512, 9232324386948815478, 13864516581612906345, 17132638924861000235, 16875312639179645137, 11536057026563830119, 1090137303802556590, 15667188983774010898,
+               4336697789732072031, 16054848662858822197, 17934449813415035557, 14518380622432694666, 14100582434152190048, 6262866632984449325, 18069160441815400774, 9798342103009260692,
+       },
+       {
+               687104890149081183, 1938816743979859301, 11342071981175913904, 4270322127259097184, 4964776270155503160, 17849333582861534767, 15814479527332819692, 8083943565773123408,
+               3986890035154628803, 15316660330065019741, 11560940574529263780, 12576851520091035878, 10883944418224886092, 9908329441525486205, 11238684990962507809, 12900626758810151662,
+               4077800412543228484, 7173833470188867493, 4604439809988262876, 8090706047559948234, 6117166546062912279, 15748537214854486946, 16719594636199001564, 563850925691991999,
+               7109145612337154341, 10502845970727626855, 6527587047878193251, 7049690136888681718, 16750703006415156202, 2559311261501721445, 1222802194566919230, 18019462938525560766,
+               322982839910423931, 2590270731903609206, 14012397059804449007, 4254569016772908483, 8508420263334539908, 9175848619353159735, 9777676085150569067, 51565612432741329,
+               10233009747926770582, 4858065366607044068, 17837971428933010861, 10016544790726166742, 15260359301638740999, 5101999662344938158, 8809855615759524306, 15369468763003019252,
+               4549989329927399868, 4866130696079291940, 2784467031729859937, 12617898982021887868, 2721301974598150044, 1014232218549205942, 5446756626431953863, 7315134179045561903,
+               2592184418896595488, 1723751460114310463, 11198512454461769811, 6203707848404803677, 2601731234271436477, 18186700975610533226, 4757569424831899615, 13359873383138312209,
+               7339520839328992093, 3349084091338116256, 16532710170417471614, 4425958052714174548, 16833748535746803845, 12665172019028452441, 11274971974705134171, 6504206221872290467,
+               17921256304121537300, 16573867650874642543, 18439217559900658467, 2917797231317530012, 2415475159165597656, 2027542924210178369, 13542535558170959524, 9428931592662127870,
+               17821420552135083528, 332847653840014838, 11832506312426064436, 8314663852639826188, 5744960486691350299, 8069724388577179929, 7949740770152910898, 7431049632429535950,
+               13904640252203718708, 10747313134117021792, 14667070697514384141, 2600977347774743546, 15498986940124021079, 14740645313274577011, 17403811028932224808, 8060102076475954685,
+               3517334016249952489, 10826317205305313746, 9664766330892822745, 4145357045596983962, 123566849370572650, 6452080295201963409, 15558941970553263818, 1191650177320171029,
+               13303794914626036653, 12135860919529132656, 3620217653879289461, 5443663950311568399, 9020744500355505374, 11953955628401776228, 2101814526784564259, 18218598416910848525,
+               306945432061418036, 3150552227215797902, 12928374347433953916, 13299101042862573370, 13702883318367407795, 4879985767563062391, 17591048490944890593, 5088664549487213106,
+               12990649636107730851, 13002224935892458030, 4380799638612122791, 7935443787987894924, 10438069978940053126, 302419699431148366, 551508078777729872, 366155636877501719,
+               1657628676376133571, 11398060401420699070, 15376723048512638551, 9875623386041366116, 9978954704196888739, 13768323245406799962, 3568095027938899541, 11120740210192996096,
+               15561317952331530901, 10479759083279078649, 16536004935523752634, 2928518661531554130, 736056663469575928, 6131440330717529370, 11275149343392851570, 9601030074480228347,
+               2397968519718544666, 7793046606567840651, 8971792946996316712, 16581860514259510747, 9067804351225143661, 12322425857061932421, 10680196669251962457, 7226521395530060461,
+               14734735764746786753, 1378251478826083755, 13509550209468602124, 14458158239096821346, 5681313138148713219, 9054039627425609375, 4235536482830620712, 1502753755874778370,
+               10053374816829223121, 5956370573575798562, 6842782625116195714, 6646143553705917790, 10487617951080656190, 3930886288654953669, 13141858447548326172, 6966039733711006320,
+               3565931266726110263, 10142260659118036168, 18315406451571961983, 16857333990691080595, 6889519058362658033, 11812045051361479600, 12503117299646153207, 7223531498406875484,
+               15243128568488310595, 13798032762330794140, 4456440673105474920, 17896260893739107970, 5519537045179649847, 11908888770632658821, 5444504459295913107, 5588728973482930155,
+               8914021876030553161, 9071747156187788379, 14974736924255494885, 17070198435868341999, 3643991391224035758, 260637732328275649, 17609644917816078225, 2302996326941944665,
+               1293835161492069734, 5795029109259991590, 6978986253519330084, 10360755458408067486, 9467742127861782141, 9197981630801498774, 6297600026339958279, 1375635441408481019,
+               16875086338187280639, 18188722331528885957, 2047282716697647836, 17808297209051779725, 4756860180475663362, 16103863616340614471, 4416311024167936572, 6340715229216403079,
+               14261984008515151673, 8778722476581699445, 1624620854396291363, 8490568310899028272, 6147263592092458803, 3717414274397202281, 3449154725620836174, 13526832985450537957,
+               5888744936142942064, 17277140802638358763, 10290028650289820825, 1940657436863195045, 10796401239257150661, 7788083050548605852, 13474393003015663489, 8961936186303685357,
+               81364364291228199, 11636155122637141142, 927710893705810893, 1403208391464987879, 4332234662194589819, 7913319387647351094, 2589089673930123808, 5387282875974124558,
+               10611669207938469024, 4491327257859270050, 14129391883837344111, 13924810848449766461, 8792187899775727862, 15048142623570073200, 3933861866144269656, 1162055633060412126,
+               6883724061714130987, 10416279294253729103, 12247033224345499651, 10291073256885105234, 4480789666471481188, 6022169887991948086, 3778647272347441051, 9527380466585130391,
+               16407225233842256953, 13423683834633513951, 17454464203550700633, 6033758555290610449, 5063673994339442907, 12250392784929419939, 5954485814444410119, 10099095370725442279,
+       },
+       {
+               7669790431656261769, 2776517632462593286, 11694025667665633506, 9533794089008895277, 2895611631120558023, 11551410655448788956, 10026541900772270925, 6243136875017000843,
+               9434484992529186384, 16435748047660609525, 16190660694150989986, 7083965852434071085, 4216306437741910756, 2698742177539497614, 5199793642504009017, 17298424769819019160,
+               4041169394784902550, 5699517344009382913, 5306272267462320559, 15846674482556330025, 2606351264228884283, 4162585980422107281, 3715151019132039005, 6607223447043258693,
+               8168579295855409503, 16727569921530031841, 6182114460261837773, 8940603165471931374, 6081572078077526926, 5890840443923124563, 11215305828294759727, 2875117534361804712,
+               9045974983664041829, 905036705033699463, 6962033946652121779, 3027264198782618401, 13786415307358010100, 3643342525745067473, 13641958783381681886, 15675065537779359584,
+               7507377696839752642, 1061259379811757443, 10276590160392917813, 6889137095037822679, 16373913505782725550, 12287733095803524526, 5695917172259210496, 6360958736925918808,
+               7459854586357006968, 702429387211615855, 8231296036461604410, 628323703857882004, 1059802628602873385, 12517208225099517507, 2368172548334856593, 4792344750094708709,
+               18352334786472886037, 7096021570596476676, 17045407505128867173, 2467670847537319400, 2225663888244226889, 1876713214939672742, 5329943993157142620, 12168650975912182188,
+               6639850268372381409, 2284514769224558945, 15390110317831975716, 13933785559694229008, 12787641603764341997, 793886210532292741, 3222136169196008839, 11104892506868626444,
+               12660547967989039787, 2109392063597767300, 9889743271997754037, 11803327596624324036, 6940409327849314286, 1466399127363116843, 2572333022681966275, 4216097356402537802,
+               16858757460581672909, 5838407119753001493, 4453405435911954669, 2828665451507432751, 13657966632733241760, 6875986784381874300, 2390233934255482553, 17386653779125555159,
+               2976756344404126744, 17032556609402836559, 16348907464011574182, 2196781021202618892, 8270822867494340805, 4738372358350764889, 6088256422707334932, 17121369334507507505,
+               2081729301541563384, 5577186154173396778, 1865152567701500436, 1422284589642218069, 2489023909725140903, 276494395149046869, 17420927169263487236, 8292343688801608074,
+               7819174654675104600, 12778055482430336726, 14615848543490171611, 17498415175263742825, 4785899184222234034, 5227136636239697699, 1570704808469050246, 2858953380860123257,
+               4323577007857413306, 10524228743339400397, 5418808897687027557, 5939367271366264075, 3569359126353670574, 12961495213964770607, 8906990808988099905, 261084295374207271,
+               13937553904380032591, 9165760362893872288, 14159606902675650669, 7794101517494576908, 11994596892880464164, 16211278212275417034, 1568324133241165712, 6579463633356173526,
+               3784436423124943604, 14504130598322564217, 13343318845201913758, 2617267381187565844, 10063945174501910869, 8584806992850354016, 17494557973113338328, 16987450461117846543,
+               3191556545349441897, 4780077336463115599, 102121356289129288, 18353108394754479957, 10099934050411322327, 10323433488737585897, 1480832277301232858, 8304664509429164326,
+               16494820005379860880, 1719281141269927630, 2983529566257876158, 15928721259545722550, 3714203000118655889, 15922105900709017310, 17662263539397115758, 1577461381995722723,
+               3426958921435818822, 395886748655323570, 280632942609884625, 4361473570148050146, 6600885194277340683, 16668323952296831943, 10057749804882861513, 5701592287343868424,
+               6951585494335471689, 15680855848517030170, 9776921814538436791, 17640230976984644473, 5777838393869379647, 2176689364164694052, 10884627395386092313, 17656310368333301757,
+               215205608065278414, 15361057989137229644, 6756215047166430628, 12215084297877052825, 7185815532109454500, 3394755837885079236, 1778980761557523977, 1861969072415300655,
+               1535235777601157298, 8875662482214652105, 15404846185148709157, 6538418983879634448, 8341745508628160868, 7582603669233291629, 13003716464169800826, 13309194956036155778,
+               4791947847339351337, 15204996809755844932, 11672964318683763318, 13067259871945801803, 2139419248113049376, 18195694858089271989, 7208559250123396675, 4671149208567820584,
+               7276586425415793787, 14549539461274532692, 7381249250982432115, 3215735370879771405, 9197833835152018601, 17236122023193655371, 5029275100388702506, 10829687080866991082,
+               15533362570521057331, 6942829144635570952, 9572990445468151820, 6294042535380467396, 9052929167426522790, 18293430694900525497, 9076155092724374912, 6410242671697688127,
+               16930844972313552415, 9009509357611549679, 10722442939705348974, 4686888495512108749, 6326319203058274828, 2590592779822711917, 12876493112068819735, 12372064322375408146,
+               11938822647496400962, 15333527667419199710, 2385985954862343680, 14776415112244140169, 12817753724474105460, 5129368568396757194, 607898027127847045, 3917240453172744497,
+               47211231428738650, 9333275559955619158, 7534434473427098199, 8557232404317963052, 11597011861056629671, 15926835677212702441, 17943276685960195536, 2513989430679125485,
+               2903417389682946131, 15905578940823611094, 4910425097773753648, 10817415382143821768, 16356392378927186116, 1174713154793914656, 9176413825070952738, 17779105524945038711,
+               18302140065591767046, 6334261306636966429, 4203057092695998640, 2740754645452686340, 10020911575632378009, 5906713384548665207, 13902791548718280892, 2505591245136304093,
+               369660229032730089, 11851915833529805698, 13485269529443969890, 1270120511649175022, 9128783725626301238, 6173048611666804214, 14151404531169195672, 18241008099921643437,
+       },
+       {
+               16226789363155700046, 13734705589524056856, 9629995513492843231, 2636144377026081617, 1233405076007260313, 2119672919365858964, 4932766292290315579, 4185117177904214366,
+               16996170392430604056, 2476294162951949891, 6677439492116109133, 1649550562276235959, 7307278264575968221, 17128676264244010843, 9768062299436691373, 3825325732056225433,
+               5861627228365499618, 5011684805137210454, 1579621475012951778, 11535371650014354624, 12847902922833318241, 4997014846790385136, 9875988184618650628, 13094082946822736823,
+               17224650011872599657, 11430188086182976152, 12892063618843720029, 5912993124689510433, 7069617917494051681, 1298012103142698333, 7943359430865057535, 9329776843721719539,
+               9091412025380293893, 8622355764644651307, 8718353412518918238, 12338548766610785709, 5241721208413391572, 6315749100915178625, 17919741546105181107, 13677847475856526539,
+               17388254638056933809, 5422523708003180288, 16851423629233109043, 5504298365310420423, 15145549220326540137, 5184279399795985462, 2201159255780420815, 12506121988996036804,
+               4460258780042860751, 1816027820333214126, 7778555198679811350, 8155451943744426012, 18392325810806023014, 3955295139981696248, 17141295608995204052, 14206938573418983337,
+               9464085603669036454, 7848014338005901108, 2368914226155404065, 11578416111848517850, 6323647866244499941, 14399589996703947996, 2824522520842155768, 391310842153371124,
+               17489550078249576530, 13418700716683405568, 8265132837103985034, 8386855948619700037, 4642739669076635265, 1941217860224507563, 7402267177254210690, 9863923110146355168,
+               6176679707488254741, 4307819088229734202, 7082712522654871200, 14603822721598353371, 4115674343542702663, 4132348830250348245, 5992042367418590636, 15937819366199058986,
+               11008669567537833607, 14841150752801539889, 5253470025479549456, 5665837575328478629, 4601810548582757669, 6173003636576141170, 6899193615399367692, 968231402917393055,
+               9948650801233133770, 5836115460383443197, 11404170696974449207, 4791020823967734476, 423024247809958592, 11251668387880260801, 5562546584223492723, 578572156618131794,
+               13456676488167240303, 17121749146829956377, 17370555398500311209, 5041791432274350681, 4009412063225388868, 2407629981571159579, 13052555280728877038, 11483117063845312302,
+               13421089948800544371, 5001604265596626568, 15312985179876036482, 16032805766802337150, 12508684642650694186, 10422897636519090240, 3970071218688010847, 17419166239676042564,
+               400453640980208069, 15220637399286523210, 17321057148174216619, 14860227640908306879, 8047994708253288483, 10174040071518845057, 3280567772472213687, 5651529697807929627,
+               13988854693674964723, 10817154032069031941, 3171651998645961547, 5518712225783687705, 14706905091132091970, 13960758460934966876, 12141035142079693145, 3149939820435101269,
+               17047631647660916802, 11327141967045825261, 6773994317182166280, 5064726840218426586, 11921340002806613391, 9067034595359929709, 16499225867422892436, 9333282251383805811,
+               16851791401266483516, 3629537449474963381, 9616439067014312078, 17691280261538133313, 13915291913519800282, 4229243823856128517, 5998682815524220834, 18293451622818510596,
+               13740317056016164038, 15410121987858832401, 12080671504470100936, 11635316325777860129, 2584464163154495637, 9849046399519426256, 7991103215010751716, 2109987257001640948,
+               2505301881938098126, 9962323478923652140, 9312199523950444342, 12957822502673689705, 8060810607849163143, 737408553843844193, 8143568733429881786, 18003168270780769476,
+               18361695650419575705, 15964191128341330249, 14834821085064012697, 12512940671502931238, 11592194993753547188, 14358438239394059598, 2876909840522954216, 13154864917311376528,
+               1919485747906370662, 5250174270363591951, 6270889482486194520, 726576673961648732, 5067680336545953003, 3152041783219682891, 15674051618916413369, 12438966377512424334,
+               7755405178378312585, 2001220826274540277, 13276328134279740680, 5464764824709243977, 5374818714652367118, 7988129049563289676, 13996688354532099099, 14091540329663446637,
+               4460927228453411137, 16058422703785787527, 8016770980039986075, 11450941100964860520, 2742597710491507274, 16940752978671801273, 5897441526901650840, 5926672707007682446,
+               11513132526446047688, 2371334524276946445, 2461552185903242316, 2195417192784351355, 8821293936856062699, 17392142102281287994, 4066797133115509650, 10704373174879556404,
+               15778536817306082589, 5755579035239870289, 2105368957367433938, 16043807797277162048, 14990960263520315004, 15618512283659189876, 1020703273079622517, 9735594589053383212,
+               11529096471626785524, 13217557548494128192, 6973227637542883184, 17901194406865837244, 2414269359614891938, 9165268075797348071, 1013041849562373861, 17525420894350269712,
+               5772778048593061508, 15424756817708323928, 11842041259277183807, 17669952685051160523, 5405007811515938363, 4415223809135251038, 2223192286456742546, 15742105795795272774,
+               2844957165101842208, 5188198001787563362, 17071130520794983821, 6691797472842348899, 4294126956896299534, 5788827614077663481, 16267876196920424765, 10795461545625002360,
+               4405006158507706423, 8343317561528812223, 7851955346465616798, 14568481075913348758, 4391527082463073614, 13997921112025001396, 15259963045788570485, 6787776208020191083,
+               4002627348223514978, 16231148554725644698, 9578235186329928114, 14741034641204805809, 14651073646349829984, 1797163177099497214, 982043220105120238, 9027434646723092211,
+               11809342655313500273, 16822704101813284237, 13097372075606737923, 5463281428453250615, 11967866991673525562, 6828790575157689223, 12568831962097805646, 8385980093725157349,
+       },
+       {
+               9246769514475702626, 5788284997389507365, 15857897362850327403, 13864676801095094218, 12881526722328523267, 2620841421323221200, 12599981775316397124, 12820989846844560040,
+               13066648645100247757, 16727492115601921665, 15749471761440498106, 937594351871983779, 8381111811209734349, 10884357918725639691, 781591570669492079, 12778743765298428266,
+               1797915488494232282, 17274756142259274463, 14207994319179101777, 9405903752538915237, 9001743317941152797, 15048752608061590843, 4925745663463425863, 17143694017177138485,
+               11613437975225156304, 8619196433402562266, 11907033287998837424, 5056904365610561965, 7637552956459333558, 2827449950719061527, 9998507085256853501, 9238562885525900325,
+               13246436769495027717, 5445015753017977819, 16266739009580878036, 15566606095998238977, 12196078605380432771, 4854324313875295137, 10974170498288217052, 6425550765546527417,
+               14574824159194628650, 16992289415800830701, 3499062703303067574, 11220872042664151226, 18135860701984580530, 13630928571014923388, 2913126838766947469, 15869180955632349704,
+               10621010745328025245, 14637275395423748577, 12928463178963493980, 3270672471462681194, 11765440832075775157, 8138439106739837848, 10004644076263261924, 12582897670868871780,
+               9605391611675301152, 14014632424042523224, 4638465078692570733, 3013469722048440965, 10972600060210514686, 4497572559400894366, 2652629676209366276, 15827846806499715082,
+               216774559418075105, 7056732230404238374, 4342481467357759950, 16143194646968227790, 12304857685680249595, 5021239809847286634, 745754913624924064, 1603290801266214539,
+               2784418922013631805, 3554650219010546629, 8896448905401216908, 13445015286698819482, 6508982623352460996, 3322529327934132311, 18417788670080975365, 17554108945303789353,
+               17620122226715347133, 9738429733440215024, 15577771434516492888, 12422193389576942718, 18383756008252443605, 12736926759685644351, 16981429110294392086, 11999528928951986433,
+               14489177617081844909, 15995916840320959685, 6361381313838994395, 11146176143708648759, 17190512001934479207, 8406914945663974955, 18073221191428103088, 14075266763636071788,
+               11493260321718935244, 7134447477334726345, 10489281872281557152, 6145540581503915475, 4002857892747271740, 5167943945955725680, 2892864850826359384, 16887114279977647596,
+               16493058314197913501, 14642843949567816202, 8421201635021034279, 3645913604138483317, 6127272877310948153, 3660286308390076870, 14343325047340052700, 5355450922054278073,
+               8426383571761073988, 17627146217941553397, 7396223609641674418, 2402241526082789613, 4067059813672963823, 10306840429023537942, 18342506396531908477, 7249869764848707701,
+               17055119974261943875, 6266720893662254540, 13102139953381148874, 5249314164321788611, 7157525732140787612, 15381277459195914226, 17265025258266710353, 17573500432599548120,
+               11703325491493519624, 6756922948215553472, 10849241105791329449, 4442124988071574400, 13193138084274485850, 11408181130174894537, 16602978650637017500, 4282478513876287613,
+               15849352004835856215, 7022332658299393045, 2753527422472509447, 2508636546397160815, 18156018186852519542, 13445036260276495365, 6279372959444826452, 4487789154840943220,
+               6912674041294744283, 18177825269025993506, 2129493844567951509, 6833453501368177831, 1878514166200306112, 12873954541639117785, 7984716702294892278, 1590286870058148425,
+               13310953099825480439, 942949035351116482, 7073926138905956784, 7700580694019269362, 3135382872993338421, 14860196563555722941, 10662854588851556233, 5736680857908686906,
+               3285730769783013255, 5648284582450022694, 16712547815126338303, 16508335566005209527, 12272617736405465053, 6690178916455692547, 3481505327914964440, 9148348679521508925,
+               5445751308732564169, 15671537507319596886, 17721221564106627243, 379590599139121791, 11923849517192812255, 11794879354344258105, 4802202540817083733, 9502952511912834734,
+               10387170863530151921, 5325952605083195756, 9255511257002170523, 413412942592261158, 2693041233704004652, 14135620291598275670, 11595337134421837671, 1965085859594934829,
+               10567751951694288416, 10466024270444644770, 17138727632883910786, 12652567654757797118, 13864111438265559205, 2552332838857882141, 3739570066357761968, 1439381288436968019,
+               14926469836092482784, 1974273958550553776, 10770915481273902280, 4033929759715842024, 15461883773070197251, 5631323369668498153, 13319268013678629907, 16483196656661792008,
+               5825598074470439590, 15514383036808278765, 836600073173284669, 17006029483641514808, 2253041172677940136, 10109282146738215012, 2050330973627959134, 13783991480192211446,
+               7361422649689322835, 16012782899552425604, 10324124765039044621, 12319908523309013390, 17065808121376215422, 14844145564675640794, 2754581529304803758, 1149534055082731343,
+               5371192675994106473, 15892724499541682278, 3862864290653799361, 15759456296270265029, 12018492462347307225, 11503979417352537931, 1894695486127847219, 15184833349947874986,
+               14711143160318482298, 15515618319260581947, 10015362293284733112, 1169298538214120845, 14481541537099551545, 10304547737174682912, 9351439436434829996, 15807708290724844107,
+               16946643895530263911, 6110142153011856496, 6857516759047242219, 2026267735072107620, 10338469980804248611, 8224240981205716101, 12739986350836865860, 6828408496869642385,
+               18199296108774357398, 10154672256889745380, 1190269705881674139, 2317654455984851716, 6948704988682993246, 7864433505284017226, 12371653445644439372, 16432795124971446509,
+               940679263188661008, 14653357165718140350, 15439920797347843673, 9415587255510557494, 18115037054677722678, 8165849408798239027, 17369387099667572407, 17619066457126678815,
+       },
+       {
+               11047138821675365077, 8918121441180891972, 26692501222219426, 15248413052700323978, 7305399157133896461, 7065644238942265367, 3949166834387057064, 14178248206708015607,
+               69860179712677448, 15464996655458230480, 15095351218136595554, 3792171085643513009, 3187131848664503636, 12713332789590787064, 6278731049699775392, 1597379696359884724,
+               3952205381894147962, 11371446109407143937, 7231851263356642380, 11612512368538303138, 5227214975837085115, 10737565048439707166, 6333629542995218640, 12386725921557807638,
+               3631886121917081375, 14286411187847401959, 1546298555066841633, 4790996540037176549, 9541492152219486842, 12304868498960755609, 11426775785781090329, 10793898029125361155,
+               16970032026045908366, 4739834790205788500, 11604777595337607879, 7222013010088766249, 5472916641327283117, 4172262758310864960, 5724466588558015820, 1116300519629843659,
+               15795014995613238211, 14290583239597353888, 2490895887909073495, 11130992987297321872, 17554999787604367088, 3420129662095546057, 11472786435923282727, 16869713476687852227,
+               15035061229930585935, 453017670704522761, 13269498238801130975, 9381945743239523058, 2560842189862328725, 6461599464735341542, 12067824007347016987, 254830492191366350,
+               10932352970046201499, 5875690226460998551, 3699681560657289718, 8665743594825198441, 10232089728487302472, 15664572298733091969, 7267222702489958195, 10552093353886118696,
+               15492342672675114391, 415437554733257587, 12890781990283079094, 13204935186176658494, 16394061615709463286, 5115734945762570776, 10421418042968619739, 5523853293632283162,
+               11813086056645720947, 8830149648607040713, 12579056778157665738, 8379445845509747387, 11968812374998926933, 7579079245215672446, 18392522237039663466, 14209436550919930092,
+               10567400467353853420, 12039111362360014956, 9752698954159464580, 974455144078370581, 16749750902684349652, 7431880327875076520, 16572811640260132367, 197121614392940749,
+               4008236965647744142, 8547116629188387980, 13874587567755370880, 12696453513706541959, 10752386832421030566, 365775083075323708, 14295272684753058141, 11024897725724291722,
+               9389823976782902582, 12987864137510618346, 14351996708263571593, 9397276818616280108, 8943695845699072910, 16761881794918812428, 14395546039428720745, 9608138420173912436,
+               1876375509629583057, 3290820252719995988, 488255726920613097, 12524692306565281959, 1588481057230489293, 2737168321842385117, 3787136521155591587, 2297952115270241626,
+               14002797112021507101, 15941913959379016886, 13373428680779564378, 905956693320605119, 14911807685762669378, 13046351903511292109, 5010776430112230246, 13569296078340893444,
+               2399232949134869057, 16408469118941953277, 17229778225562184411, 15990256768949242309, 10694906341686584836, 2816242351659628719, 10794163145486835660, 15601904974333104002,
+               11025280186920123511, 2638544612389113264, 14138782464677956897, 8182901095979048555, 11304014986311338849, 5418181013691186545, 4702887342992202530, 10901371551431733592,
+               7470028071605003558, 15552389775050890646, 8285175978626575302, 11755261053723122966, 10951094485216236078, 5507384267235142469, 13239757172982680465, 16153920989213321821,
+               18058993449364903238, 13898361855323379776, 4830208064835445821, 2108287244297002782, 403367259355957679, 5208097191763320114, 5105753392567780820, 6874403921011777407,
+               1158521281204350113, 6232098057848694897, 12517518152351190341, 17852831094628421272, 11653774695260269881, 4420518556213490728, 13835371272800239099, 12119809446886544909,
+               13202632776652821767, 12444449950521044637, 11128589812117041029, 13640351754206364654, 12210309609173025143, 2998033188714623978, 2790558847086549679, 1412882974937756344,
+               8872627396983903111, 13010748252899511409, 9503554222158928531, 17266043773425260257, 14299273669130129568, 8206060595465248374, 2391269797717981426, 11490348680137544215,
+               5625434013536513462, 11006046905736534335, 12974260386406529669, 9092861657954444193, 9064784322822166467, 388172762639483312, 7975459140038679785, 16519143691087724914,
+               5143546864201185527, 6400878864024957342, 15513803558106064076, 6712861984922181478, 15623960351786428150, 3094277713920675576, 6184647748693682810, 7857605928718754519,
+               17306606255667524897, 5112741148301782470, 12807238528895999857, 15137864759480529337, 14604908573844046691, 17945466774813936069, 8840495514948749443, 11197321446299638637,
+               17220811598578674405, 4438480777123093236, 3563461541688367236, 3111403934731489046, 16319666149508644048, 11775149819643332554, 6467838040542164752, 1567553021477840718,
+               5384669083154912160, 17619132083131362037, 8938889855576647487, 9107335704092137106, 10077424566800668390, 15550874273916351174, 15171215175982142697, 15277375103802490853,
+               2219152199405421709, 5367881810186787185, 9606063680551349934, 18233690822105957780, 9941441403610160291, 14996958158691873775, 4936282940888570414, 16608409936766385729,
+               3344228690528365773, 14741103791830625697, 12105806333035047780, 4814603778329751458, 15692542571489717296, 4074467482166609769, 11583878004635312071, 15057041878895842153,
+               12046059187840675577, 1106267261822046486, 4800396230944794513, 6983782857932290361, 12630891077786998995, 18331269049237387531, 8843236455524152484, 8233277245902259517,
+               4072376012468301087, 15956856707868364136, 6651399164294705117, 9169559249495366525, 8774931051408681195, 7328702764302633441, 3821510551720221090, 13559321821383641691,
+               13270099407878039596, 11569032926557804346, 7759575992876193458, 8239088820951102451, 9633607727685959064, 9775909232917811341, 12297921731498614906, 14756100221590046549,
+       },
+       {
+               5228416958727036186, 12534300056259911378, 6859045937063682340, 16561718753727911412, 9427589074776024847, 4167904055656501509, 10156691045253563236, 17557096561606923049,
+               12847261474293104380, 15935635664155479706, 11956861064550631146, 11743590506948225647, 15973092866215748716, 8269726904881958353, 15639962392523441528, 15171417818360069012,
+               2605212343977737441, 18393471024186189813, 2302707671753008158, 8606549841034095192, 3842822953634987820, 3094721493917442423, 6408313759447502937, 13486364200254727287,
+               2191808101092881088, 128992526124656216, 738676021426139131, 10157323147642681558, 11221959943853120586, 18255489816550713347, 10885231659068427649, 12104397395119665023,
+               7707807226411417919, 16609863548699265350, 17639371636697428128, 8755472387723764172, 164779854477783265, 9714199241756765614, 3491355372893948450, 17683742455036967163,
+               13595758632462338296, 14515163666150177917, 6720823780841221770, 15071435664343609336, 9016075014492765983, 16881277609836316886, 6969993988115170067, 15419704786434737070,
+               14933348768149415725, 8499210770493553168, 6778840616148281272, 13282837866452012488, 12007326272174861053, 11172739862019218274, 15202495365302649711, 8797477675597086120,
+               17862558746132168231, 4941846130090682869, 17131557654945008226, 5312800819142473968, 5818269467205924209, 13458582047859447022, 2683428091382447153, 12956887954464730664,
+               11820752998821943867, 5623379642132478491, 11666807493120740820, 7241997274572162616, 17165010508995490690, 1769225877906480182, 3814296306467163522, 1913823003062817434,
+               11936813336110488997, 3878433838529606580, 6540053284493149566, 10610279324743393563, 14079852809920102066, 9176732841330794388, 14287311909822853963, 7146204303626670196,
+               1222343790928490335, 2199405396044383670, 14080919887213592148, 7341303626667347624, 11784881532696657518, 17307742911086150556, 6036132721599132043, 12167106497065306941,
+               13817073203406999359, 7220729284169210756, 14908407498603601482, 13536224989620701632, 1615171540711527931, 2063856048260214664, 10622581435417474559, 16378505765730768032,
+               6855676470217754770, 9517149712286624325, 11080380031068971680, 667425509348698033, 6136243307299269825, 5326577850303193160, 16120190278345757447, 1982981965726975383,
+               15399454106099176868, 3988744407816581672, 3596277710300384050, 15129113714633923498, 1554582462382333698, 3164553872715651710, 12729140363982748426, 16366728035709811784,
+               11647936211409428873, 14704462653811533865, 10005129575282387925, 1526194796943187368, 10906326807488904308, 18256878690674435807, 13093574545395154003, 12352810226542367406,
+               15290817014272444879, 8012864091692295774, 7591940515496590516, 9299619125326026848, 7297256232167521068, 17861204372399797627, 3100022958796565106, 15313770879200204613,
+               10190931844127971311, 4449277895844944513, 18060903840299422620, 5786504870079014862, 13877878835839147302, 17536010013969819055, 12266576574650233794, 3344384108564085445,
+               10406231172694378191, 12785551100938284935, 12210880209800471137, 16615829503150405150, 11718424737227538631, 2245674303359461903, 9283401225508960391, 7699506693893764319,
+               2278745583218618906, 10638058115573097116, 5685140621618740987, 7758115175926730915, 9043786871908073988, 11442680114439652875, 15805407285446479015, 17615595308217319903,
+               17127838629068819444, 14692086977823146619, 2491742894643214379, 3238012827598604955, 4066194902402629617, 3613111175737094005, 3296022969960608152, 4860674720288543209,
+               3753308721541654311, 13160824061458819791, 11298768140351857216, 14042645015841972579, 10518697187157549363, 9641851844202952198, 9254393371864075771, 11429987449073904258,
+               2566815986599406395, 7824829323439900657, 14465315986665451243, 2957504741164666523, 2280672126115151165, 14999624386740200468, 6090063205272921919, 3478652904863279960,
+               18131467168461028363, 16471039226156513736, 14133684792391617163, 7137732710914086892, 17299189471163637576, 17270681183882183871, 9046519354210103502, 16091721986926209161,
+               6572875037492082093, 18318192911446580882, 18107990043035854610, 13573958681720538720, 2821064027974708708, 13000417359062035623, 18286430707379660800, 13070676610179458046,
+               8521670721910745896, 7440450230382417926, 13794050882540606099, 3657777690979179248, 15466400576048586018, 7802926536345945651, 11932698778931413693, 4291944108972289013,
+               16729016738422946915, 4082443597391481873, 2238453914102498318, 1806710580451019071, 18305396377745213463, 2262209146853870557, 17240603302299977012, 1540474707615687112,
+               16013022710115947086, 8748688582020024424, 10921431579160628425, 2228053349060750948, 7024441100951863599, 15816203310189470753, 9078141084316010447, 9841344410499582933,
+               13377311905703150010, 6352753896568161822, 11086576920416079356, 7629848369702522073, 5472036379742160857, 6535781794177956975, 7671272114437903042, 5056286897725243410,
+               14579350500102276494, 5882738271691348624, 7188200631561491668, 3605286077046581049, 8957701412704914688, 10347270272487533128, 5995825272041784807, 18321189862831103872,
+               2376178340116743056, 2263593380938083722, 1990228394694589285, 13477447633165073333, 9023956677421314778, 7820910817739139038, 5288765314200405868, 13070699273589738968,
+               6765952613794178887, 347733275422001747, 7640026333627494061, 12925707101320796635, 5670472934143686904, 15041817307271371058, 18176041895529109656, 6838891343875575060,
+               9902363248877274636, 15776195244792726061, 1935342462634574355, 16572507349421626602, 7503944294807242065, 7454248748618678609, 2837392985175901475, 16494567631149775512,
+       },
+       {
+               12299242278498309265, 117303082144788574, 18382936515565701803, 7941141688858846015, 14923823358299367958, 15681089039073030752, 16878721085421212785, 3933697483394042011,
+               2878536922988449879, 8819365314325664735, 2696760638950720974, 11357179421800829605, 14730809809256560583, 16277258726425730599, 13189689275745970592, 13769784951430309444,
+               10292669945637125918, 13595563061674492799, 18301330068714272653, 16981073598172019270, 4022713583718555211, 847970754090163894, 12867993617169467387, 10021141621864633865,
+               15254713655124736464, 6283719686609422435, 5417864180357938798, 14010638809605797246, 10873690600705871523, 15014239467130590294, 15765460219545280655, 6048061577845125750,
+               13465802402879986040, 12777495579796377113, 11251142258511736751, 8312965145580158560, 223338793373356823, 813747086573652373, 534790745256052224, 3658554932030960904,
+               223170064814687698, 12938716002978051117, 3848816111228150666, 17463649319617382466, 12886402189488467296, 9605942357133455486, 12272689261734151433, 9916808458308982839,
+               2879267873712146919, 1770061136847768757, 3497337219301780129, 17065005588401306579, 7675751531915094916, 4337540836976665798, 12505868586426061855, 16929961945120117126,
+               12012729503226546642, 4811951115754240681, 2652621264600062520, 1108958391967017223, 2508980100759035797, 9023233544151778447, 11183557587641545146, 10726727280840759519,
+               7189877122763725514, 14656082750550993666, 13508306914749420120, 4564443784575285318, 15450566991657647015, 14019683331552104148, 7751003035652012225, 960642801291306739,
+               4621870789074053275, 2699296606556701282, 17510056683561737074, 14554735156054608866, 9556940770704438829, 10801168482998872433, 2280142648958056556, 4982572404720159279,
+               14621729774738200671, 16850208728798178903, 2650832773786164628, 8325244333065591089, 17692120343646193143, 2242845836784335580, 9386711085286369304, 517979059098779699,
+               396296174223428093, 16763788748988621834, 10606803701784640909, 2399987183687936561, 3641562114746393614, 8536687357022564742, 14532545286961725758, 14658331097531946901,
+               13237433907493396869, 4990918623816750268, 17673032790739307275, 15907935024302716062, 8613470231259845273, 9346326052910147032, 17747177708802561938, 4490130127498754807,
+               13867405496809412712, 7002613759387491643, 13033935552806967378, 67437088702121131, 1528641041740753990, 7001198041125832592, 6102137699349551632, 11527483925092226802,
+               5535652777947676324, 1216916140919282417, 343617165825197489, 10806931059627863289, 3212291315152120591, 3351900116486367965, 8595828725191802110, 15621077401736893558,
+               2386026063595321071, 9144724461940169335, 13121187420621518554, 17351696676224980491, 143495028693925520, 4590642171152119027, 8655406817079059692, 10005507077955932112,
+               6982427644490593208, 5211219672384700779, 14348546115682624722, 5876199850746516331, 18396840586595761484, 1465795856184232635, 9374516147960853174, 11803025633575966436,
+               16374709377982692229, 2545295070586009694, 17366393861359867323, 18067336234259281315, 9181658491221440805, 16188192004088261717, 13669686513572099673, 2044092029751770484,
+               7308293641399229883, 9813539775451467496, 4837144575100457648, 14073521030008335794, 12371724228966966456, 9185074727660313894, 7387427551441329556, 1866580457929037678,
+               2047964090310465728, 14133690277069748515, 8287749071957055844, 16821270580974431218, 10324684883587585565, 9652498187344172497, 2461802306013063247, 15048850312040680643,
+               9659170831875656345, 4251587871822599596, 12391279033133774782, 7346556824831912968, 2133114137534468833, 8694105814921565301, 1000087733076615381, 3478818915231998954,
+               15832320183998834886, 898251865651859288, 16874504161383651033, 18425166917936355349, 13387271833996394553, 808054572728974308, 2281828182196149100, 14620221246129351423,
+               2755242181069093228, 16155597320469161129, 17375128328249992589, 13376690667170223367, 12825454052191060221, 13625129606409283552, 5627148592782580041, 3092789333954796605,
+               105705035058376953, 7541598459498134635, 6627685529861836787, 5724525771392188178, 13865897118300842617, 627652561624109853, 167084371112939132, 14192831153344015422,
+               15618434900514973465, 14267977447705810206, 8823759714826430108, 7918740515193061263, 1664424041430494212, 9076733744947861202, 12010737794701759719, 13920688631446302868,
+               14823160144680924028, 15690572793903331709, 1101762466949115887, 19462496059060771, 6099422315003219574, 4300077459158116870, 1282001407902323746, 5792772971400374848,
+               11488321122368726901, 14632273370344181937, 12984850848826263218, 1857014998357880446, 13897135914532207935, 15925630222053677390, 11992050787349110965, 10072349923584966035,
+               12837696619944805389, 13470316523008526719, 3074966674353053986, 2630814767089382743, 13353767941686870870, 11405513520090968568, 3071969598389884693, 8212421686942839224,
+               7866179127856055582, 11874624506147226333, 5793384221044709375, 4411967221310302622, 3004913667339358722, 12230878672003882045, 7395980261120250376, 5188846147165419817,
+               16160221386626609076, 2876994290210606255, 6065036384672004173, 14696333348949573335, 2667009584785381424, 12100192661844794919, 12401945669155059163, 12847772853650923808,
+               2286437117905535902, 3130250324287833414, 3662253455746154641, 13229041365675585947, 3663813013822489770, 3093300797589723687, 11507645566517710232, 3715061633580408995,
+               3464453985305889088, 7486900500389940957, 8944303108517222303, 18319933556403836918, 6782476025105836770, 12822840946923377510, 2799592944286097404, 8737598030273298051,
+       },
+       {
+               2754563581284692865, 11257360722362829387, 8254261291934606879, 10023569920325096229, 7980898855627864603, 17162063449612285703, 9275759455936104363, 15936804738099638644,
+               303387668469489035, 7978391052264888020, 15413722057350324494, 508608987485166058, 5585753287556892522, 1344134516582665443, 15144279405777509214, 17014353449841567149,
+               12518577022215294774, 11347384788122950558, 17122718824958020364, 5431993665805279177, 1445831254446028321, 9845654210244803480, 18315778529692612284, 930563922336183289,
+               4894710987714215219, 15704993603878996107, 1606204036324478223, 14308635149530198932, 5026736228773269251, 2911689442372084137, 9004077539360196849, 7770049130277452000,
+               2745120518194234905, 17255944807561408883, 7371907591838942770, 11781525288383871227, 7814952754785494862, 15022715213812536212, 4112388658963418656, 13703771908397991335,
+               17455440140812341569, 16738670164475421762, 13259904130186215994, 2168106064304872507, 1969289843772256992, 9025317999701057831, 5835661391798891929, 3826587698101558069,
+               9149648374608464235, 7248346993716635643, 17283919168525322365, 10107681064815728795, 12176813938029507719, 15110337574289033068, 2436453685316043712, 5876967059744625564,
+               6197919059881189313, 3300993078638782623, 9357667752372201437, 17688129755135009447, 5477090746558113696, 12602024521188880300, 15889961935507293355, 7135039746373941272,
+               12561063426893244305, 3079971284510744316, 15695857190375815873, 16730673956207425338, 12065477821845465116, 13846158368121919228, 2126156187526559500, 3005167441915916768,
+               3858987859895327040, 17043903959888117395, 5861237635520080595, 3292646198413575902, 14286644557048422360, 14346409530388980974, 12583555046601155161, 4665981927428063991,
+               7657686120974201842, 2388299767028319466, 17934808017791217639, 16708640707026372313, 14122341266134976486, 9547124998857374491, 11194069918436025923, 14657538980930727877,
+               18115789712912297420, 6543740714573413570, 1955886376702349613, 14736853369719086334, 3914330395250768396, 7607848156418885173, 18220633528980056514, 11930952850158858930,
+               17010681753474701341, 6961088634819162945, 18395881317121515295, 11611411242007267179, 7996717433149311639, 2687736005475404867, 15340214362731923149, 7116441414289074727,
+               14302198697220662403, 11915041511943922518, 12363437164440173650, 4047410026894059083, 11439743031696133447, 8776097395071907030, 6851061783357383945, 16484733576581941012,
+               2861660066704264713, 16453202148771053225, 10039035813504063627, 6275446616881871868, 7150609984920482782, 11100941755544354363, 6219760433202580646, 2875377482232912143,
+               16477698187919702699, 2757160833848759781, 5976267476122243443, 7375951277779829055, 6525111513935493528, 9969722922172879681, 12582700753056539952, 3861958159147836631,
+               4207324524057007052, 13478421263392765917, 13318275642734768006, 8504333045658265535, 3960720256367501697, 1601661680373853468, 7704205542213854353, 1552780884856863914,
+               11788483659211580527, 8739274750400900816, 17562450707643849072, 2113004873311762141, 8542099133996522813, 5273956141012313478, 15661081976505113338, 2290009483289921559,
+               7730337285529332076, 910421998453976119, 1242962796308775978, 15931313183507922513, 296811920445331257, 5821874870466240960, 3843405649348506130, 9007082448812181532,
+               7200777231000974420, 15816416455380831370, 12932038056359512011, 16422801186386616731, 489979647738684819, 8269568123908387407, 11617965045895762979, 10069799398667455631,
+               8245819835927284113, 5237630684564909794, 16572245571184457585, 13396211619915630497, 9177789877937729597, 7598297211302983411, 3133511073496333246, 16553020037702090576,
+               13441991323065749602, 15441570013111011986, 291172418860690999, 765089869758770890, 15943751395897588683, 1887511823199710563, 15452188663399676440, 15028027691170546376,
+               11009923302693800320, 5465227554242327455, 6511134004216481185, 2187999546010819375, 8387421071023131689, 174295266381833460, 6010935117399493668, 3340537243300033200,
+               270646782953286316, 6635640130829923909, 12717598479778596267, 3198506535831522029, 2605714695474737827, 14548588937126505914, 10448279824323025574, 16008560590494788290,
+               11460241048816176102, 6557818897531989327, 6948658872009630691, 12506263743501199667, 1813031030961999507, 18320107449706503757, 16783076453582799039, 10113937529079967843,
+               3096618551325580575, 16427990761832670936, 11792441105446619028, 682188988823121368, 15606025696371121549, 15395362449248397023, 10158149307437310549, 4442375503593769727,
+               5486499432056098253, 3811951715772590831, 3856863699598204250, 559724736042732093, 13251752681229681959, 3173330346541355882, 3597530263899943500, 11567248716558420280,
+               12822024566847931229, 14487146762942136806, 1361688279016339671, 2776885758026394514, 13616222293131162973, 4629388276054227930, 8304132204812769256, 15188275451670510949,
+               3676452641243730693, 10839008248003066479, 7676518604603740317, 18384275325050378660, 7827069556104560937, 14335741841451672783, 1145975213382205474, 13691620069378415495,
+               2513451633312793643, 17331457978938147928, 11588204658848186728, 8824497684232939293, 5956154520546906549, 14434958079241686709, 11798870987920360447, 5875117843056165993,
+               11313908033360767461, 14678575871510948417, 8479250768537158849, 13854183783158898926, 9413525381201650053, 10077438283140087199, 11413783222317729281, 4418417663988371635,
+               6001837395299394988, 7545846298204709215, 6662102781970969966, 12696054550672669874, 7436995610194789060, 9042605089262227561, 11621508125069628605, 7289479057360149973,
+       },
+       {
+               15555649500689005370, 7857014165815014600, 4664069234996337119, 8058230521837307501, 18090421626009183450, 9278179697462444898, 17138879353097908770, 18285223269807746171,
+               12741225973381753432, 5461579923265799106, 4348015554411389960, 14970536173310927872, 11568371199139699619, 11748662751675667230, 15495664823061891700, 670495577617908409,
+               9865772269601493999, 7325690007062740244, 18437964667185475354, 9546360111100619473, 6266116854923135821, 295905071295541234, 16037468634731642095, 16602609756229843150,
+               13266892287530449189, 2232961926857263527, 5934654989155432442, 5415975493246016158, 17117784386882463158, 3875398271691758986, 15755743581177209843, 11380746535012415659,
+               2047267291755864302, 5637045342080349843, 15779859211873634959, 2415175423642772217, 8664113127182901077, 3032959071705433205, 4250761979529656864, 8729259992491925346,
+               16559648310139278090, 4796731467175572814, 9267555165184254828, 1400425639375650333, 5199035239208036114, 7994153995816640929, 15677746297407711038, 16338895562326287438,
+               1740700879164022194, 8442598604870387302, 14969965175291161450, 3086786406508018865, 12097766404705693713, 3199218739761578935, 1744290654371906763, 3672816528005113908,
+               10162459499000477259, 7534168794800651527, 6320985751131807192, 9263840233901040421, 12178625283764017250, 13143797113231152006, 13089053551699608219, 13480464010111258056,
+               6572275813002629593, 15328678880838895837, 4281489161088939969, 17996597009627631572, 10405019085582914256, 4773602940383417103, 1455403777441353089, 14766164051850429812,
+               3886207141264898075, 4215113531127552656, 14283840761174092490, 11161507022796293343, 11235510295695006534, 2260082644337974884, 3781681413610409735, 5577127823856153222,
+               15609337727165147542, 5725010295752332028, 10091444858515990726, 16162855978360002823, 2478705273652882251, 11394669968372227148, 512641267828429208, 581410050368207889,
+               11426681347395118622, 17135867298562042628, 10870734720453621112, 13803364322975322217, 9740527283062276630, 13765238480893165263, 4792349632705804116, 18359029140065847048,
+               15215482935039834459, 3553551735757600990, 2471323651039083728, 11355669733892999598, 15830640053604899661, 1625382463038435804, 11969247519895019474, 14372668755409420943,
+               11113773299077372683, 16618589175113863833, 12580653821785550146, 8264195478884998326, 13569468260761711850, 16539804400793525042, 14464540796871846551, 7710175783216723569,
+               17565888320840294282, 12018783137972195797, 12159604578082686310, 3210316551614996638, 7700243787046971168, 8307491254792612954, 18022719331150542511, 15890872243361196004,
+               1420251412241033168, 6449255753238336368, 7468624722117319576, 5716072259994197219, 8165015263320602150, 4757529151848960259, 2040364517493350115, 11069642333484542749,
+               6861520668253090597, 14998859189233167760, 4851545815068976365, 594940747993801912, 8473464707442482665, 2316305389548210767, 3995416902578245152, 15770229481630179441,
+               7316766449463697051, 1410976281384361962, 2878678490331118371, 17638505404208445694, 1130528985192221086, 7544558337870473835, 12071909234624857373, 436426448500115731,
+               17436263074416557505, 4339627812592344328, 1076653379358004720, 4996950998108333398, 8528954985898069924, 8259369611572362613, 7869239207308554342, 3592003501289265534,
+               9434687670958330812, 4808705744496679962, 13910334628239183613, 2628594509406050235, 10055911465166862298, 8069256921143792190, 11886968715847498191, 6351594160398684406,
+               9865961381837093259, 9590584894285774485, 10674927452501376239, 13861388033657872936, 808108663597281834, 16581187679405825998, 490312642991375167, 11352102610468872412,
+               12888468148530619065, 542846015600866106, 2086677842713697080, 2758534484095407635, 15767123419143795297, 7077908316515201321, 10297306681753168866, 4641656730233236179,
+               104445550853777927, 3829969899624802332, 4713997522991885393, 677661257782477991, 12383280183673921457, 4373178143111769979, 6375181113677777933, 18335077047046332699,
+               5472832021993175857, 6120966193470238758, 13156950075464061259, 14833372202848630444, 5760885723102571027, 18022572190906170343, 9870918995920897221, 9546055667466056471,
+               9516299398994303577, 11139435630263588724, 7364473923787049608, 15378275072059759415, 7378721410182635028, 2461490895435109307, 2579531356642691202, 11061693189962996686,
+               17380308085259417126, 12584808641030185141, 15485460243194852460, 16172215807782473427, 690761937231979275, 17570908286361380250, 3347059970688467328, 10404397759606846636,
+               1302709369035452282, 7149637102192386111, 11659118804203241786, 13909758997057192683, 4361167997834561257, 2300569874961985919, 1609719848856066643, 9866395233709297503,
+               17124591880405051324, 3379747334483646957, 2084957978131092947, 2413497199486596627, 2867893699156486423, 1357836849049583382, 13607307985344221035, 18039194570940763745,
+               831259058391834318, 12782538711785697535, 12640197944141330321, 11004378265133697847, 13622812183191119169, 5878590957416415562, 4810392157669422629, 11128662835376944411,
+               2248775486830407244, 1550340755758127506, 8399436463450785695, 11063895076440303538, 2168511054719571959, 12238498894267955838, 10824266376477587807, 1073243669335517712,
+               13568560319245254019, 17615770913976878569, 13214159705850440913, 7542574047209989510, 7392331519546111377, 2685908847786414772, 14835825677444128105, 11347648758435372538,
+               13230815692170010235, 10662664037814374845, 10120384214921531334, 8892863196093018212, 4443096401408136417, 1896901619181196514, 739574867683694091, 11233952771600927581,
+       },
+       {
+               10708602749843635238, 8046488591192123621, 11391158257016334553, 2512908912806916201, 14760224624269838038, 2631910198880826809, 2387247811669872033, 2048193899742148806,
+               17392983665205025720, 12603331233691760840, 3752711326309791976, 8281544857330094164, 17004651346561270106, 10399322540256775923, 9721299450284863176, 3725182263994944884,
+               13643198694788276032, 8127425924819487897, 14165945065582850538, 16520977003164405917, 1941948502806705647, 12390949208067741787, 17112117376594486408, 10232906951259490042,
+               74190110112564319, 11227229657066745164, 10151080599595091944, 16591051376074591375, 8256332495682655293, 7127985739945537626, 5708687346183367016, 18310921046455023281,
+               10040565835468209502, 3986586816478505371, 7957179672896506016, 13347112914739722590, 14099734293320932556, 13921950344400895005, 17478414833301838037, 961445463330402797,
+               10553899634420153414, 4215979268474142438, 3643081140297634139, 11620906704125380460, 17733628678553828301, 137473878710304143, 6211837577294956591, 13926110616399428016,
+               15203257341351417031, 11597829209697937782, 17317571979811895272, 15929491640570317745, 5731227916276913121, 17093153916149088230, 3908757069480556294, 18211818355208735794,
+               6887629766078662088, 15330755394432598442, 14144608177273202986, 13258654996547018856, 8975611270007504091, 16869834856279102361, 12707970875852047823, 8520055680055874514,
+               1643407997152867899, 5400650551136488814, 14663391437159245064, 4743209938058826866, 1728998201888511561, 11238331920657195520, 11617984741897247805, 13858029141809651878,
+               14003691155137683825, 14641672309228817657, 4031783205073356111, 7414359968614421153, 8166814052414482491, 5209260157266028169, 17555696996149558694, 9780166780476833956,
+               16029688335186691281, 4244772808651443261, 6450459413414527821, 695875191412722741, 11104054226249884864, 146461617619843327, 17480214580411209436, 11285418463967817315,
+               4922928863857449168, 7226901725606965824, 7568276305032368752, 6253457805758596797, 14345040877576203078, 1718759302498746946, 3544444746772280646, 17880302727399449566,
+               10693864548794383214, 736148233485985101, 5241869061152863453, 7166954323782542739, 16861482585847848251, 11483636939866570861, 5950529069765100144, 700887039653157350,
+               3906969739692830848, 5546431121705298614, 10491799900914853406, 5871175286230239238, 2851574662174517162, 5511397532379144624, 17409985391224790540, 319012646822749823,
+               15269778527761027251, 16471737837294177924, 8830398856035267114, 8206807757132984992, 1421214226977370752, 14233751335943482739, 9668238787333455452, 8700964319357541954,
+               17561670470565298976, 9524122142014309347, 12619871254022879995, 4098610542031538614, 8338691110372464881, 4378598564044777665, 16435680634249352743, 12067828180476756532,
+               17102475410743425567, 16244272017711449252, 17598420420289880464, 17858587557620312875, 7275673248698358659, 13952444068457447282, 14004356855576602555, 15776401868125266614,
+               9848210305813205280, 13777844361911806961, 874096498600831552, 6286216140019341540, 1229781121487503670, 1221366673976886811, 4534525466071627057, 12966848050780717673,
+               14890015174575641658, 7082696407720868596, 14546372439063914434, 18306301153433516531, 14360952638570231274, 5387283652784509262, 7246876761413034655, 4917620254108676720,
+               16572428185201836512, 15535161956998457706, 3118508753345802652, 1036719175817464914, 9929541174185476740, 17658764424885337186, 3038747611544544975, 9299826573437432057,
+               4068144934809412921, 10422353259330469599, 10820596685747357573, 18174251490011716747, 14838047097904304200, 6494279871501263445, 10908514990777375627, 2395220126873880030,
+               8963350163641627638, 7331858013030906816, 15047142507680204097, 6113080618647404016, 7520779807516814683, 10255234845683676901, 12010823325949652354, 4005195924244758895,
+               14455661618497189876, 980858168361168621, 5057114595071838088, 9447128440518577562, 17115933446433165191, 2063106073840638313, 5944852338857186064, 14601740796836275216,
+               12750698494453238590, 822220438401342753, 12735466470750534773, 15168985403101776640, 17837672477921333079, 5413174218886573483, 8340507718774735027, 3796235681866322764,
+               3366536195244539993, 13901131415620358879, 9146606194544531067, 7568835872371146677, 7101767951356426039, 1958938171972212156, 3871412404872561111, 6437054924013233533,
+               12849284342518738377, 6061751293342567452, 15168528907847693260, 2071752334274992986, 338461453751559028, 17270401493472349305, 14152214298057413781, 14074152302209367061,
+               3814267663972523036, 16047424572869508620, 328411057776532579, 2321721854548154476, 14950895796162035951, 2381867458906113095, 3121132178592915484, 11019696935452271225,
+               17929201703034060485, 15478512769360046037, 11652099424221007544, 8436785170867890275, 16340404489137765730, 13705192502407972039, 9464924753010269658, 17372624212933856135,
+               11237648987477338397, 850109691127167972, 6566350160877169296, 8028073340740368222, 4445151747345891893, 7753144690511205475, 7551118086710031441, 16785474804106433438,
+               3919851124685189663, 16028223238454025712, 9008783533564802058, 15647028843636411071, 2029953422298604024, 361326896057539567, 7653333452646403127, 9211397293968688243,
+               1817762546790624760, 15025271080704836746, 5761603182050280401, 10355268146728370750, 12900583599325924868, 1488036927944469046, 3405173852255315327, 5600132277974719103,
+               12574920924242276218, 18146097977073890534, 18281543194137545725, 4432773597060264867, 797962164984225968, 13432184750641235201, 12394976215803938078, 3054137600383896411,
+       },
+       {
+               18270562314314829224, 17574550722906577917, 15522987576586641271, 4200899284963891561, 15719788437321868967, 18390235318178988753, 17371818886753265385, 4583380351670429228,
+               10102001197913431240, 6211688443233768420, 1986665099237206297, 9248907879269017005, 3081890249882755206, 7828527646248386813, 12676034092230326487, 14655968027461080131,
+               11464797300361906821, 1444449385286554508, 12433005157477847389, 964895564896662942, 8457290958728547067, 7044433897330872257, 12292673928275053405, 13679355097865192207,
+               5841260956815214452, 9461234662498869948, 4761949640006529525, 18229823346336752572, 16055957459773168413, 4272222475092786627, 18249888117586812770, 4531982814021269346,
+               6528332072572425694, 15678657170585498065, 14462305190193144746, 10159286562616704237, 8919172138248087686, 13247073064443362933, 3056992278576665488, 8216417459286092432,
+               15095644792163717355, 9931529712396800935, 8608932369590222253, 17019087735655287783, 17120516184457264144, 16412592485673181957, 11221555966650765276, 6815162077372858604,
+               2239262553722461896, 16518231021003046485, 12875479040073845800, 5243141733462514317, 12216971859495819530, 8917663622006068692, 2606734295032613674, 11237688605489138628,
+               7270238601276019194, 7318279377964882079, 5226788506940171017, 16838449902078450273, 3375184937745100689, 16320655850583231520, 2173229791272659780, 9816381971766204380,
+               11061652864259684005, 3625039563689831268, 4435107405432574197, 17570841169180914890, 13981724030179216670, 4992487505540472327, 12893808204753555435, 12899171569920731024,
+               12002788024483301555, 629439982201171214, 13749214763651595011, 7164215996082938159, 63895081825959000, 7006379700570403491, 11929054672290963822, 14290981753366049931,
+               13554823979828564217, 15627748053816803157, 12924111102804720301, 3165135223777020148, 16345805559363705538, 17656153856991335888, 5211305829410935273, 17846236012427517420,
+               17113448198982970082, 8879656883528014268, 15215762680430094206, 15232212751792759071, 13699137317730183483, 11815206710130297569, 12298409691055054593, 2192455093917691024,
+               6973243752017383665, 15334919534387330350, 12203459507012560294, 1880762698376948842, 13008085926447766632, 11695961991328184563, 1311309249708428072, 11981691262998313807,
+               9209757463013140118, 6782250604095077195, 7896297860376631775, 11500117438976638113, 9099678680126826621, 11908588510950302487, 16863479726536938776, 6368086884375751995,
+               6220904427249143299, 4501361418756965744, 13907877383736656540, 4499586229279778873, 7233050316216252450, 2775027076708404645, 5669561106187108564, 13951461080947060780,
+               9742819322069712752, 8779224519997661749, 2591205872359340025, 9144644967919881415, 10495832103710459914, 4557264342687723360, 935865282128150338, 7120324256648044882,
+               10780007491891304021, 14382731247791652187, 3296810302419712004, 12567831906993651128, 13933396378746555124, 9754754796778422405, 2905077741505886450, 1522919492210831578,
+               7282056954663740402, 4915867300034445627, 234865561845141598, 8874426225092097899, 196269165389812019, 8951904020835594063, 6908903359164319029, 14062039535595890356,
+               17922518107542393156, 17388335427727081004, 9077910363057082196, 15157438705071651749, 5615196861086779767, 17404239261681991687, 9772161835068093639, 8380484042808490346,
+               4683169301229531061, 14940390399739549639, 13128742567354398401, 15222231511210090535, 7352694898928671332, 1221555526903686446, 8697118143614336514, 14515400523185205597,
+               1119145169329993209, 3453487026721044641, 13723232966162256192, 15282444658208236515, 17806849942057939434, 158876409507122147, 11954364486113732203, 17566268785944006600,
+               1443798830844295330, 5744920153630226551, 15739845606128975055, 10458513157123726949, 14711103578835123416, 13886988522344422595, 4454455988362290346, 3507977514728491242,
+               15328194945269186082, 16398971046683442289, 16293780909421539295, 14488637138080135219, 1108438550767062231, 16291467684905586857, 11891067917592351245, 10459212739896579624,
+               10239864229747754958, 12477284975467600510, 14054830413782031834, 17752968481181892755, 16082713391521411762, 17191329716867535304, 11245514405315337909, 15159733745232554536,
+               4102022129275956496, 9361580273813141387, 13824110615577377618, 17115977884930866990, 15058705994968389537, 8039281695081359531, 7179945727911625126, 17628825480910826356,
+               2477336341361304271, 18030759410783456479, 1164757311756325043, 14195508307731677040, 9794350654156795137, 1135232100348022155, 16693007636113380448, 17770308235375345497,
+               7064407865619227176, 13284912648471743270, 9099541805618279168, 7383718461788433067, 3311987567268438113, 10943963018398042859, 8038765968977300792, 11039205462473399718,
+               15444441705629456398, 12030687282161152512, 16500102437404896225, 11467410246278043769, 14031300093087427598, 14458597378298191386, 9434445586505481169, 18221119130471329822,
+               2269899977501467759, 9674818903084386596, 11781166634280447465, 11752600152694102168, 14011747753002945247, 1084585411243442928, 15614695372212325691, 17196679090968022414,
+               5062812993852092949, 13193601915773858975, 12910718608861476282, 447390754333146274, 18393090736120037653, 13231946117349235609, 13365030203093499221, 9724404925244523782,
+               18064151108813428175, 3928735035534454387, 186686833744587171, 18406101378699384605, 16477405641027895528, 697258480673566897, 8958117283476321666, 6970167016227017231,
+               12694666558858009121, 10992313774737315187, 6046508760845509477, 16818819584649823054, 10464090160691032219, 1221502600750419478, 8658907655588546849, 16110628890984509877,
+       },
+       {
+               6266830413981331818, 10890859480409122410, 738708598357264321, 9241173142142102299, 9152169484987657321, 12122430118903337055, 14270062735458703743, 13877635605034675649,
+               4572419849863661964, 16330741525817240677, 5456771007607263420, 8798510164381810403, 16547183593064549865, 11355135595370359779, 17581910791451710925, 11684604415749005488,
+               2766130068233451740, 15909689412657372214, 3272828023364980896, 12907534005596438003, 7065629942275705493, 10609982651084321649, 17330343421617897811, 1746246157222856918,
+               13168953859078137190, 9072500190247791267, 11090199374278127099, 3503847851309060744, 14395788825673846582, 15073993563711333791, 12879874391706003251, 15417028700542288171,
+               2686132933630431595, 334448852204016400, 5636563341880055087, 3897420469445246068, 10569177829735084588, 8244586887721364305, 17973493209847502315, 18083956436923498083,
+               15514509130323617046, 9833490355170899102, 12028021566105512521, 6349458533674010018, 13470024118569549588, 7867188201997717819, 6110792121234766402, 9917858515766574695,
+               8273062939911446888, 1936638151089648185, 44602505720759914, 7839132833110815763, 13045756168264521992, 5375972549477973022, 16964151563535745964, 2871770426902555432,
+               14164643693563803212, 6386904235704679249, 931435629437735510, 4496152555914735639, 820099532545743339, 13419988718062417698, 8948965620484833159, 7238410427920554862,
+               4387941928212462673, 8023190031094282215, 12322462122895470016, 17311901330042910195, 16445894183838823370, 690424095855074674, 12820742226551488738, 227935274674223825,
+               17437729542205914525, 8439533239207225162, 2862942422640746698, 7340866642549630610, 6770451500989398335, 17262212260581413381, 2156505157624055602, 12195119268846383898,
+               13685370053507732180, 8304030489296890211, 7042719123662732989, 12115154796394040286, 10496877583013829980, 8909625177349683785, 5268451666475070682, 8910488385056259560,
+               8874918984373509240, 6652428549855789281, 14866714872885601270, 12093494664302554643, 10149999253136441007, 1611873554177023520, 10271627298853910516, 15171882630355491729,
+               17085353800722834618, 3271271583189511718, 9338466116389304614, 4685545953421459012, 5059702655119414343, 201476627889215522, 6388612869673101372, 8357217932305360896,
+               1836621694151238424, 11438765101326043062, 5537182303007083642, 2657011195641217678, 15370176245454161308, 1478361893117141052, 8729368992402422055, 4807782542738120272,
+               5084555197036037383, 500829604818691390, 8128181767026348964, 17895639808733462562, 4138748420878083709, 267892430674902987, 8954358455330696651, 1946224964877667668,
+               9440495138081785154, 17328162383695942099, 1870751290505230781, 17987066187778049275, 9952223038481207705, 10126409487298126876, 1181369784146909444, 8158422380540037915,
+               13005094963168549814, 7254364757817833162, 3708127625424981603, 13214729399033107803, 14306349749849146051, 6983270854272831328, 14340019638575491596, 704963281855585401,
+               14561080905697443279, 7640393429462623622, 15685656608213407004, 6317405842945074950, 4586197269496115618, 4352991463721324184, 18421865732314202847, 13679296167045126011,
+               5024751682397066348, 16464187416447039066, 17561916915150311869, 1553872229528720506, 3971081625989469183, 16363381852589102144, 270446294712200212, 4668332646727035585,
+               4623922898967168175, 14927682190770218553, 18082407698612059245, 8156136453512346914, 17256761355350416250, 16185397881787027880, 15277309552707416345, 5991448876439153037,
+               1334994484802978518, 6876293985013000163, 4439518198423905531, 18287119869714109760, 10942138263490204506, 13981840082343935999, 186527448590996253, 11759869552919496944,
+               12652601656062843187, 3947181446273381189, 6235196886760030384, 10531746495897900463, 13249616872107073217, 7937663398525899211, 8701780810784627798, 5901496026068341468,
+               1059285256835989485, 18284969105568513488, 8222225088165109003, 1178299600673068913, 16068875143685216551, 17849596766342630525, 1648308197824141718, 6344465813776674352,
+               13850247359965870279, 17391106451201459411, 9882112511974412840, 9027485913083134379, 2654737707750698953, 2829872619210764000, 10765067664204983675, 6008367494734883394,
+               3596754664049660092, 4049565277418079196, 14294713401434678004, 682517403208603499, 13234861305501540306, 2878761138137340816, 7563571058666806838, 10752984583868770507,
+               16399575624290910947, 4698193514990054887, 16222170007882213172, 6300376482027477465, 11587700570984519002, 4408509191665524069, 8909599698892352923, 15110169407475815879,
+               13814725956725513903, 11675366986709837701, 8008867936756292473, 9627238521208818281, 500674066787171963, 7307892989752288627, 16701476208533897826, 13745712031279374379,
+               14988991093658383268, 6586109441484875615, 1456715231981080716, 10587865765103526958, 7439504550868615754, 430398141621608230, 17710495017725824018, 1267747579289674850,
+               7939033276966801601, 2952159422351169438, 10439776924885737877, 13630489377585028212, 1779349587540144503, 17209739673050012100, 4174716919431642272, 4986592555205663040,
+               7110204405213656469, 5225260473696365908, 13544564684169074596, 10807318789744351361, 16301252682064971136, 5046748520130689465, 7049174921499294642, 433785658536711265,
+               14622798677938552282, 10254953149954221954, 2609148400899865119, 8197897294400569748, 11784700166516996756, 18107483989994737564, 5332550435198791193, 13389061302706010047,
+               10892870009313407934, 5709686117526627488, 16343828906887149047, 16063790174205876315, 9076070192754075075, 4639156357669822592, 4904064385440242264, 5942264027390072320,
+       },
+       {
+               17271984572727555145, 2097715321690717305, 5328035183708920909, 13206781766168781008, 5915693606819932446, 3870849056297265622, 18070792155150730518, 7786839743829304936,
+               7939886940063870939, 3597929036186322512, 12732772396498766041, 13300425267730247515, 2345112231224079293, 12327614629296314761, 17106102937162407683, 1702694317559034053,
+               8821632341545057929, 16708916351043551467, 9171560460858577216, 5711973041149612575, 15808302665077457285, 8412173943543358851, 12602476370021215716, 4778674887660148537,
+               2707032230021934480, 14943945588296447659, 13333962501998857701, 10603744732015256400, 3386903941135274495, 8507451908469049716, 9231176235773710950, 995464562185179329,
+               1251633503842168929, 8646405730060859011, 7525758827556699239, 12781503299321323139, 3762059070509735358, 12904588764985510882, 518456268741331092, 2752400776174997580,
+               2965193395248314453, 17005383961540689211, 2510904953800463288, 14582093408745785683, 14930278391247460535, 15319775861672772086, 7915822626743762260, 10481055458185028303,
+               750419144665626202, 4009275022270511551, 4810013488865977907, 13090697535304919393, 17408171061427940566, 13469810562978287715, 3952372983235223818, 12596642250700034956,
+               1497127512412966214, 11292269970549257426, 13920714718237672232, 1363993524078475237, 3687544717271789391, 14097532154250414203, 8367320351336033564, 11089672460564007700,
+               3927746316404254574, 9973240942982210953, 14122301504960485144, 13249357693517290445, 4259646940372475995, 13156585130751616020, 424701295260668232, 13006066175253059189,
+               10308406270137410351, 18444509448482991837, 12509509048086126555, 8343613342319774737, 7902938427788958534, 9924925722974851885, 3762983399809982874, 3397026083592781307,
+               2116063253535766674, 12792173758770945620, 11357854367169339661, 4502375174987631263, 11374536277081101446, 718846097450449491, 6555869089578359747, 8571702699293548804,
+               16993953276024768829, 12025590727803527383, 2672535181364381995, 2183111709986676538, 14822521615475063339, 10618745739454592027, 9957515072444869664, 4797521918890127374,
+               4582720743315312164, 18280419827142252016, 13380629421749133990, 16786942173448683921, 5929601960379909803, 6715621236552343797, 11192523517069751956, 228125323996215945,
+               11861176681909235996, 830114321507110720, 13132205092670772295, 15318287322892364044, 9027539547229346224, 17629383881225964174, 17167841317952050345, 2169650970520181403,
+               11366374573920831312, 81590945660392134, 3339836125719372590, 6176339191258224503, 13498384602634172923, 17380518646558253069, 6505222573402454298, 3404196177841425416,
+               18097777493026370528, 398882723487597643, 10462164796529820357, 7704526739683689547, 12438059168025171393, 8163001730991802064, 3319372757738711275, 11518015261707325261,
+               11235814273447729629, 17827792960634604769, 10951458440780869321, 13957342734404907932, 7344502969085321880, 15052563297577817908, 9276707332138855229, 16077312904856138176,
+               10945312442787809330, 8353703025227023259, 2523779015225839136, 5997809042199398051, 5595238423081509301, 1901941038793828090, 983256298544496123, 929860142706986099,
+               1859865867925261002, 7171610585558961405, 1708769301690637951, 1669524125723022855, 1126574755172968332, 2284167219201068318, 14925928881489847288, 4349400324295146347,
+               7809927122217534998, 6003738786706135597, 16541272992243715653, 11352602417510156921, 6070703545889058045, 3742828100079104877, 9416263310824977145, 1406892456840131842,
+               15907861713154660116, 1789008941779432664, 1086909323248385272, 5337878342158043460, 16405416607888113885, 8262005873603178297, 12775015438669465500, 18394022127507526579,
+               9832954710628449545, 14612341389215489179, 8860090710725054989, 501948203387806263, 9969784653624607958, 8524029089859194791, 18028069685553315869, 7863046312587606086,
+               940114737935470576, 15661699274328042324, 2496303902262203344, 17900779334646110602, 10928989106385540880, 11160326060698033088, 6591628982832414200, 12860480197090465356,
+               4005088727670892586, 10215872293486093012, 7634075494800881158, 7707144163086802537, 7085702388211248163, 12168208652772836726, 16347414703478252736, 9386623607672009940,
+               10720163442173876242, 185901255673735804, 189524655270248212, 17937598483325200462, 9672767027914841820, 10911520298114954717, 17238190140596785520, 12302850034563751398,
+               1819872496749425461, 5856173707582412777, 8519855762092470428, 16315722646681962500, 11554620938156340375, 11822224388003836169, 8221825485736638318, 8413608007099273503,
+               16265754830488408124, 13716061973016396515, 6050948709307262401, 7654402024031530787, 149712175032162058, 8319305312043679388, 6115793437696694706, 9669523344165801010,
+               16530167766100505402, 14672843572926881623, 10752276706209340624, 6888427606311779724, 9060900993058482991, 10439396339124215720, 17640982730425880863, 12916411341252677116,
+               13182242421100666863, 5267519287044706312, 1780278156705475292, 12839545421803851420, 9724873776343820617, 11742602593528879231, 7598735248774560112, 4512374343657017031,
+               15080601286098047668, 6570749562833033851, 17494147260115946401, 4878559727303047850, 2259644365338981526, 4232993783633913284, 3035566741498855042, 4306414296080197928,
+               3878740698199360708, 1631626027682263021, 10479957065093850273, 1678395573475248815, 9964111965340163993, 8992208313996775841, 8147773940555378986, 6205594793300838098,
+               11776245660806714247, 18129100488268011560, 15389929343761297429, 14544292652959164154, 18063319363114104433, 13433144948667100183, 462314076175867487, 1862686058702915115,
+       },
+       {
+               17596113920958619489, 11920824479658301378, 3786905428099710821, 11112764289322906111, 8817260450068629272, 6518847791514184438, 14593687325057339783, 18018581321332807475,
+               2056254186648603335, 12143016575009965669, 3290271983033386616, 4338404082685850854, 12660444972475266123, 6345409453044955404, 13278869140778657354, 10063005167581762786,
+               5303950317664091150, 17409642188139937758, 12135894348302287058, 16444741243419918751, 13935885817311324323, 8496908197501732703, 12163317723288843510, 16891353436915314685,
+               4168420842704770545, 338440394515115377, 2102734009665481092, 9772725684473416465, 1247616337419130000, 4222072446972129729, 4836898447189504007, 9154346000276664999,
+               14649401370738987318, 10044081678892811795, 1306517740393103656, 16586067283450489622, 8211832777731897494, 12849393859171286949, 17327526552807783018, 14171704619529498238,
+               12849053390245557890, 12693731077061619694, 5891211584023409476, 1008960642219209210, 15593393872187214387, 7381248773473326001, 16559656086795428559, 2106025108820858934,
+               4347667984894353308, 2129883711661222690, 1076488804494872856, 15059968377755299195, 12380937310378496242, 16425480883270944108, 4769192332535557551, 10388305045430499744,
+               8553482596123775980, 12627020622203381515, 10774788686070344669, 6271789114731522097, 6270586844349642345, 5584690155569770537, 9478526526319537174, 3405597782572827563,
+               10255408065071335198, 2384996481315588922, 10679447117297819075, 3734157461055440416, 1635042286365643780, 11321809677772938996, 2373960964139986040, 4869129159740273704,
+               16681657814739017038, 2045405432090866328, 9473434018957974472, 5549808619751464269, 3650191693776946828, 15805634549736708741, 16764187297356548667, 6849534466635874363,
+               15295973549776084894, 8150873746601283651, 8017271980921908229, 4899654767305073834, 15257501950484641691, 17365331272978440066, 14582514748324426172, 14727798284858071666,
+               3180828552573045472, 17698570278585440462, 8986722854533057232, 4518665117523514004, 1718699978312382231, 16973074530347269964, 5684175730451960274, 17228649521631238473,
+               2897180423141326703, 13691273076814343144, 2967066815351306232, 1032540647518716635, 16365716239989474776, 9503666134295232767, 4599017511227366879, 14475021161770955579,
+               4512626226592149712, 13575110216387069176, 13488662643497927183, 9673147324484250604, 143936220816719815, 2307325398241477161, 468315224038772027, 17743582630124600591,
+               1476494936296433813, 3408612621327299295, 11632756669813257564, 14296719897220703576, 2241234207239321749, 12237974399755684219, 16253635131573079566, 11892871179872526079,
+               8492025373682814159, 9341562763134230960, 10104358220305514878, 17545404790574939459, 15737064134098795026, 3880597485411313924, 388663918823974597, 15032915458906101183,
+               965170717686924337, 17890763357610871180, 17588999527212997589, 13975763809893342952, 5109669798963414493, 7891916061794044612, 4789971769354067287, 13049661741280223048,
+               13047125712251887103, 6463859133854403980, 12163714608926575519, 1018022589444930561, 1736262463418943433, 15665908585957261569, 8814123147308650486, 4798595000205497714,
+               7506024921976923590, 5624217973379693717, 1727881279508834884, 6843292805721229768, 14721392495779901462, 15739256886195814859, 4955780690636679890, 7941019297099640360,
+               1679075860853192334, 11512607379850785303, 8606478479964129549, 11355506676698290554, 8638706560448426692, 11314948425220125007, 192055228531777598, 1407009579456262795,
+               13286048494307428802, 9003344338654830342, 14153483128501604993, 18443414499226619410, 1307798988667786279, 4422280407538765508, 1295189585361403916, 13026087054487841568,
+               2784400402546744378, 15890015749743051151, 2721137876244951114, 5096506081391833837, 7797931926335359630, 11689452583898581132, 14104784079353186010, 3188967683935096888,
+               11330231400343362000, 12540174755074499088, 10360616188128925049, 3458938550662172118, 9983547038346979353, 14986318734459319551, 6345635939240236679, 6320686366534231970,
+               14746231842102190633, 3622710091833101572, 12626649920759262265, 7005023704205322451, 8825692535315999015, 4515463777365688013, 9604411949030284505, 440641657645532650,
+               15551627195111259367, 17849357920181562395, 12870839822102241674, 13056924324197787476, 15109676201265834798, 12974964680406025093, 12841612415554457877, 2986633967268013902,
+               16172780290314506283, 6024364507532794579, 11981052290745212925, 14235100278052078327, 12912505872017936022, 4228821405313065812, 2097279962856941481, 5542690235350104224,
+               6815123236701278368, 6160442936745831892, 8260371745376005388, 715614132817606668, 7741929556783214361, 6266561134278568728, 13996537792746468394, 13116379830815883328,
+               2212637711439965528, 14217650183061928416, 540869510933311267, 6195450915592159668, 14904187357299823445, 5215400274033728644, 6907285779833076435, 15804222685871187391,
+               11124404141552478131, 15318338152189072517, 4067893425297764249, 1697503410612817642, 219476584157335935, 13106826093753036522, 13049745208482785760, 11832231199490391669,
+               10493328169052594634, 10627081887813813659, 11388663495964140754, 1823051796271862577, 12476400584366298768, 13709148086980681224, 4023418280354022922, 7805776130903851852,
+               11989040498741265687, 10985482710426001838, 598034896692782488, 12230542700168560619, 1496676485546951232, 6833695919100964828, 527254545105454187, 6276811762216173921,
+               9452334891928331309, 15207477416486363718, 8081596400773698461, 7528187414539292243, 4773782664413845594, 9435822414884353799, 2722451711480791323, 13642248100035410269,
+       },
+       {
+               16570512961992288509, 15784840936011612960, 17797638261217375128, 10589124475671334830, 16848440972121709899, 697679021479737566, 1456738239410270672, 7214966028857473701,
+               11434157439953722433, 9090860151661100670, 8407869262026581159, 17882547383849407986, 5277257988019769029, 11463853580825342183, 13607489835500075467, 16878800997498950751,
+               16059297404709367406, 8426877510924536482, 15269952608796785555, 6256768900860981984, 13142655793714702073, 14566340391957173918, 17147065283704191109, 879106195264399,
+               1169887957113173798, 4936710663791789838, 8029349457377894665, 3317691225106441967, 3622769674498678594, 1954144360900150482, 1432045977341997899, 934737636789214593,
+               3519438486034584001, 16935008858078961013, 11197550931955434437, 14100007087636813411, 11096181469792598416, 1355325916242161182, 3003143504356161310, 5855778258533244174,
+               3469569649879539425, 2734409579230557820, 11243101718460963222, 14449395552625174865, 2832531264658408884, 12736053595733579053, 8514265014627300817, 4646556172848350801,
+               1035318057221356651, 16671259128991069733, 933190532640544326, 10073090919720429370, 16298191828003546946, 89465711115503243, 1726024123088964037, 6293688775358665990,
+               9646181593082190523, 16068017411165381498, 13319927590045936565, 6113055520205251774, 5576373032696512038, 13880344501714804196, 12022206929479211261, 7387979357081975315,
+               14353322331225872624, 14137906560696321406, 9597841809127146330, 14479164716385450316, 18390885446667453601, 13789601367024187697, 10599569472420906075, 2183893278236533867,
+               17984045804937170919, 3008713646989855019, 11485907798025297413, 14380740919052976941, 3447658178143557676, 9095585806057103587, 698302327819557146, 7922185712178340950,
+               12592522203651044465, 1491459000495558958, 16988036704095888812, 4620491143241098446, 3378886739158384486, 4601357523445825298, 7994566595487207192, 4507705687201434902,
+               13553890993911526641, 1237937561304731611, 11053651340854998814, 8737874920379363783, 15414508226001886918, 9311523317130687807, 12080742822716708234, 4715194040021784977,
+               11413808093931937231, 8917864246709968658, 13554307490245863526, 2827250138133094370, 7637229863299622584, 6947884496333162143, 4815638417787805223, 10291803792760846879,
+               12634048591085853546, 14321728045924893987, 12328747445286182403, 436433860116637979, 5910966881246245784, 11478152401127002379, 15956760875311888867, 9580341487614973173,
+               5405380974793160831, 17240616607222875763, 18407061562244315632, 1777973921117407170, 6264824459040652928, 18267228171835175724, 1278124974392461846, 16099414790431742315,
+               17182132836049601530, 1486820395924546410, 14089047182364760490, 5375431386740917568, 2352352269256972682, 6220398075470064021, 11444733678216077372, 8173002234516562536,
+               2862732059898640615, 16485439906762588046, 8431038226899400253, 8931540904642954995, 792388953489761723, 9296018986570869365, 406447163304028453, 13270392174836298982,
+               7772216409762031099, 334915652033124323, 9705063888720244418, 9829080877134570370, 13800256788887079067, 6121678265481939341, 11747955988727867922, 15561904257519022219,
+               11919247213871390231, 15058232650937578711, 16509435050946309716, 4585646383560577121, 7109079914182671169, 11070600764446172401, 13212464399509938674, 18057628120939602025,
+               7896339057146013415, 17613745684396593735, 4238258305077796259, 15438639564771394288, 1482402451684594916, 3104492350488980260, 5195487229736262641, 1361150797580203482,
+               16473144777827648385, 1226441665397311636, 11587851779002173636, 5723433682141598491, 3818559725806959172, 9177247615754603193, 9531025756553277601, 1716800965379459594,
+               10276432666086031385, 14627452075834666747, 18000674623336885291, 15328386422432799237, 18139556051577750412, 2213209867616444127, 9597214736611625280, 2458176131336755868,
+               17117806110792423322, 15887422186644000204, 18208397717053970445, 7361598408210891485, 13818554723430207838, 12816010025806087198, 17883064936092688211, 1716893191215908273,
+               15949855327936545010, 15892613064802301412, 7776232754624386979, 2193423430757249310, 10751855334513902678, 13772090376350944100, 5644047706587449960, 370992037484721524,
+               10797607675141630710, 16625594903133516890, 4419277245854893028, 2258389314023537326, 16758443963306613299, 15289730903996513589, 17124263661185245991, 15862017582286958991,
+               12272869926038995590, 4569089761627301260, 6495211060884501138, 11124576322292919277, 18314798224925096163, 13232331582712038213, 4402693571738173484, 9384301049965683996,
+               9611026793910805538, 11152002731283498747, 12528844591327054806, 1485961507414531975, 12820893906402770618, 16248407567081091370, 15794078730898691457, 18231302945982292403,
+               16329953561108738383, 14553061366216182492, 5112198484879130320, 1893048255589705004, 11469678860036344015, 8992526488267920066, 18208245559304821518, 8980963391041920447,
+               17694621707784163170, 16317870945177246022, 9173265111786762052, 761657177655159269, 4876597178189658673, 8185879737091523833, 7520213092991049248, 6827963030155074898,
+               4104149897263226969, 1008830393844825523, 1692548451180187046, 10984924503299463085, 3526468436911084942, 18012043951628458646, 15181223987778535698, 18016160796635284569,
+               1524865955503524054, 7479709667052337482, 1064851658558537015, 14404181438374010311, 192685278892740648, 38546070651855709, 17006752915941498851, 7120034574635007914,
+               5783711159088718530, 3503029393593618754, 10736192136662142256, 15443859608128978668, 271805305647187927, 8244170003029416464, 17017071503038388446, 2536084345379259313,
+       },
+       {
+               11535283160083833975, 15102917952496589829, 12909095696891909745, 4611119212602854744, 4195756524232932570, 3754603965149529000, 11539276962358607816, 4401424391553230481,
+               6842993463058627120, 2708745114617181146, 3832382691810282630, 10333834458057320812, 15028197197004077388, 7681293343255119354, 16227537691626587485, 6703363869832495607,
+               17567108285065737529, 8693245930330183070, 4025672038042952121, 3491067119247522844, 2100799837993193702, 9579542950705774054, 5091525285265581997, 1806757015709820088,
+               7757354840118131559, 16227348978414023262, 5800861674805516343, 16486235803248700961, 15646700163023677309, 504258765210816549, 13724147899924699697, 13588899538317277096,
+               15895596198730294923, 12513494396374459899, 13552575153453342654, 11312160635199213507, 12446618129881485796, 11286186116805515445, 1584191291800429567, 10188741008566636830,
+               10157626021970320469, 6580688164585715207, 17158416694471177787, 2873484006255074946, 14852216457444863041, 7463041347566136496, 2190030775722958628, 1116223035803602728,
+               8598875756176012541, 2146658618778432566, 17575736667490551813, 3602654209723135985, 7223347129734689099, 7256921024940026570, 12249118963297692963, 18168532365040819099,
+               7585174044375463988, 2491923406404093282, 9355733262044036112, 11484079611349577325, 13145030009254943291, 1234932884591406048, 479845670619308618, 87735010308690865,
+               17307641427543377277, 5862898330718319545, 485176909118483750, 9845223919324484076, 4293549583740204024, 12765124043303931186, 17870894781132657382, 6508172378961793849,
+               14234156373312856400, 16210939788814051708, 6478880037923038392, 10435512103812909561, 18142844321802359753, 3243996803126554757, 395603619159523019, 10213589535656704607,
+               13256075137060741204, 991285459654295161, 7857174835799942102, 16201105040554625727, 18398612085349994216, 4512860776717176840, 3521452275695011919, 10622137733045360311,
+               14993897771652736376, 3320388672992783302, 18421556740970114213, 7438967127794745135, 15048397725789819354, 12721899159423777001, 1135125102123667189, 6637485660805148630,
+               205606553319362431, 15484041062449893984, 12896720585684759529, 16675624014916513672, 7579112430564108390, 4602460356900251082, 2677787525524280838, 16723483619407414479,
+               17981939084373319995, 3989926231875116241, 15342509934701840045, 12999252495311233519, 15389919024942778009, 6136335679373143315, 4117381415379544275, 13342256463740646775,
+               7622769999043907199, 15227992053145045634, 2719412067263856950, 17811161335980566241, 15036003689029442301, 4919601685231030712, 6756893600905532338, 18029567067112075531,
+               15804957839814547154, 7924193945337173678, 1080401129055171214, 10816444561878528576, 13171610473229361771, 8099842733764406841, 9284741070210451667, 9245195215372025289,
+               7352706423771400643, 11698139248518535945, 12836997796963939813, 5747451345763534394, 7572033904536738295, 17752330422795919668, 16404760947165813434, 13477251724246705199,
+               13700661979310397040, 11172816633936827025, 7087232997755437759, 601317374152115944, 16028751590837491967, 2749566595186093629, 4445248645671399873, 14714182958477634997,
+               9630153311383545953, 6436885924177487891, 2150319761793765423, 3799049242167098053, 13902640603080497957, 13121685068446422901, 10099985117244683905, 10692630753099650856,
+               15680946025356791729, 10935239212262708062, 15255596602338430716, 15502989798538458360, 906862139952472300, 16128362872146694687, 9038121313842477036, 18304772087255114926,
+               16961332967315316395, 2872796507989583018, 18145413156795763341, 6377517922859730669, 3543621377523624979, 10701607653242580646, 17747200374013876449, 15987594633077120628,
+               3487728992359467218, 11271201736509774853, 5968332690756574092, 3519182420015237550, 17144214368301394415, 1805926423542721773, 13696269518209159134, 942126126861202483,
+               16211326119697754410, 9043490763746629445, 13119640043033532883, 9720862297941999125, 12662669665140843415, 2188499520755532048, 2671631563874698813, 621164898587943254,
+               4804461736506692241, 10698651491947798952, 3524135800884470917, 11451653751986650957, 10424912129082359813, 6912080226482239953, 10357808719970986526, 11757540241185558439,
+               1841157911016607198, 17522398974331009019, 17392843956059453556, 10510758656389762948, 7666344868273530034, 10739409534839380580, 18010518965344703872, 14478457810678500914,
+               1617286442811984718, 4008909641875477702, 9328654790542709745, 12015676532404599710, 1763241944305573436, 9348325841675336084, 4072126498552363080, 17245688939115723821,
+               17277555838655940279, 16604852268187595492, 11674181070138727191, 9847423407697994070, 13562477602392929772, 8181792789545038731, 6999326623175714057, 1227784795779857129,
+               14923095901189736698, 90760593075377861, 11732533481504731510, 6000651333412910877, 7847865090059184838, 16859539404919901595, 2709105957383645337, 10263820965340474390,
+               3161036642361826348, 5744405044938832483, 8939741099437920817, 9766097724147073614, 12117283480449144394, 14632688836103128438, 9491651214417380913, 13676064073123352224,
+               4673738700738845848, 2758750364605631228, 16596306154038523740, 4124917668203310922, 2170509910405778957, 4178077301639210933, 5109055439238993109, 9627760120514410208,
+               7259236533647228872, 9608619771663043870, 4148523959415435806, 8831501534166306825, 7919036824652396994, 13625969543100731176, 2546426055029800579, 14852443398434563210,
+               7185947197544988797, 13306809398790059447, 11440959253278285287, 15084384140482244570, 5059824327869316332, 7585354587200615362, 6801884469610571467, 6427162399794357267,
+       },
+       {
+               1453348772281274490, 13028088570940491471, 16100623112750251840, 5210244400259879874, 9443916155735416174, 16869520919318450506, 7479400208826706574, 14374970913352602458,
+               10149597276931117465, 5778043705364022356, 13888443605241209218, 6889225091714429810, 16209363638493043975, 8516350006446457646, 9214830076046105138, 8894115046323798175,
+               13026208197163596446, 1935567165776196957, 17296090833026336866, 8461284827078097590, 14545382879887213077, 3302103559307506085, 16026840048628844803, 4599071908983273604,
+               16375505785562641226, 4903074653735993511, 10355787845763031761, 3188849033041803587, 3145147452182864049, 13878747873108378466, 2798650520315922121, 2325962694441538199,
+               3587824003578414733, 14942115314012282784, 5312737955169054323, 12478174640832111702, 7866537714619856949, 1076672758151595875, 12163513815501875048, 8343003998956997868,
+               1392855790923554429, 928317148609633070, 18064469091536763974, 13446092366984636072, 1975222540660444795, 15443703204026028192, 4016450768356916736, 16656367700821047808,
+               11505659892372808762, 10322665279031813234, 16948868760451861492, 13706671779256832515, 1968671033447691229, 2446599110590827903, 13721045634744350023, 11053432744256776013,
+               11530583608023224967, 15979155166527001287, 592931868138800645, 5361781029549479856, 11246418752830406096, 11882251984248471436, 12026389461944629423, 12289077922798223820,
+               7685868633977346753, 12528120620943035447, 18394735788313062922, 8523101916703102094, 14261596878655792929, 6364753027040158382, 6433482955677830548, 11538026548937002170,
+               16221339092185577802, 2285289075757313223, 1151823739515800834, 1010537560193450047, 10651328720714490261, 426599792903611671, 7181136719074122463, 15350479907287263858,
+               7559201271967630136, 3561344874280275357, 16379496429080959327, 9662226613694502966, 10995850494788192620, 14875349277152338391, 730989400822814422, 14352408679782573731,
+               1328339467113622233, 13374824154992864223, 12057132015324007824, 8507647484414695512, 9286016370798146986, 9083798709648036612, 4312959727577073260, 3732271624824420608,
+               13007262390446754395, 5631627784562092966, 2644488352265945851, 15340614364643014664, 6692152810984634488, 3903120388658969320, 2513009101887784188, 11999681442010831364,
+               8301343575202991577, 7108394080005777057, 3477086484634015274, 8772644795325835021, 14747670046873500269, 11068536909552811695, 12349879357573378133, 8898863927320049679,
+               5231654281125841638, 5181061730027800171, 10657176101406080919, 2548241936122768256, 17140253194139059526, 17961047717804458883, 12407260567549658707, 1464243167234637194,
+               14129872794455315922, 16354810591314135702, 3177417010197743958, 16494351130927698692, 16557765056328447818, 3139394196704738651, 16891813998271303650, 7374470997276173905,
+               18244279644122204437, 10097660526910786400, 9270181538098732492, 362243376823712218, 12369863141977485111, 2550957813014523686, 7768963959853738595, 470330801228165919,
+               14632133560934390222, 13844843545192224059, 12232948338847787315, 18223343336729121487, 5219716370019749202, 2729037467284418866, 4546118556621109595, 12191675540034649671,
+               15868991745937371466, 12686820201922367283, 14799186526268126508, 1241626948050017911, 7080072468753824165, 10793537086099229143, 7855065677501047369, 9747396305344084667,
+               1547814412223404746, 14194709348405912167, 15771028929623393801, 10945048172868684389, 11234483878611528405, 9542605377580701681, 4555391547268120796, 14916872217451960022,
+               398873176015355134, 17609838001051405497, 3752252377312468061, 10441993652683449973, 5218696730429184844, 6514361533063264268, 16024112124035725701, 13453525984055386124,
+               3452753233449684767, 8937677805622461008, 15346651759545553711, 17055791435062851045, 7025089132368408239, 7345356702153522862, 17760529714295220737, 10772604293313163303,
+               9940223451501501487, 13671810088603813912, 1432075826781639138, 8145669182511487125, 852664959675237493, 11640273224943853609, 16220508798123490173, 12787926729706993802,
+               15490131882364039637, 5140304620645573547, 9403655757498826823, 9824850954989176893, 6366139388903157264, 1981838834216345294, 14659870286877979556, 12091578124492612524,
+               9672198938588933438, 1848525214318852627, 6500329435429402369, 8547555101599185897, 4282139019453982058, 13391782461875853462, 956960429753408730, 1865393350316759140,
+               9155847368519787501, 17397005067762861574, 9943535970799289809, 16365250691105460494, 13595148040475375224, 8300668237654861875, 7149654787413440141, 9226755501324961219,
+               9359301870380673800, 9344500253098672841, 282669288080771734, 1996492472861301505, 4777949892950526502, 1374151996531969836, 1529729047243522545, 3371309923165192567,
+               6832171775190531128, 7903951882621813138, 13717573220828409267, 15400575122727850054, 6101307565293576434, 17226772767105983314, 3485283905347036760, 18439321272895583847,
+               5095761409418784463, 15484673138064200869, 7743962634971666154, 9119597914470879266, 17978461537972396088, 11490423388734028778, 6537551181013090408, 11706370534703673937,
+               6635008658379780815, 11428304571924124070, 392068559161657302, 16314310970878215293, 13769492864572584674, 16880907685897496637, 2877983831559338706, 10391660973242662710,
+               16861266984653213659, 1968749328591656132, 13301499995824894911, 14523175695360471336, 15130688872832023531, 1794208537894703529, 10525607764904270704, 14288604199111912452,
+               6289130721434350290, 16129337673129720846, 6648351866142453445, 7705983837166554199, 8120136556582544814, 7924417299222764443, 7821995671300500892, 17697662726179084739,
+       },
+       {
+               14086745261650819748, 17953107869776717888, 1777725846494438428, 2765314406831814212, 2603997194371852991, 2223517025105045134, 15579901335531749634, 6571733615332171148,
+               5478465698516556930, 287443454357750768, 12201204663663129285, 782849770204658255, 11270045035009204251, 18152683972363144337, 10463300037926642739, 14363641589598863851,
+               3790592075869665284, 5120320091554329756, 15361581282394028709, 14360464660911164915, 15249656958991931940, 2563751872827049233, 13745792006936646733, 14572943674933168173,
+               3167679014977537749, 3417445004776702290, 1709246158507866266, 5861367897285174360, 8437429877561342262, 17231607446243478748, 16047596399306766948, 17656438585829685897,
+               12977336347094692192, 13723871955002954132, 17399919575273038847, 16163973860244779675, 14997921584659740746, 6543247361992425067, 4675926398794487109, 17580512382853194054,
+               10778828023580771765, 9812611440536367405, 14168149065325522570, 6692229110872358750, 11010962724400581057, 13055203605065073902, 11396463140731730116, 16969789651736772232,
+               3285258013801327520, 14114268241282882888, 5367399533198476395, 17277410244918727028, 2751895479568588421, 751309667192066167, 13038472116718581917, 16013586354334596135,
+               12364168614988940500, 13194367252463423118, 12223406606527741280, 5014139294736037086, 11244699482831816093, 5336498572491451990, 14268404582568856142, 14502318820969599316,
+               13295673091232554814, 313981772853781347, 11829785736449464030, 13341198421333360997, 16787450350663111566, 6525407229623764159, 2012189087039636323, 2110887590404698758,
+               16984895766311549717, 1057465499230843916, 13565444352859773343, 1019268943988786852, 2190009140530404855, 10045598732295352970, 4789803496780829836, 10700158388954091321,
+               14840255112988420500, 10066628133368048408, 6527354835873855384, 16106607076894419125, 3989024604987083046, 10713316697020150694, 16811389107269552264, 11294596059797019619,
+               622403023838932676, 11423409007234191765, 17086830255702454786, 1213655124481948199, 3976593910085142945, 6315875935390432543, 17947502153968859628, 18031540937011531543,
+               342675887578148289, 18366454547938469828, 3853530442390999217, 7499455395579634652, 768597405171336502, 1636271570683567151, 16786205337983572309, 13056241332863199715,
+               15991153618414855143, 803325462494472241, 5709347424437559249, 10138502962472290727, 4675124205115228106, 9599016746550345197, 2769443894695609085, 12311020551315051087,
+               11470964304318784059, 17313372553735202469, 10686997186364536871, 9228453594798060121, 57933324335302024, 8931389936300346353, 17823596478938529898, 1126996688113949835,
+               10457697409306668434, 7830477435299250296, 7772379952622394912, 6109610138112185532, 4382803614711332911, 286231563340803504, 14408860285425706036, 9445290615796219321,
+               17536503470234411585, 10755841521760916925, 15905055604395954066, 10842889504280336728, 10780689817551616331, 12490302644719656914, 14399349211478895553, 6458867531104408547,
+               18263696007238300109, 14344529985676987842, 12351733186419515951, 14648750128188787544, 3817061805140294292, 13460439592176294955, 2651602395003150964, 17613970291099197676,
+               1107162420032075035, 14270134754120385897, 4090584027509443635, 16066949131129832709, 10961641187652236678, 5480069976143996625, 8549185711954755645, 3125346629140152790,
+               18337941236561689695, 2899707239319273137, 10519944305927777790, 6913088845356962577, 13796383125935684169, 2756403850320695444, 10018647980137529204, 15185795467001072323,
+               678732289042224133, 4682655677430115166, 4806112367076139288, 7101473987708012826, 9907594813802528406, 5572757906434657546, 17819688309930892783, 8734990255058630746,
+               4831187103439262344, 8323117365987697459, 10690753367486223100, 8744079000061869982, 12737295198832254982, 8667406752954112119, 7942221205780634447, 12612313636795726189,
+               16544756691464009983, 3413196415113664237, 18442955254149959801, 10193439941306925215, 15178607176290875326, 10962146035584651400, 11757614026658646304, 16241528460556234026,
+               9593194029396792148, 6376573619820601945, 14694667798662125868, 473733746941891591, 662607401339043361, 12105576520816361855, 16629740468317868384, 12416206001206121129,
+               6655696780366945398, 12313066500177107654, 15308290012322636383, 2159880960357061128, 12374858353753840133, 11331956329091160239, 11794840094276473821, 14170553661155653327,
+               3336445037682266403, 3746885541049520962, 12688476435907418892, 7399089272376853858, 4625608774712059624, 1535040330210000507, 6878676093546636363, 14533846142831376645,
+               6250279356724130049, 3901672557903829499, 4884397030724371499, 17385695093365573379, 1240675257703364805, 9703149291204612490, 10295741452056015824, 7249917314998921510,
+               3336800790505577062, 319907795530586958, 15852045830964927276, 5538471989976998401, 16558766045222360422, 3135574045680866961, 7590873965560972285, 17191236425969884848,
+               542161999237385999, 11197034618748267807, 9595673564043235773, 16351524685431643264, 17127456926935032059, 15448416181819692483, 2035065584045934249, 10976830957530152324,
+               3230012351101746458, 1662948417350421518, 16062645290454019168, 6021730506322388306, 9903225699788133023, 8549278993611431648, 16267339446315716903, 9759051179942016620,
+               14281696762614162345, 14970002486407845832, 14940104843292093805, 7021313216295048550, 18131586729996841512, 13957742754718859034, 14322894803959804982, 12861731196696133597,
+               8838210194055479741, 16190279688839291456, 16520121358582757556, 16768959728701970634, 17279896910204983538, 3582816187015369256, 372137484481226748, 12972230207718993241,
+       },
+       {
+               11480031272463364121, 2525856087688686375, 5875255653057452580, 5606696614467440464, 12094715534218447962, 6173479337351577758, 18244015404482482803, 13199349349511499695,
+               6097225965006328457, 2630336000831717722, 7049638698786526134, 4203465038263485233, 4677974565964393904, 16044036678123636261, 7266049959100300634, 11339674070148504929,
+               1979992348876614621, 7494083465935166973, 16035723662722831744, 6820849908885211777, 16740735239901023053, 2017530162004533409, 3087262288875984227, 9072904925376793991,
+               1830819081327272165, 11951292080860646547, 18002500803418629938, 13317986695217403840, 5005574200470766330, 10138179785738652504, 1610518863105278224, 13309443265578956954,
+               8383241685301818332, 6629521234420338478, 8997316634951392497, 9976633096395028594, 5171570735720385772, 8129153749198218776, 10596302915145665067, 3726383961188926740,
+               14494271933981109919, 9056473564311980628, 10557807473422306929, 1549747977888697589, 4534184223615087698, 12977118933167042558, 11930457930026683843, 8346041661496792064,
+               7756665146227128459, 15140824521273386708, 693427108108819556, 14819189462601222526, 4507393341357475468, 8710020646873218244, 4535796033535410044, 11884504632761707946,
+               14192194428653714479, 11578618567931657764, 6032668189933768881, 15981535562386193924, 8925792218631314923, 9408714146004183681, 8859017894477140398, 1675606340537058506,
+               13447287279335601133, 7792625320709870803, 5347956615552953057, 335662974452886013, 892825083599137885, 1017154417323307505, 11923254597349925339, 13818364932306372202,
+               15945578153358602744, 6304522416189552358, 2545503746231186920, 14563857419242252397, 9711931929315762229, 7949505077082864287, 8780199792032437102, 10109661610848827442,
+               1628958128919487289, 9818701341087940523, 16480240737841185501, 12633108361335093100, 7982147509828265471, 17959437456356197928, 14370416793872407673, 3577532534573396628,
+               3265119697568866078, 13753322853248061974, 15435163376825672274, 13646180516491714938, 15620545622955090250, 18241486585498394565, 459566729126467878, 9728217493753855944,
+               3187267754295885454, 7928049460349917700, 737484733736740002, 16459695106656291329, 13000947522838718027, 11933371771659873912, 4720706464557996274, 7997020276574823784,
+               12655797542121172150, 16574741514838026101, 13532097913031715162, 13578832971779600350, 18171552525916232035, 1516234640889581592, 13625693062693291889, 3869929504544890755,
+               5134589228918179333, 5186584327613952853, 4114726195152833642, 578924708883784650, 9128473117392713984, 17390547319520768186, 15077700332150016764, 8707446714183162237,
+               9883406233903270985, 17184231210468300584, 5498903678702785900, 6903833261382863389, 11489138095102981636, 9021901931786177471, 3227433089132150317, 16639455550797627042,
+               2873811051246262545, 12759149028054319339, 17920917684786397179, 2576455203420292139, 3181713670456310447, 1109589489775958300, 8920119044838278090, 16056330702164227666,
+               14277712977137303378, 3896132440952049994, 13252040000848248790, 7844779060499908154, 8651912177362107995, 5527615699397299219, 17688189207278018869, 14560189235973121390,
+               10861951673021959044, 16820848382034483641, 6761027571816469843, 3555385088072119757, 9363319138244920099, 14172742116400795253, 9535965929584057049, 15628517769546199992,
+               839045372102318861, 2032615141683118500, 1921816835840256924, 504869150737570005, 15932184001422473505, 7849475855313305697, 1189994394722618598, 9874798350548229684,
+               11973862230325381876, 7670835358390713178, 2113918814334481709, 2289514490388170400, 4570586695077036349, 9449360682811675838, 16506880875578470116, 13723444740920888736,
+               14210428465641691143, 15330786835024186142, 14173742373807858721, 15041216914246450688, 6027140311333696225, 17929849776014561356, 3955935517651718925, 12080548003455651805,
+               1974142217308765297, 2347591555456293560, 9029256828390326937, 15561672734848339972, 4719329765359230610, 1924866103348851009, 4950258359754995181, 3245952633715281425,
+               4636201671610663345, 16662311204732135584, 12398897461787695675, 1355753199357412657, 14695655628527768564, 1692838776852698754, 7346906782826540912, 14869028424564984700,
+               7242751356102425321, 7770223857340282376, 14976092066160539655, 389604327668352376, 3472336298605227213, 11456496863560248128, 14597769228654187922, 17838672631901123288,
+               10997764239928568735, 16648935573721932916, 13735964592293716412, 1364388817619955667, 2511134998006929958, 811167458534120344, 9371523327214092569, 9359553283016173792,
+               15311627918891973770, 17170652974122329165, 12620036374776436604, 17439165699070911984, 18124482726761033947, 18390083820175794165, 5492125340791896125, 16506113603670143446,
+               14240080119980315297, 4751983902385717684, 7941412103662252178, 4796803816695225123, 9327986654018000413, 15111345676387005726, 3582558555283734415, 11913156735178831102,
+               2000999613038609412, 1070613390669459171, 595743672188217500, 9169968884291187666, 17960105939867090032, 13927107353795575459, 17872593051171658925, 11087013461789649235,
+               2280207936513065312, 11704149285124951522, 2138093032627822381, 6816805886026674440, 12141709925796155041, 12164596600353477920, 5711177504477877148, 17211856235678509153,
+               6061025098309340877, 4060747063380827182, 15186975689243681841, 18380882388949786706, 927262408801716090, 7447789770541113239, 14074172896745727729, 15372475239996145400,
+               12915868875134296756, 3071143582305760275, 10848717856747030010, 10973183887638314967, 5983269487036236823, 9885184706933333413, 14509493669845681951, 9669608065801379977,
+       },
+       {
+               1190044221726873109, 732025666411072563, 7781096808432277694, 13079879637655900365, 9048680577986693793, 12528346194104542124, 10575369576322629835, 14068913038053465964,
+               3297775431071502652, 7947266993949467566, 6161673381820779563, 10604626734847205996, 17669018066064502925, 2386071939136502354, 1076023928806956187, 16075459682742916440,
+               12387028018538599950, 5791681577936683396, 7536922194386052138, 15377770247350254336, 6564316170002440575, 10629371267149545956, 16125760269901494382, 16051398044897962024,
+               6237354803374899565, 1782400080026955610, 16115027077529639342, 17907259814836219524, 13179234383592426160, 7302978467158243198, 13607720993463749225, 6693531817169120736,
+               9659467198848065929, 13765104107473534739, 820057324758632016, 16604163594878267405, 15321524555426147294, 14524167419333362957, 157291234996957911, 3689488130722730671,
+               13896531645245568605, 13598412639648980920, 3875086557856143664, 9242105512956135595, 17410265178284161091, 14904754836127450463, 2354327747158525902, 3858493849578874654,
+               17288438225198818690, 15275190140700748774, 14532856272428522409, 2192294551011758591, 4275966798014984695, 13252812474545742114, 8604705074440591847, 504054699541924162,
+               3623027910997185067, 15957466839356832933, 3504133700071704955, 4135728439139397021, 1160600455691338871, 4431928072859292239, 1542956305318065546, 14109181184369694855,
+               9135041378474229537, 15626265487594878380, 2645257479784082878, 8105679948445763432, 8579715781576202730, 13437359533149316300, 4344754720520585005, 13326372852934103673,
+               11341622086474305983, 17104958945811183278, 8154944722722765678, 6696975609844549775, 10895966360082878017, 2277686037575837054, 12236842881540344526, 2086470279064067791,
+               2942668817124399651, 11439025398519255779, 17477264434671471242, 9606507094132585461, 1771475584689465869, 10791261379080046759, 12901998265727968789, 16423426725595035468,
+               555419805011031621, 13715683285513290290, 15526654591995532751, 7023761423093873354, 15093366433178982304, 8625749648874372840, 6412297471587129206, 12161114204724955762,
+               9362623422820895267, 6491356159483508885, 8543224082493101588, 17290929683278258587, 17348088672546490894, 3323350644823701753, 398525379151271104, 17794417664139368677,
+               5880914635028486784, 2898124605786107494, 7953506026198179840, 2189477357380899574, 11207122442953694293, 9288539232660208671, 13527697625010979453, 448462453367651162,
+               11262205719433170585, 7539606872920196479, 492385789142086954, 16036594120332851267, 8084547797138041354, 10063336189771527714, 2484395715469739911, 4879298610504146231,
+               194633990068625151, 1028128699653523895, 7436102537486268753, 1855520454959348468, 5098690958966904466, 3342676718901330604, 6942212660412942406, 16510188838209674083,
+               8847926418142642416, 13342814936333556870, 7082971165114489981, 9307541560233171550, 3013250253632606412, 289291445038948658, 2146586262066552853, 17331519863134074479,
+               13747350589043267381, 6342477793304440894, 10087817302474912962, 18076409030930122816, 240893790090129194, 16364025156922886538, 13518167316464590136, 8034023137744309866,
+               14013962864860194917, 5900268096329749317, 578665371390927342, 1407477069341362927, 15142181569643383319, 5217173950329651840, 7999234477517614232, 14722759409199120103,
+               857809728583972424, 12785911478120621636, 11351522624307635957, 6288237507210579634, 15030282678317951238, 5521516375915920991, 1243458350248005764, 3567973108073272461,
+               2834660673354035229, 10728451420162645120, 13396052377701115268, 5730788601228223475, 1616452754395208882, 18236419625072278846, 1179103743668306981, 9179882267624091153,
+               14087439523312437665, 7814060325531094731, 16777382811045908592, 16916500419494378884, 16312259370378381991, 15848836870251345077, 16352246673954213424, 5228629139249919486,
+               16889782864065172884, 4486233301301317202, 12424854171669138635, 12490430652425390015, 17335301435940798099, 9685877269515541824, 8728054940414220990, 12781228698496150916,
+               15949574575791239459, 10394047428873141717, 15915386168603191086, 11400139144838475744, 17198578050070482368, 10505386377385262682, 11269920026804647377, 6796664536515856824,
+               3285292208372623455, 3132524240856145976, 9712372580979649457, 10523781046601368064, 4797168047433466290, 11748687702182632788, 4177442610271848350, 8549047039673741703,
+               6897143822689085584, 12727238507037725105, 12692443686524496083, 1187606781546544862, 11016254758711515442, 15622643445771261724, 16669571628491989170, 7099030384210775042,
+               3541342827520921014, 12596176563952906070, 5209816272233406534, 17158219989390045881, 9096207539532607151, 12291463442559161708, 5188945441827912424, 12721126884401346746,
+               8137171114112655022, 6980210601071561830, 10156197453074241467, 4481350962546197264, 1902625885079226055, 18310954340184922140, 10624840172920793227, 121304340390125189,
+               5261036238619130144, 1418912875050883205, 4741122621962383610, 17995804738511375239, 15493968366750472633, 8417505178158780382, 14685111207483504618, 9729483826733360559,
+               13434828863770210135, 2940287993177646896, 18241509923298296610, 7613631401252601295, 16815829390381900683, 8566309323681786413, 11094402941539790077, 8442864581771174862,
+               17650059733379916650, 4260524072883785227, 8351659371377110706, 710338300032970720, 5512358883882849029, 15533759462039713914, 14352344066268876816, 16708588250954382269,
+               7963995066277321795, 14986230345162551366, 10616366460602472778, 16186943329215681149, 9522855644164647723, 9858336437877021178, 16344942402271072884, 18027353494090590022,
+       },
+       {
+               13175608910844763921, 11168387468381338510, 5555873864224342205, 17780559602571640345, 1582669533588472814, 8145133762789622706, 1625372887980692455, 4576809104068554285,
+               2900978533555060931, 1749946807863203576, 11705734511931072459, 4446980691693419424, 14437524160594907241, 12795912566640000773, 10400036254697939154, 8356113088668925361,
+               8900726473285671992, 890209742292473781, 16059468388719373167, 16577940938542233221, 17381766864962227733, 231915274132518769, 16477817024012878700, 15646021286310268545,
+               17511864284462479051, 4391315454785363822, 16633389246499252566, 4290325975494843430, 15912670649662225191, 14172733821603328367, 12709802627494541709, 9648238681838878635,
+               4196883387800999444, 11261069840079702254, 7135968036494594517, 14537849011631244070, 1930221875891546479, 3029378442249928630, 6219774718328347890, 5922417028077454069,
+               12470404961188516783, 10420863874252801995, 1369334550763670666, 4781925915058005676, 13086538845357988031, 11031029468188842766, 15252022305121561855, 10497770692868889659,
+               8808726441417268278, 8201526072266158452, 1136378216494101481, 15014143365043073153, 9752793532008788265, 18423606089906807282, 12708377698545978413, 13697405528655748691,
+               12840624483048662115, 13614226123606379619, 15087571995173849344, 1395488309690794621, 7173958427217959878, 1198561064176820332, 16821886260165681626, 10019479169661217935,
+               8089335244564816024, 4652396396372834438, 8473523796721514770, 4493469844513366216, 5448577418901909194, 13487502520341193870, 17978888920023381084, 13125222810420128122,
+               11369140159803973135, 8391820975236191093, 4865145203995472561, 14899728882581231165, 11169032718524058736, 14532440521453562763, 7464998467530340358, 14981246381757614771,
+               1242992129726403300, 2014928170416925311, 6341058783517690890, 11690291498253019630, 15951586247597589423, 14033993236702971559, 16963725291567059464, 15075124616754319226,
+               9901328250515532535, 12796305315632203942, 10819069447660403847, 12542238242508661240, 17077777737462854238, 4364294351375777648, 8335244153165894685, 8863541604979427311,
+               12648774127830238318, 5576880401343711606, 11786867566889606858, 7421038047404952574, 1037620897405863409, 16680872357246325645, 10443290127564886223, 9718182896013830581,
+               15199007294286606824, 10225517367964809030, 12827778649823141649, 16046039393887815140, 284741135347255597, 4015036609703147909, 3902771329647468314, 5128707935422024078,
+               16953148044626345363, 5101833106541998042, 7655361325113312133, 15948906743291877728, 11619404274756349415, 7521254459857915559, 14978040810149334918, 18392994517091959591,
+               11029520456752683158, 2297291237551781454, 7934683676555855479, 1563954733146546128, 2252805128528536255, 10523375695822939112, 4598652721256818062, 17493379105069761435,
+               1717382065475436420, 12444276194160330384, 3605273785657402256, 17503422605669121015, 12066457002913396306, 18109827202111882684, 11555238022219952400, 1993655497207863497,
+               14852223665677610379, 4743851404709775958, 8525514757892437524, 10402777181498591725, 17096034999928466604, 4289543339828736175, 4306145672261807290, 15366124999227707930,
+               9159996652502914864, 10301349423202296392, 13530090903323000632, 4082840779249202050, 8824726775176314063, 16033767772359951785, 9181204573557660412, 7582747879080399183,
+               2747551692916263132, 3151123035150683281, 13938314333309683791, 11970864255483579560, 7894236725861110998, 10515613623232567716, 10445557830757066839, 11155097727742050955,
+               511773909731247800, 2463012923954369656, 15859141716591041471, 4940781664379556792, 12435624343534748284, 10278084527750129328, 13178135781125832492, 5930328346313533490,
+               9122100956633732655, 4007876149211873275, 8339438668849688737, 7791075492023424820, 1771434463088769532, 17441254147665904787, 9470298561063283873, 16552350513326886351,
+               2842235074681099572, 6045955093828210410, 12534027406207583719, 9023829328537353058, 1661393615224515538, 3265308219651631507, 14825441620546235307, 6190486519065164472,
+               9569762631377921701, 10341967309273270300, 4697570564829842013, 16684762125903667303, 5281929071085172097, 13027961546412671127, 18398764602992176314, 3872796039504642974,
+               3625046733403850478, 18072436321985678348, 12926724831909767455, 17260889391923475120, 2205546675974800411, 4823605748727161314, 11756378320036258430, 12725625915588142865,
+               3620769638269480452, 531680461898170, 10213227252513668871, 15446816035938502695, 15189868868814686765, 8689079054027125562, 10767300823767661010, 12185259819280811201,
+               2954211398425891878, 887045055614004603, 17024961552904496644, 11183183814128062689, 2275500228939836642, 8454621353771976628, 13706050871317440521, 13152782683288296426,
+               5035609627965208105, 6338722048255995169, 11594969687968475335, 5639340633771742838, 6928934109570365590, 11589609913085167707, 18353534295019770247, 6879412911232288750,
+               13223374340976842384, 5803903047180226505, 10382392856292138950, 6807712794865416975, 7273350714698980002, 16071615116869102753, 11130104866208195846, 17099222713467268806,
+               4288395624114587260, 10186593737807119648, 5970871638851383523, 17274628153010076591, 11083355019391773968, 15571651381840416650, 7269503864920933911, 34314525388851272,
+               13518907013113787435, 13799188114963266222, 10949327997049617616, 12851874981220611149, 14245323937486085594, 18324803746062213911, 13224741762315864830, 15910543010675195930,
+               10042008593756684008, 6713471518385846030, 10961845838926538977, 855334359173719954, 7598642325962297361, 18006511265377032901, 6844179774752820363, 248341098560552116,
+       },
+       {
+               9259451175701532574, 15597985540941612547, 4541553034987877619, 8927802479718285609, 14672230714928802576, 14284617950605306700, 13339970812390782046, 787078889494395850,
+               18165439414433063919, 14693282888419586094, 14992616289789993230, 13232208150801553912, 16850347485914337693, 223364064845089224, 7302899015436300563, 4391216311540396088,
+               12558388403188680537, 10687978569513354810, 9373570856564649772, 4079327722512691465, 5372437374337150740, 3297421622932790851, 9326853593823854687, 8305371884938201251,
+               13121472331750731303, 323745485980480220, 15110308702528119977, 4696302365805118372, 9859094500834571602, 5315656270700787939, 4187063204400651801, 1695695129564818327,
+               12817586844019849804, 15425488216915741929, 15293562913126043054, 11770898970765978555, 6806103820345670787, 17789094149138630459, 3807781571713999192, 5823254011289457198,
+               10112524230916015604, 13571143908656270599, 6031089010487808103, 5774558171390644848, 1808959243244841573, 14071312530426692155, 9241399242704553402, 9836150050655369231,
+               14083007972403535491, 16009534514129505275, 12481249112231139039, 10309390659262581143, 5782517315325366794, 16717384553294759530, 4578392002424884134, 239005024949492645,
+               1836857790164349346, 11263074778654917115, 4786985732596838094, 10525445084936097674, 1484357665966453236, 3110871407036679558, 1668700683093601768, 2736269131339849752,
+               9249362594190920246, 8088172462140746331, 4080107866285682736, 16205599538438551353, 18312943145606312277, 9100632964181080418, 3969991115337154345, 5340098959750368315,
+               12122448407048035645, 2891250339380982359, 12794212052932523400, 7166035112141500392, 15777441312724841162, 4552528682229856831, 2210391301762911476, 16410254680957321386,
+               6910044784455706429, 11951245774670922855, 207795885948948810, 3884359690300962405, 4578772752480772344, 2948797025787714138, 16774444535658202808, 1388183483009000463,
+               16561979129019905420, 1881862411760441386, 15441950514711322010, 12933020223458438856, 5570341451312029630, 18172638959728259059, 9074261777549091198, 6171200053222754816,
+               10126435102176037237, 1545112930055760251, 11563139991870561593, 10766754172364938834, 5116781688621052838, 14471715119500781375, 4724882615229687192, 10031687030722046325,
+               15016829467434780812, 6777508689306592732, 3811682306063049290, 11475361222871876387, 6080948654298953274, 11612742274762615033, 5268311600240325047, 9147351973710519861,
+               12130203770930472759, 3880998309361490881, 8807462332494735511, 9291388074337055133, 18165312304248982432, 12733144434841535979, 18090195697688236271, 5825342884125782172,
+               13034385644450400616, 16498936039876211302, 13019014556329727588, 17911110193068084415, 2034190024798401134, 1526884555531436223, 8108814142164064795, 4075908755148182733,
+               6404489603451030675, 16601749455344583377, 12907740667428956072, 8446383351289364752, 698035388979141580, 3593914367189873571, 6744392605914028800, 18168078953147292456,
+               14484703498492722699, 6030798911934842161, 15931002029256202288, 13491601992324491240, 8585568434702372483, 9113555433818303018, 6375455514164501736, 1476639189214882947,
+               5209683814158663472, 16895526973128357178, 10457488910391635027, 17530003042232440701, 4030542539553991812, 9445656287872984963, 4212489101708176016, 837886727556721620,
+               2983790309644332360, 11276772732994425347, 1310621139116895737, 3131558545024164284, 3529698629777893989, 13271773334458143370, 8171825923423406479, 305718858162497191,
+               12347543988562572522, 4315642616923374215, 17586477762860427847, 1037334149869395772, 18311071546005132724, 1489505092175764848, 8926409949339059078, 10260307609945070716,
+               1253128470325829265, 917180526219408600, 10471425074479693158, 12658678264459355332, 8502334428811982364, 3789675096428271759, 4531393894096863308, 12176495757901795513,
+               15081766794595471636, 3944913291385975654, 14507832069904091484, 3624606168811123851, 11476968507677098110, 1056328247986567681, 15246608002200052960, 6566558379177875405,
+               652315099041528631, 4287214618428297946, 11730560225433863449, 7935915607867430686, 15979159466809939008, 9209839549459543141, 9501045239358734673, 15490773728258884277,
+               14281001444503113096, 9253803478538227873, 3842669056581745692, 18399990656305827164, 11841387504710944221, 16052361836589007383, 831115622826254867, 8219898649601530197,
+               2339128600785774471, 1426373723429876004, 3299581455481810683, 16966544600853047157, 8419320331267538738, 8376963013864643226, 1996128805959565963, 2376766970819731241,
+               10963611841695254911, 2914831079289063424, 15884256460390936367, 8724520571578171796, 329402220949313078, 8905943304651682982, 1280899166177109409, 6980213851983339340,
+               5524321102331478758, 2149164875175284006, 10897639484514200325, 14605181792035620644, 316829907946955098, 13776780818927038502, 18167912441745301047, 16845612593885106452,
+               15817940025107036888, 14405005201957074368, 11647077937228007305, 13795438792777593442, 9813339145840642083, 13196196205982926907, 5981408724994946624, 12303812818084690125,
+               11821409230485627325, 1934768678832528678, 15798397330147151183, 2089418311766868031, 16206123311846842647, 10276976147555604745, 14858750786699873336, 2500482310681473276,
+               9502861285700748804, 12163827978530279544, 9383068907817479934, 5717811606328725851, 12416198015020836733, 15689586164720677894, 14337921697724349521, 9392403465642971279,
+               6696074876763293236, 10302972695440286968, 16647054763285662245, 7841147641486000427, 10612636854719975349, 3592516733641215266, 14172459823963607855, 1290213042793222575,
+       },
+}
diff --git a/libgo/go/crypto/elliptic/p256_asm_table_test.go b/libgo/go/crypto/elliptic/p256_asm_table_test.go
new file mode 100644 (file)
index 0000000..f91108b
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build ignore
+// +build ignore
+
+package elliptic
+
+import (
+       "reflect"
+       "testing"
+)
+
+func TestP256PrecomputedTable(t *testing.T) {
+
+       basePoint := []uint64{
+               0x79e730d418a9143c, 0x75ba95fc5fedb601, 0x79fb732b77622510, 0x18905f76a53755c6,
+               0xddf25357ce95560a, 0x8b4ab8e4ba19e45c, 0xd2e88688dd21f325, 0x8571ff1825885d85,
+               0x0000000000000001, 0xffffffff00000000, 0xffffffffffffffff, 0x00000000fffffffe,
+       }
+       t1 := make([]uint64, 12)
+       t2 := make([]uint64, 12)
+       copy(t2, basePoint)
+
+       zInv := make([]uint64, 4)
+       zInvSq := make([]uint64, 4)
+       for j := 0; j < 32; j++ {
+               copy(t1, t2)
+               for i := 0; i < 43; i++ {
+                       // The window size is 6 so we need to double 6 times.
+                       if i != 0 {
+                               for k := 0; k < 6; k++ {
+                                       p256PointDoubleAsm(t1, t1)
+                               }
+                       }
+                       // Convert the point to affine form. (Its values are
+                       // still in Montgomery form however.)
+                       p256Inverse(zInv, t1[8:12])
+                       p256Sqr(zInvSq, zInv, 1)
+                       p256Mul(zInv, zInv, zInvSq)
+
+                       p256Mul(t1[:4], t1[:4], zInvSq)
+                       p256Mul(t1[4:8], t1[4:8], zInv)
+
+                       copy(t1[8:12], basePoint[8:12])
+
+                       if got, want := p256Precomputed[i][j*8:(j*8)+8], t1[:8]; !reflect.DeepEqual(got, want) {
+                               t.Fatalf("Unexpected table entry at [%d][%d:%d]: got %v, want %v", i, j*8, (j*8)+8, got, want)
+                       }
+               }
+               if j == 0 {
+                       p256PointDoubleAsm(t2, basePoint)
+               } else {
+                       p256PointAddAsm(t2, t2, basePoint)
+               }
+       }
+
+}
index 8e1a4125ade130cdd28f827884221f26a8c92e07..48793f0a87df0992560db0383918eb7d6c2d145e 100644 (file)
@@ -2,13 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//-go:build !amd64 && !s390x && !arm64 && !ppc64le
 // -build !amd64,!s390x,!arm64,!ppc64le
 
 package elliptic
 
-var (
-       p256 p256Curve
-)
+var p256 p256Curve
 
 func initP256Arch() {
        // Use pure Go implementation.
index 6f721b8fc76c16d2e4cbec41e80660dc47b73ff1..2af9d75ee14b5d6977c206ac87cefda14c878395 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
-// +build ppc64le
 
 package elliptic
 
index fb38e0a272d5d016c6103d0bb03ea7c5544ccc57..3b9a7671f8cffc36d11da793f9054e9104cacc31 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
-// -build s390x
 
 package elliptic
 
diff --git a/libgo/go/crypto/elliptic/p256_test.go b/libgo/go/crypto/elliptic/p256_test.go
new file mode 100644 (file)
index 0000000..1435f5e
--- /dev/null
@@ -0,0 +1,155 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package elliptic
+
+import (
+       "math/big"
+       "testing"
+)
+
+type scalarMultTest struct {
+       k          string
+       xIn, yIn   string
+       xOut, yOut string
+}
+
+var p256MultTests = []scalarMultTest{
+       {
+               "2a265f8bcbdcaf94d58519141e578124cb40d64a501fba9c11847b28965bc737",
+               "023819813ac969847059028ea88a1f30dfbcde03fc791d3a252c6b41211882ea",
+               "f93e4ae433cc12cf2a43fc0ef26400c0e125508224cdb649380f25479148a4ad",
+               "4d4de80f1534850d261075997e3049321a0864082d24a917863366c0724f5ae3",
+               "a22d2b7f7818a3563e0f7a76c9bf0921ac55e06e2e4d11795b233824b1db8cc0",
+       },
+       {
+               "313f72ff9fe811bf573176231b286a3bdb6f1b14e05c40146590727a71c3bccd",
+               "cc11887b2d66cbae8f4d306627192522932146b42f01d3c6f92bd5c8ba739b06",
+               "a2f08a029cd06b46183085bae9248b0ed15b70280c7ef13a457f5af382426031",
+               "831c3f6b5f762d2f461901577af41354ac5f228c2591f84f8a6e51e2e3f17991",
+               "93f90934cd0ef2c698cc471c60a93524e87ab31ca2412252337f364513e43684",
+       },
+}
+
+func TestP256BaseMult(t *testing.T) {
+       p256 := P256()
+       p256Generic := p256.Params()
+
+       scalars := make([]*big.Int, 0, len(p224BaseMultTests)+1)
+       for _, e := range p224BaseMultTests {
+               k, _ := new(big.Int).SetString(e.k, 10)
+               scalars = append(scalars, k)
+       }
+       k := new(big.Int).SetInt64(1)
+       k.Lsh(k, 500)
+       scalars = append(scalars, k)
+
+       for i, k := range scalars {
+               x, y := p256.ScalarBaseMult(k.Bytes())
+               x2, y2 := p256Generic.ScalarBaseMult(k.Bytes())
+               if x.Cmp(x2) != 0 || y.Cmp(y2) != 0 {
+                       t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, x, y, x2, y2)
+               }
+
+               if testing.Short() && i > 5 {
+                       break
+               }
+       }
+}
+
+func TestP256Mult(t *testing.T) {
+       p256 := P256()
+       p256Generic := p256.Params()
+
+       for i, e := range p224BaseMultTests {
+               x, _ := new(big.Int).SetString(e.x, 16)
+               y, _ := new(big.Int).SetString(e.y, 16)
+               k, _ := new(big.Int).SetString(e.k, 10)
+
+               xx, yy := p256.ScalarMult(x, y, k.Bytes())
+               xx2, yy2 := p256Generic.ScalarMult(x, y, k.Bytes())
+               if xx.Cmp(xx2) != 0 || yy.Cmp(yy2) != 0 {
+                       t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, xx, yy, xx2, yy2)
+               }
+               if testing.Short() && i > 5 {
+                       break
+               }
+       }
+
+       for i, e := range p256MultTests {
+               x, _ := new(big.Int).SetString(e.xIn, 16)
+               y, _ := new(big.Int).SetString(e.yIn, 16)
+               k, _ := new(big.Int).SetString(e.k, 16)
+               expectedX, _ := new(big.Int).SetString(e.xOut, 16)
+               expectedY, _ := new(big.Int).SetString(e.yOut, 16)
+
+               xx, yy := p256.ScalarMult(x, y, k.Bytes())
+               if xx.Cmp(expectedX) != 0 || yy.Cmp(expectedY) != 0 {
+                       t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, xx, yy, expectedX, expectedY)
+               }
+       }
+}
+
+type synthCombinedMult struct {
+       Curve
+}
+
+func (s synthCombinedMult) CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int) {
+       x1, y1 := s.ScalarBaseMult(baseScalar)
+       x2, y2 := s.ScalarMult(bigX, bigY, scalar)
+       return s.Add(x1, y1, x2, y2)
+}
+
+func TestP256CombinedMult(t *testing.T) {
+       type combinedMult interface {
+               Curve
+               CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int)
+       }
+
+       p256, ok := P256().(combinedMult)
+       if !ok {
+               p256 = &synthCombinedMult{P256()}
+       }
+
+       gx := p256.Params().Gx
+       gy := p256.Params().Gy
+
+       zero := make([]byte, 32)
+       one := make([]byte, 32)
+       one[31] = 1
+       two := make([]byte, 32)
+       two[31] = 2
+
+       // 0×G + 0×G = ∞
+       x, y := p256.CombinedMult(gx, gy, zero, zero)
+       if x.Sign() != 0 || y.Sign() != 0 {
+               t.Errorf("0×G + 0×G = (%d, %d), should be ∞", x, y)
+       }
+
+       // 1×G + 0×G = G
+       x, y = p256.CombinedMult(gx, gy, one, zero)
+       if x.Cmp(gx) != 0 || y.Cmp(gy) != 0 {
+               t.Errorf("1×G + 0×G = (%d, %d), should be (%d, %d)", x, y, gx, gy)
+       }
+
+       // 0×G + 1×G = G
+       x, y = p256.CombinedMult(gx, gy, zero, one)
+       if x.Cmp(gx) != 0 || y.Cmp(gy) != 0 {
+               t.Errorf("0×G + 1×G = (%d, %d), should be (%d, %d)", x, y, gx, gy)
+       }
+
+       // 1×G + 1×G = 2×G
+       x, y = p256.CombinedMult(gx, gy, one, one)
+       ggx, ggy := p256.ScalarBaseMult(two)
+       if x.Cmp(ggx) != 0 || y.Cmp(ggy) != 0 {
+               t.Errorf("1×G + 1×G = (%d, %d), should be (%d, %d)", x, y, ggx, ggy)
+       }
+
+       minusOne := new(big.Int).Sub(p256.Params().N, big.NewInt(1))
+       // 1×G + (-1)×G = ∞
+       x, y = p256.CombinedMult(gx, gy, one, minusOne.Bytes())
+       if x.Sign() != 0 || y.Sign() != 0 {
+               t.Errorf("1×G + (-1)×G = (%d, %d), should be ∞", x, y)
+       }
+}
diff --git a/libgo/go/crypto/elliptic/p521.go b/libgo/go/crypto/elliptic/p521.go
new file mode 100644 (file)
index 0000000..3d35594
--- /dev/null
@@ -0,0 +1,259 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package elliptic
+
+import (
+       "crypto/elliptic/internal/fiat"
+       "math/big"
+)
+
+type p521Curve struct {
+       *CurveParams
+}
+
+var p521 p521Curve
+var p521Params *CurveParams
+
+func initP521() {
+       // See FIPS 186-3, section D.2.5
+       p521.CurveParams = &CurveParams{Name: "P-521"}
+       p521.P, _ = new(big.Int).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", 10)
+       p521.N, _ = new(big.Int).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449", 10)
+       p521.B, _ = new(big.Int).SetString("051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", 16)
+       p521.Gx, _ = new(big.Int).SetString("c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", 16)
+       p521.Gy, _ = new(big.Int).SetString("11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", 16)
+       p521.BitSize = 521
+}
+
+func (curve p521Curve) Params() *CurveParams {
+       return curve.CurveParams
+}
+
+func (curve p521Curve) IsOnCurve(x, y *big.Int) bool {
+       x1 := bigIntToFiatP521(x)
+       y1 := bigIntToFiatP521(y)
+       b := bigIntToFiatP521(curve.B) // TODO: precompute this value.
+
+       // x³ - 3x + b.
+       x3 := new(fiat.P521Element).Square(x1)
+       x3.Mul(x3, x1)
+
+       threeX := new(fiat.P521Element).Add(x1, x1)
+       threeX.Add(threeX, x1)
+
+       x3.Sub(x3, threeX)
+       x3.Add(x3, b)
+
+       // y² = x³ - 3x + b
+       y2 := new(fiat.P521Element).Square(y1)
+
+       return x3.Equal(y2) == 1
+}
+
+type p521Point struct {
+       x, y, z *fiat.P521Element
+}
+
+func fiatP521ToBigInt(x *fiat.P521Element) *big.Int {
+       xBytes := x.Bytes()
+       for i := range xBytes[:len(xBytes)/2] {
+               xBytes[i], xBytes[len(xBytes)-i-1] = xBytes[len(xBytes)-i-1], xBytes[i]
+       }
+       return new(big.Int).SetBytes(xBytes)
+}
+
+// affineFromJacobian brings a point in Jacobian coordinates back to affine
+// coordinates, with (0, 0) representing infinity by convention. It also goes
+// back to big.Int values to match the exposed API.
+func (curve p521Curve) affineFromJacobian(p *p521Point) (x, y *big.Int) {
+       if p.z.IsZero() == 1 {
+               return new(big.Int), new(big.Int)
+       }
+
+       zinv := new(fiat.P521Element).Invert(p.z)
+       zinvsq := new(fiat.P521Element).Mul(zinv, zinv)
+
+       xx := new(fiat.P521Element).Mul(p.x, zinvsq)
+       zinvsq.Mul(zinvsq, zinv)
+       yy := new(fiat.P521Element).Mul(p.y, zinvsq)
+
+       return fiatP521ToBigInt(xx), fiatP521ToBigInt(yy)
+}
+
+func bigIntToFiatP521(x *big.Int) *fiat.P521Element {
+       xBytes := new(big.Int).Mod(x, p521.P).FillBytes(make([]byte, 66))
+       for i := range xBytes[:len(xBytes)/2] {
+               xBytes[i], xBytes[len(xBytes)-i-1] = xBytes[len(xBytes)-i-1], xBytes[i]
+       }
+       x1, err := new(fiat.P521Element).SetBytes(xBytes)
+       if err != nil {
+               // The input is reduced modulo P and encoded in a fixed size bytes
+               // slice, this should be impossible.
+               panic("internal error: bigIntToFiatP521")
+       }
+       return x1
+}
+
+// jacobianFromAffine converts (x, y) affine coordinates into (x, y, z) Jacobian
+// coordinates. It also converts from big.Int to fiat, which is necessarily a
+// messy and variable-time operation, which we can't avoid due to the exposed API.
+func (curve p521Curve) jacobianFromAffine(x, y *big.Int) *p521Point {
+       // (0, 0) is by convention the point at infinity, which can't be represented
+       // in affine coordinates, but is (0, 0, 0) in Jacobian.
+       if x.Sign() == 0 && y.Sign() == 0 {
+               return &p521Point{
+                       x: new(fiat.P521Element),
+                       y: new(fiat.P521Element),
+                       z: new(fiat.P521Element),
+               }
+       }
+       return &p521Point{
+               x: bigIntToFiatP521(x),
+               y: bigIntToFiatP521(y),
+               z: new(fiat.P521Element).One(),
+       }
+}
+
+func (curve p521Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
+       p1 := curve.jacobianFromAffine(x1, y1)
+       p2 := curve.jacobianFromAffine(x2, y2)
+       return curve.affineFromJacobian(p1.addJacobian(p1, p2))
+}
+
+// addJacobian sets q = p1 + p2, and returns q. The points may overlap.
+func (q *p521Point) addJacobian(p1, p2 *p521Point) *p521Point {
+       // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
+       z1IsZero := p1.z.IsZero()
+       z2IsZero := p2.z.IsZero()
+
+       z1z1 := new(fiat.P521Element).Square(p1.z)
+       z2z2 := new(fiat.P521Element).Square(p2.z)
+
+       u1 := new(fiat.P521Element).Mul(p1.x, z2z2)
+       u2 := new(fiat.P521Element).Mul(p2.x, z1z1)
+       h := new(fiat.P521Element).Sub(u2, u1)
+       xEqual := h.IsZero() == 1
+       i := new(fiat.P521Element).Add(h, h)
+       i.Square(i)
+       j := new(fiat.P521Element).Mul(h, i)
+
+       s1 := new(fiat.P521Element).Mul(p1.y, p2.z)
+       s1.Mul(s1, z2z2)
+       s2 := new(fiat.P521Element).Mul(p2.y, p1.z)
+       s2.Mul(s2, z1z1)
+       r := new(fiat.P521Element).Sub(s2, s1)
+       yEqual := r.IsZero() == 1
+       if xEqual && yEqual && z1IsZero == 0 && z2IsZero == 0 {
+               return q.doubleJacobian(p1)
+       }
+       r.Add(r, r)
+       v := new(fiat.P521Element).Mul(u1, i)
+
+       x := new(fiat.P521Element).Set(r)
+       x.Square(x)
+       x.Sub(x, j)
+       x.Sub(x, v)
+       x.Sub(x, v)
+
+       y := new(fiat.P521Element).Set(r)
+       v.Sub(v, x)
+       y.Mul(y, v)
+       s1.Mul(s1, j)
+       s1.Add(s1, s1)
+       y.Sub(y, s1)
+
+       z := new(fiat.P521Element).Add(p1.z, p2.z)
+       z.Square(z)
+       z.Sub(z, z1z1)
+       z.Sub(z, z2z2)
+       z.Mul(z, h)
+
+       x.Select(p2.x, x, z1IsZero)
+       x.Select(p1.x, x, z2IsZero)
+       y.Select(p2.y, y, z1IsZero)
+       y.Select(p1.y, y, z2IsZero)
+       z.Select(p2.z, z, z1IsZero)
+       z.Select(p1.z, z, z2IsZero)
+
+       q.x.Set(x)
+       q.y.Set(y)
+       q.z.Set(z)
+       return q
+}
+
+func (curve p521Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
+       p := curve.jacobianFromAffine(x1, y1)
+       return curve.affineFromJacobian(p.doubleJacobian(p))
+}
+
+// doubleJacobian sets q = p + p, and returns q. The points may overlap.
+func (q *p521Point) doubleJacobian(p *p521Point) *p521Point {
+       // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
+       delta := new(fiat.P521Element).Square(p.z)
+       gamma := new(fiat.P521Element).Square(p.y)
+       alpha := new(fiat.P521Element).Sub(p.x, delta)
+       alpha2 := new(fiat.P521Element).Add(p.x, delta)
+       alpha.Mul(alpha, alpha2)
+       alpha2.Set(alpha)
+       alpha.Add(alpha, alpha)
+       alpha.Add(alpha, alpha2)
+
+       beta := alpha2.Mul(p.x, gamma)
+
+       q.x.Square(alpha)
+       beta8 := new(fiat.P521Element).Add(beta, beta)
+       beta8.Add(beta8, beta8)
+       beta8.Add(beta8, beta8)
+       q.x.Sub(q.x, beta8)
+
+       q.z.Add(p.y, p.z)
+       q.z.Square(q.z)
+       q.z.Sub(q.z, gamma)
+       q.z.Sub(q.z, delta)
+
+       beta.Add(beta, beta)
+       beta.Add(beta, beta)
+       beta.Sub(beta, q.x)
+       q.y.Mul(alpha, beta)
+
+       gamma.Square(gamma)
+       gamma.Add(gamma, gamma)
+       gamma.Add(gamma, gamma)
+       gamma.Add(gamma, gamma)
+
+       q.y.Sub(q.y, gamma)
+
+       return q
+}
+
+func (curve p521Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
+       B := curve.jacobianFromAffine(Bx, By)
+       p, t := &p521Point{
+               x: new(fiat.P521Element),
+               y: new(fiat.P521Element),
+               z: new(fiat.P521Element),
+       }, &p521Point{
+               x: new(fiat.P521Element),
+               y: new(fiat.P521Element),
+               z: new(fiat.P521Element),
+       }
+
+       for _, byte := range scalar {
+               for bitNum := 0; bitNum < 8; bitNum++ {
+                       p.doubleJacobian(p)
+                       bit := (byte >> (7 - bitNum)) & 1
+                       t.addJacobian(p, B)
+                       p.x.Select(t.x, p.x, int(bit))
+                       p.y.Select(t.y, p.y, int(bit))
+                       p.z.Select(t.z, p.z, int(bit))
+               }
+       }
+
+       return curve.affineFromJacobian(p)
+}
+
+func (curve p521Curve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
+       return curve.ScalarMult(curve.Gx, curve.Gy, k)
+}
index 812ce3c65522bddcbdfe4809c28b8c06fc9e6984..86e0f3cfe70b70d70d300c405536af4b79ee357d 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !appengine
 // +build !appengine
 
 // Package subtle implements functions that are often useful in cryptographic
index 844f901d18e6311d7ae0437be7034bef0428b9eb..35b442f7a2321e77fea5e0bfaf7bf8b22f804b91 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build appengine
 // +build appengine
 
 // Package subtle implements functions that are often useful in cryptographic
index 1468924cbc0e5ecdbb51f198271c89bdf178c444..29729fad015e3de3ae0dec6e2010c1f7d02c17aa 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 // This program generates md5block.go
index 282ba1b8592f5f35af858768b5e3be595c969f56..acd456af2151782686a90f6acb20b4a736cde8a3 100644 (file)
@@ -157,7 +157,7 @@ func TestBlockGeneric(t *testing.T) {
 // Tests for unmarshaling hashes that have hashed a large amount of data
 // The initial hash generation is omitted from the test, because it takes a long time.
 // The test contains some already-generated states, and their expected sums
-// Tests a problem that is outlined in Github issue #29541
+// Tests a problem that is outlined in GitHub issue #29541
 // The problem is triggered when an amount of data has been hashed for which
 // the data length has a 1 in the 32nd bit. When casted to int, this changes
 // the sign of the value, and causes the modulus operation to return a
@@ -212,7 +212,7 @@ func TestLargeHashes(t *testing.T) {
 }
 
 var bench = New()
-var buf = make([]byte, 8192+1)
+var buf = make([]byte, 1024*1024*8+1)
 var sum = make([]byte, bench.Size())
 
 func benchmarkSize(b *testing.B, size int, unaligned bool) {
@@ -235,6 +235,22 @@ func BenchmarkHash8Bytes(b *testing.B) {
        benchmarkSize(b, 8, false)
 }
 
+func BenchmarkHash64(b *testing.B) {
+       benchmarkSize(b, 64, false)
+}
+
+func BenchmarkHash128(b *testing.B) {
+       benchmarkSize(b, 128, false)
+}
+
+func BenchmarkHash256(b *testing.B) {
+       benchmarkSize(b, 256, false)
+}
+
+func BenchmarkHash512(b *testing.B) {
+       benchmarkSize(b, 512, false)
+}
+
 func BenchmarkHash1K(b *testing.B) {
        benchmarkSize(b, 1024, false)
 }
@@ -243,6 +259,14 @@ func BenchmarkHash8K(b *testing.B) {
        benchmarkSize(b, 8192, false)
 }
 
+func BenchmarkHash1M(b *testing.B) {
+       benchmarkSize(b, 1024*1024, false)
+}
+
+func BenchmarkHash8M(b *testing.B) {
+       benchmarkSize(b, 8*1024*1024, false)
+}
+
 func BenchmarkHash8BytesUnaligned(b *testing.B) {
        benchmarkSize(b, 8, true)
 }
index ccdae4045365539f69d0476e3bee41bf259b50e6..5f31731f68a5abd834466d68b651a2f70086d12c 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
-// +build amd64 386 arm ppc64le ppc64 s390x arm64
 
 package md5
 
index 56520f1f0020e113837fb5156dccb43cc0dc5389..3d44df284bf4d7addef4e74c0adec93469d6d5cc 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//-go:build !amd64 && !386 && !arm && !ppc64le && !ppc64 && !s390x && !arm64
 // -build !amd64,!386,!arm,!ppc64le,!ppc64,!s390x,!arm64
 
 package md5
index 360b215d9a9ee693d11c705569842a4728187e21..22be7f0ef94e24be0ef623774b3303755b3d08a1 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package rand
index 60267fd4bc229263c39d016493b34c879cc0ccb0..d7c5bf3562d54747f0ab5db368f90a219dae964c 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build linux freebsd
+//go:build linux || freebsd || dragonfly || solaris
+// +build linux freebsd dragonfly solaris
 
 package rand
 
index 837db83f770844ef92d4b644fed2a491feed267f..2d20922c8253098f59eac79fe913c28ff9631cf1 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build linux freebsd
+//go:build linux || freebsd || dragonfly || solaris
+// +build linux freebsd dragonfly solaris
 
 package rand
 
diff --git a/libgo/go/crypto/rand/rand_dragonfly.go b/libgo/go/crypto/rand/rand_dragonfly.go
new file mode 100644 (file)
index 0000000..8a36fea
--- /dev/null
@@ -0,0 +1,9 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rand
+
+// maxGetRandomRead is the maximum number of bytes to ask for in one call to the
+// getrandom() syscall. In DragonFlyBSD at most 256 bytes will be returned per call.
+const maxGetRandomRead = 1 << 8
similarity index 79%
rename from libgo/go/crypto/rand/rand_openbsd.go
rename to libgo/go/crypto/rand/rand_getentropy.go
index 9cc39f72d1d9b221563ab37717dd1931daab0f28..f82018a4951c743c82f15c28b82262b601112f27 100644 (file)
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || openbsd
+// +build darwin openbsd
+
 package rand
 
 import (
@@ -9,10 +12,10 @@ import (
 )
 
 func init() {
-       altGetRandom = getRandomOpenBSD
+       altGetRandom = getEntropy
 }
 
-func getRandomOpenBSD(p []byte) (ok bool) {
+func getEntropy(p []byte) (ok bool) {
        // getentropy(2) returns a maximum of 256 bytes per call
        for i := 0; i < len(p); i += 256 {
                end := i + 256
index 7e939742ac657bbe389305a512676f39feceb243..7ddc2b6169cbe6d7f2587947ad150b68c6cc1739 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build js && wasm
 // +build js,wasm
 
 package rand
diff --git a/libgo/go/crypto/rand/rand_solaris.go b/libgo/go/crypto/rand/rand_solaris.go
new file mode 100644 (file)
index 0000000..bbad0fe
--- /dev/null
@@ -0,0 +1,10 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rand
+
+// maxGetRandomRead is the maximum number of bytes to ask for in one call to the
+// getrandom() syscall. Across all the Solaris platforms, 256 bytes is the
+// lowest number of bytes returned atomically per call.
+const maxGetRandomRead = 1 << 8
index 9ff4d35844e4a56ac0bd4fad474080557d6d6692..01458c64ad0c63cb27ad95475eb1186334bc1fec 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || plan9 || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd plan9 solaris
 
 // Unix cryptographically secure pseudorandom number
index b2adbedb28fa859aa9ee0a23ac5313ca53370e02..814522de8181fc326d29d925a7d6df8e53af7996 100644 (file)
@@ -269,7 +269,7 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte,
        saltLength := opts.saltLength()
        switch saltLength {
        case PSSSaltLengthAuto:
-               saltLength = priv.Size() - 2 - hash.Size()
+               saltLength = (priv.N.BitLen()-1+7)/8 - 2 - hash.Size()
        case PSSSaltLengthEqualsHash:
                saltLength = hash.Size()
        }
index dfa8d8bb5ad02e6feb3420348680c146b03740ad..c3a6d468497cd44ef38023e3d97a4b2e6dbc38d1 100644 (file)
@@ -12,7 +12,7 @@ import (
        _ "crypto/md5"
        "crypto/rand"
        "crypto/sha1"
-       "crypto/sha256"
+       "crypto/sha256"
        "encoding/hex"
        "math/big"
        "os"
@@ -233,6 +233,24 @@ func TestPSSSigning(t *testing.T) {
        }
 }
 
+func TestSignWithPSSSaltLengthAuto(t *testing.T) {
+       key, err := GenerateKey(rand.Reader, 513)
+       if err != nil {
+               t.Fatal(err)
+       }
+       digest := sha256.Sum256([]byte("message"))
+       signature, err := key.Sign(rand.Reader, digest[:], &PSSOptions{
+               SaltLength: PSSSaltLengthAuto,
+               Hash:       crypto.SHA256,
+       })
+       if err != nil {
+               t.Fatal(err)
+       }
+       if len(signature) == 0 {
+               t.Fatal("empty signature returned")
+       }
+}
+
 func bigFromHex(hex string) *big.Int {
        n, ok := new(big.Int).SetString(hex, 16)
        if !ok {
index 178ade666a15fc47a2325502b9247ea983c3470a..6fd59b39409ca979458b2777899e9fc612356787 100644 (file)
@@ -401,7 +401,7 @@ func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int {
 //
 // The label parameter may contain arbitrary data that will not be encrypted,
 // but which gives important context to the message. For example, if a given
-// public key is used to decrypt two types of messages then distinct label
+// public key is used to encrypt two types of messages then distinct label
 // values could be used to ensure that a ciphertext for one purpose cannot be
 // used for another by an attacker. If not required it can be empty.
 //
index a47b3f404474c8cee97436983ddab95acfa4ef2e..b270d79d3c1394921c2dd510274fcb08703e0323 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
-// +build s390x
 
 package sha1
 
index 98038e58077c2ff0ebc74419a257cc611fe541e1..436f78c74534d40f4fef63a31bebb354baad4edf 100644 (file)
@@ -1,3 +1,4 @@
+//go:build amd64 && (linux || darwin)
 // +build amd64
 // +build linux darwin
 
index 681e928de2530ae7af7928b9b81d2d9eebaa522b..c3e6010af121928d28227bb4d1095c5437fa14e4 100644 (file)
@@ -156,7 +156,7 @@ func TestBlockGeneric(t *testing.T) {
 // Tests for unmarshaling hashes that have hashed a large amount of data
 // The initial hash generation is omitted from the test, because it takes a long time.
 // The test contains some already-generated states, and their expected sums
-// Tests a problem that is outlined in Github issue #29543
+// Tests a problem that is outlined in GitHub issue #29543
 // The problem is triggered when an amount of data has been hashed for which
 // the data length has a 1 in the 32nd bit. When casted to int, this changes
 // the sign of the value, and causes the modulus operation to return a
index 88074c0bffe29d8da9ecd901de0c4442a9158e7a..d0d527d416eec00abbf1139d843e591beaafed54 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
-// +build arm 386 s390x
 
 package sha1
 
index 089b3c45ff017de8e7c6b7580a0db543ca338cae..48629ee796953922014b0dc184dc5ad187da2a9c 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//-go:build !amd64 && !386 && !arm && !s390x && !arm64
 // -build !amd64,!386,!arm,!s390x,!arm64
 
 package sha1
index 1a6e6a572d8dce38dfe00c215cccb46e0fed0e92..de1c15468f5ff6bd682d6bf617823468ec8fd80d 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
-// +build s390x
 
 package sha256
 
index 433c5a4c5e6254e9cd0acdd33f9a3c15bdb724a9..a2794b015dbc44375cb502afc08fe53d38111b8a 100644 (file)
@@ -229,7 +229,7 @@ func TestBlockGeneric(t *testing.T) {
 // Tests for unmarshaling hashes that have hashed a large amount of data
 // The initial hash generation is omitted from the test, because it takes a long time.
 // The test contains some already-generated states, and their expected sums
-// Tests a problem that is outlined in Github issue #29517
+// Tests a problem that is outlined in GitHub issue #29517
 // The problem is triggered when an amount of data has been hashed for which
 // the data length has a 1 in the 32nd bit. When casted to int, this changes
 // the sign of the value, and causes the modulus operation to return a
index e283c412c183ad4a7ad9523ee54cd0e3ffd340b1..ccbd9d65466f1845501df1596273b01230e2b9ec 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
-// +build 386 amd64 s390x ppc64le
 
 package sha256
 
index d1b507583d336a2d6129c3890e35c836b4a99d10..2d320b83be114f980bf09c2f6f12ea30785e3e23 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//-go:build !amd64 && !386 && !s390x && !ppc64le && !arm64
 // -build !amd64,!386,!s390x,!ppc64le,!arm64
 
 package sha256
index 14081318ad11ea3ed4c5ebfb7a496ddf77ea892a..30c161f7bc250ed26bb844e060e31557210475dc 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
-// +build s390x
 
 package sha512
 
index 59998b1d38d7450c29ec2d5d191194f060fa20f2..0e1528fc69f6018162473f9223557a7cfbee9d3a 100644 (file)
@@ -788,7 +788,7 @@ func TestMarshalMismatch(t *testing.T) {
                        }
 
                        if err := h2.(encoding.BinaryUnmarshaler).UnmarshalBinary(state); err == nil {
-                               t.Errorf("i=%d, j=%d: got no error , expected one: %v", i, j, err)
+                               t.Errorf("i=%d, j=%d: got no error, expected one: %v", i, j, err)
                        }
                }
        }
@@ -835,7 +835,7 @@ func TestBlockGeneric(t *testing.T) {
 // Tests for unmarshaling hashes that have hashed a large amount of data
 // The initial hash generation is omitted from the test, because it takes a long time.
 // The test contains some already-generated states, and their expected sums
-// Tests a problem that is outlined in Github issue #29541
+// Tests a problem that is outlined in GitHub issue #29541
 // The problem is triggered when an amount of data has been hashed for which
 // the data length has a 1 in the 32nd bit. When casted to int, this changes
 // the sign of the value, and causes the modulus operation to return a
index 0ce599b8ebcb4f43fce9a5ed8144c926896c7e51..8ec87c3fbb982bc527a7316e6f0992f1e2da9828 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
-// +build amd64
 
 package sha512
 
index 3d098c5b17eaac01dd93c9b5309c4012904e42cd..e4e5858adb1cb480360eb7da4563bd7cccc8af95 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
-// +build s390x ppc64le
 
 package sha512
 
index d3998a8283a50d33aa6ab50a5a400a091fa81b17..2b0854beb4e72cdea1b30d652d30b44cbee70c4b 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//-go:build !amd64 && !s390x && !ppc64le
 // -build !amd64,!s390x,!ppc64le
 
 package sha512
index 9a356758fbfc5dc09835bc6db3c1cee86983f5f1..4bf06468c6dae4741d0302b15b77f5219bc054ad 100644 (file)
@@ -13,9 +13,10 @@ import (
        "crypto/rc4"
        "crypto/sha1"
        "crypto/sha256"
-       "crypto/x509"
        "fmt"
        "hash"
+       "internal/cpu"
+       "runtime"
 
        "golang.org/x/crypto/chacha20poly1305"
 )
@@ -46,10 +47,10 @@ var (
 // InsecureCipherSuites.
 //
 // The list is sorted by ID. Note that the default cipher suites selected by
-// this package might depend on logic that can't be captured by a static list.
+// this package might depend on logic that can't be captured by a static list,
+// and might not match those returned by this function.
 func CipherSuites() []*CipherSuite {
        return []*CipherSuite{
-               {TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA", supportedUpToTLS12, false},
                {TLS_RSA_WITH_AES_128_CBC_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA", supportedUpToTLS12, false},
                {TLS_RSA_WITH_AES_256_CBC_SHA, "TLS_RSA_WITH_AES_256_CBC_SHA", supportedUpToTLS12, false},
                {TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS_RSA_WITH_AES_128_GCM_SHA256", supportedOnlyTLS12, false},
@@ -61,7 +62,6 @@ func CipherSuites() []*CipherSuite {
 
                {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", supportedUpToTLS12, false},
                {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", supportedUpToTLS12, false},
-               {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", supportedUpToTLS12, false},
                {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", supportedUpToTLS12, false},
                {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", supportedUpToTLS12, false},
                {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", supportedOnlyTLS12, false},
@@ -79,13 +79,15 @@ func CipherSuites() []*CipherSuite {
 // Most applications should not use the cipher suites in this list, and should
 // only use those returned by CipherSuites.
 func InsecureCipherSuites() []*CipherSuite {
-       // RC4 suites are broken because RC4 is.
-       // CBC-SHA256 suites have no Lucky13 countermeasures.
+       // This list includes RC4, CBC_SHA256, and 3DES cipher suites. See
+       // cipherSuitesPreferenceOrder for details.
        return []*CipherSuite{
                {TLS_RSA_WITH_RC4_128_SHA, "TLS_RSA_WITH_RC4_128_SHA", supportedUpToTLS12, true},
+               {TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA", supportedUpToTLS12, true},
                {TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS_RSA_WITH_AES_128_CBC_SHA256", supportedOnlyTLS12, true},
                {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", supportedUpToTLS12, true},
                {TLS_ECDHE_RSA_WITH_RC4_128_SHA, "TLS_ECDHE_RSA_WITH_RC4_128_SHA", supportedUpToTLS12, true},
+               {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", supportedUpToTLS12, true},
                {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", supportedOnlyTLS12, true},
                {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", supportedOnlyTLS12, true},
        }
@@ -108,25 +110,6 @@ func CipherSuiteName(id uint16) string {
        return fmt.Sprintf("0x%04X", id)
 }
 
-// a keyAgreement implements the client and server side of a TLS key agreement
-// protocol by generating and processing key exchange messages.
-type keyAgreement interface {
-       // On the server side, the first two methods are called in order.
-
-       // In the case that the key agreement protocol doesn't use a
-       // ServerKeyExchange message, generateServerKeyExchange can return nil,
-       // nil.
-       generateServerKeyExchange(*Config, *Certificate, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error)
-       processClientKeyExchange(*Config, *Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error)
-
-       // On the client side, the next two methods are called in order.
-
-       // This method may not be called if the server doesn't send a
-       // ServerKeyExchange message.
-       processServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) error
-       generateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error)
-}
-
 const (
        // suiteECDHE indicates that the cipher suite involves elliptic curve
        // Diffie-Hellman. This means that it should only be selected when the
@@ -144,12 +127,10 @@ const (
        // suiteSHA384 indicates that the cipher suite uses SHA384 as the
        // handshake hash.
        suiteSHA384
-       // suiteDefaultOff indicates that this cipher suite is not included by
-       // default.
-       suiteDefaultOff
 )
 
-// A cipherSuite is a specific combination of key agreement, cipher and MAC function.
+// A cipherSuite is a TLS 1.0–1.2 cipher suite, and defines the key exchange
+// mechanism, as well as the cipher+MAC pair or the AEAD.
 type cipherSuite struct {
        id uint16
        // the lengths, in bytes, of the key material needed for each component.
@@ -164,37 +145,33 @@ type cipherSuite struct {
        aead   func(key, fixedNonce []byte) aead
 }
 
-var cipherSuites = []*cipherSuite{
-       // Ciphersuite order is chosen so that ECDHE comes before plain RSA and
-       // AEADs are the top preference.
+var cipherSuites = []*cipherSuite{ // TODO: replace with a map, since the order doesn't matter.
        {TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, 32, 0, 12, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadChaCha20Poly1305},
        {TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, 32, 0, 12, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12, nil, nil, aeadChaCha20Poly1305},
        {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM},
        {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12, nil, nil, aeadAESGCM},
        {TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
        {TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
-       {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteDefaultOff, cipherAES, macSHA256, nil},
+       {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheRSAKA, suiteECDHE | suiteTLS12, cipherAES, macSHA256, nil},
        {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
-       {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12 | suiteDefaultOff, cipherAES, macSHA256, nil},
+       {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12, cipherAES, macSHA256, nil},
        {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECSign, cipherAES, macSHA1, nil},
        {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
        {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECSign, cipherAES, macSHA1, nil},
        {TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, rsaKA, suiteTLS12, nil, nil, aeadAESGCM},
        {TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
-       {TLS_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, rsaKA, suiteTLS12 | suiteDefaultOff, cipherAES, macSHA256, nil},
+       {TLS_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, rsaKA, suiteTLS12, cipherAES, macSHA256, nil},
        {TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
        {TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
        {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil},
        {TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil},
-
-       // RC4-based cipher suites are disabled by default.
-       {TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, suiteDefaultOff, cipherRC4, macSHA1, nil},
-       {TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE | suiteDefaultOff, cipherRC4, macSHA1, nil},
-       {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteDefaultOff, cipherRC4, macSHA1, nil},
+       {TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, 0, cipherRC4, macSHA1, nil},
+       {TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE, cipherRC4, macSHA1, nil},
+       {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECSign, cipherRC4, macSHA1, nil},
 }
 
-// selectCipherSuite returns the first cipher suite from ids which is also in
-// supportedIDs and passes the ok filter.
+// selectCipherSuite returns the first TLS 1.0–1.2 cipher suite from ids which
+// is also in supportedIDs and passes the ok filter.
 func selectCipherSuite(ids, supportedIDs []uint16, ok func(*cipherSuite) bool) *cipherSuite {
        for _, id := range ids {
                candidate := cipherSuiteByID(id)
@@ -220,12 +197,208 @@ type cipherSuiteTLS13 struct {
        hash   crypto.Hash
 }
 
-var cipherSuitesTLS13 = []*cipherSuiteTLS13{
+var cipherSuitesTLS13 = []*cipherSuiteTLS13{ // TODO: replace with a map.
        {TLS_AES_128_GCM_SHA256, 16, aeadAESGCMTLS13, crypto.SHA256},
        {TLS_CHACHA20_POLY1305_SHA256, 32, aeadChaCha20Poly1305, crypto.SHA256},
        {TLS_AES_256_GCM_SHA384, 32, aeadAESGCMTLS13, crypto.SHA384},
 }
 
+// cipherSuitesPreferenceOrder is the order in which we'll select (on the
+// server) or advertise (on the client) TLS 1.0–1.2 cipher suites.
+//
+// Cipher suites are filtered but not reordered based on the application and
+// peer's preferences, meaning we'll never select a suite lower in this list if
+// any higher one is available. This makes it more defensible to keep weaker
+// cipher suites enabled, especially on the server side where we get the last
+// word, since there are no known downgrade attacks on cipher suites selection.
+//
+// The list is sorted by applying the following priority rules, stopping at the
+// first (most important) applicable one:
+//
+//   - Anything else comes before RC4
+//
+//       RC4 has practically exploitable biases. See https://www.rc4nomore.com.
+//
+//   - Anything else comes before CBC_SHA256
+//
+//       SHA-256 variants of the CBC ciphersuites don't implement any Lucky13
+//       countermeasures. See http://www.isg.rhul.ac.uk/tls/Lucky13.html and
+//       https://www.imperialviolet.org/2013/02/04/luckythirteen.html.
+//
+//   - Anything else comes before 3DES
+//
+//       3DES has 64-bit blocks, which makes it fundamentally susceptible to
+//       birthday attacks. See https://sweet32.info.
+//
+//   - ECDHE comes before anything else
+//
+//       Once we got the broken stuff out of the way, the most important
+//       property a cipher suite can have is forward secrecy. We don't
+//       implement FFDHE, so that means ECDHE.
+//
+//   - AEADs come before CBC ciphers
+//
+//       Even with Lucky13 countermeasures, MAC-then-Encrypt CBC cipher suites
+//       are fundamentally fragile, and suffered from an endless sequence of
+//       padding oracle attacks. See https://eprint.iacr.org/2015/1129,
+//       https://www.imperialviolet.org/2014/12/08/poodleagain.html, and
+//       https://blog.cloudflare.com/yet-another-padding-oracle-in-openssl-cbc-ciphersuites/.
+//
+//   - AES comes before ChaCha20
+//
+//       When AES hardware is available, AES-128-GCM and AES-256-GCM are faster
+//       than ChaCha20Poly1305.
+//
+//       When AES hardware is not available, AES-128-GCM is one or more of: much
+//       slower, way more complex, and less safe (because not constant time)
+//       than ChaCha20Poly1305.
+//
+//       We use this list if we think both peers have AES hardware, and
+//       cipherSuitesPreferenceOrderNoAES otherwise.
+//
+//   - AES-128 comes before AES-256
+//
+//       The only potential advantages of AES-256 are better multi-target
+//       margins, and hypothetical post-quantum properties. Neither apply to
+//       TLS, and AES-256 is slower due to its four extra rounds (which don't
+//       contribute to the advantages above).
+//
+//   - ECDSA comes before RSA
+//
+//       The relative order of ECDSA and RSA cipher suites doesn't matter,
+//       as they depend on the certificate. Pick one to get a stable order.
+//
+var cipherSuitesPreferenceOrder = []uint16{
+       // AEADs w/ ECDHE
+       TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+       TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+       TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+
+       // CBC w/ ECDHE
+       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+
+       // AEADs w/o ECDHE
+       TLS_RSA_WITH_AES_128_GCM_SHA256,
+       TLS_RSA_WITH_AES_256_GCM_SHA384,
+
+       // CBC w/o ECDHE
+       TLS_RSA_WITH_AES_128_CBC_SHA,
+       TLS_RSA_WITH_AES_256_CBC_SHA,
+
+       // 3DES
+       TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
+       TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+
+       // CBC_SHA256
+       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+       TLS_RSA_WITH_AES_128_CBC_SHA256,
+
+       // RC4
+       TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA,
+       TLS_RSA_WITH_RC4_128_SHA,
+}
+
+var cipherSuitesPreferenceOrderNoAES = []uint16{
+       // ChaCha20Poly1305
+       TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+
+       // AES-GCM w/ ECDHE
+       TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+       TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+
+       // The rest of cipherSuitesPreferenceOrder.
+       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+       TLS_RSA_WITH_AES_128_GCM_SHA256,
+       TLS_RSA_WITH_AES_256_GCM_SHA384,
+       TLS_RSA_WITH_AES_128_CBC_SHA,
+       TLS_RSA_WITH_AES_256_CBC_SHA,
+       TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
+       TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+       TLS_RSA_WITH_AES_128_CBC_SHA256,
+       TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA,
+       TLS_RSA_WITH_RC4_128_SHA,
+}
+
+// disabledCipherSuites are not used unless explicitly listed in
+// Config.CipherSuites. They MUST be at the end of cipherSuitesPreferenceOrder.
+var disabledCipherSuites = []uint16{
+       // CBC_SHA256
+       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+       TLS_RSA_WITH_AES_128_CBC_SHA256,
+
+       // RC4
+       TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA,
+       TLS_RSA_WITH_RC4_128_SHA,
+}
+
+var (
+       defaultCipherSuitesLen = len(cipherSuitesPreferenceOrder) - len(disabledCipherSuites)
+       defaultCipherSuites    = cipherSuitesPreferenceOrder[:defaultCipherSuitesLen]
+)
+
+// defaultCipherSuitesTLS13 is also the preference order, since there are no
+// disabled by default TLS 1.3 cipher suites. The same AES vs ChaCha20 logic as
+// cipherSuitesPreferenceOrder applies.
+var defaultCipherSuitesTLS13 = []uint16{
+       TLS_AES_128_GCM_SHA256,
+       TLS_AES_256_GCM_SHA384,
+       TLS_CHACHA20_POLY1305_SHA256,
+}
+
+var defaultCipherSuitesTLS13NoAES = []uint16{
+       TLS_CHACHA20_POLY1305_SHA256,
+       TLS_AES_128_GCM_SHA256,
+       TLS_AES_256_GCM_SHA384,
+}
+
+var (
+       hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ
+       hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL
+       // Keep in sync with crypto/aes/cipher_s390x.go.
+       hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR &&
+               (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM)
+
+       hasAESGCMHardwareSupport = runtime.GOARCH == "amd64" && hasGCMAsmAMD64 ||
+               runtime.GOARCH == "arm64" && hasGCMAsmARM64 ||
+               runtime.GOARCH == "s390x" && hasGCMAsmS390X
+)
+
+var aesgcmCiphers = map[uint16]bool{
+       // TLS 1.2
+       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:   true,
+       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:   true,
+       TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: true,
+       TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: true,
+       // TLS 1.3
+       TLS_AES_128_GCM_SHA256: true,
+       TLS_AES_256_GCM_SHA384: true,
+}
+
+var nonAESGCMAEADCiphers = map[uint16]bool{
+       // TLS 1.2
+       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305:   true,
+       TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: true,
+       // TLS 1.3
+       TLS_CHACHA20_POLY1305_SHA256: true,
+}
+
+// aesgcmPreferred returns whether the first known cipher in the preference list
+// is an AES-GCM cipher, implying the peer has hardware support for it.
+func aesgcmPreferred(ciphers []uint16) bool {
+       for _, cID := range ciphers {
+               if c := cipherSuiteByID(cID); c != nil {
+                       return aesgcmCiphers[cID]
+               }
+               if c := cipherSuiteTLS13ByID(cID); c != nil {
+                       return aesgcmCiphers[cID]
+               }
+       }
+       return false
+}
+
 func cipherRC4(key, iv []byte, isRead bool) interface{} {
        cipher, _ := rc4.NewCipher(key)
        return cipher
index eec6e1ebbd9060559637c9d2476046b2665a4bed..d561e61707edd979576c9c21ec8224aa2228c447 100644 (file)
@@ -7,6 +7,7 @@ package tls
 import (
        "bytes"
        "container/list"
+       "context"
        "crypto"
        "crypto/ecdsa"
        "crypto/ed25519"
@@ -17,11 +18,8 @@ import (
        "crypto/x509"
        "errors"
        "fmt"
-       "internal/cpu"
        "io"
        "net"
-       "runtime"
-       "sort"
        "strings"
        "sync"
        "time"
@@ -443,6 +441,16 @@ type ClientHelloInfo struct {
        // config is embedded by the GetCertificate or GetConfigForClient caller,
        // for use with SupportsCertificate.
        config *Config
+
+       // ctx is the context of the handshake that is in progress.
+       ctx context.Context
+}
+
+// Context returns the context of the handshake that is in progress.
+// This context is a child of the context passed to HandshakeContext,
+// if any, and is canceled when the handshake concludes.
+func (c *ClientHelloInfo) Context() context.Context {
+       return c.ctx
 }
 
 // CertificateRequestInfo contains information from a server's
@@ -461,6 +469,16 @@ type CertificateRequestInfo struct {
 
        // Version is the TLS version that was negotiated for this connection.
        Version uint16
+
+       // ctx is the context of the handshake that is in progress.
+       ctx context.Context
+}
+
+// Context returns the context of the handshake that is in progress.
+// This context is a child of the context passed to HandshakeContext,
+// if any, and is canceled when the handshake concludes.
+func (c *CertificateRequestInfo) Context() context.Context {
+       return c.ctx
 }
 
 // RenegotiationSupport enumerates the different levels of support for TLS
@@ -597,7 +615,11 @@ type Config struct {
        RootCAs *x509.CertPool
 
        // NextProtos is a list of supported application level protocols, in
-       // order of preference.
+       // order of preference. If both peers support ALPN, the selected
+       // protocol will be one from this list, and the connection will fail
+       // if there is no mutually supported protocol. If NextProtos is empty
+       // or the peer doesn't support ALPN, the connection will succeed and
+       // ConnectionState.NegotiatedProtocol will be empty.
        NextProtos []string
 
        // ServerName is used to verify the hostname on the returned
@@ -623,17 +645,21 @@ type Config struct {
        // testing or in combination with VerifyConnection or VerifyPeerCertificate.
        InsecureSkipVerify bool
 
-       // CipherSuites is a list of supported cipher suites for TLS versions up to
-       // TLS 1.2. If CipherSuites is nil, a default list of secure cipher suites
-       // is used, with a preference order based on hardware performance. The
-       // default cipher suites might change over Go versions. Note that TLS 1.3
-       // ciphersuites are not configurable.
+       // CipherSuites is a list of enabled TLS 1.0–1.2 cipher suites. The order of
+       // the list is ignored. Note that TLS 1.3 ciphersuites are not configurable.
+       //
+       // If CipherSuites is nil, a safe default list is used. The default cipher
+       // suites might change over time.
        CipherSuites []uint16
 
-       // PreferServerCipherSuites controls whether the server selects the
-       // client's most preferred ciphersuite, or the server's most preferred
-       // ciphersuite. If true then the server's preference, as expressed in
-       // the order of elements in CipherSuites, is used.
+       // PreferServerCipherSuites is a legacy field and has no effect.
+       //
+       // It used to control whether the server would follow the client's or the
+       // server's preference. Servers now select the best mutually supported
+       // cipher suite based on logic that takes into account inferred client
+       // hardware, server hardware, and security.
+       //
+       // Deprected: PreferServerCipherSuites is ignored.
        PreferServerCipherSuites bool
 
        // SessionTicketsDisabled may be set to true to disable session ticket and
@@ -925,11 +951,10 @@ func (c *Config) time() time.Time {
 }
 
 func (c *Config) cipherSuites() []uint16 {
-       s := c.CipherSuites
-       if s == nil {
-               s = defaultCipherSuites()
+       if c.CipherSuites != nil {
+               return c.CipherSuites
        }
-       return s
+       return defaultCipherSuites
 }
 
 var supportedVersions = []uint16{
@@ -1419,87 +1444,6 @@ func defaultConfig() *Config {
        return &emptyConfig
 }
 
-var (
-       once                        sync.Once
-       varDefaultCipherSuites      []uint16
-       varDefaultCipherSuitesTLS13 []uint16
-)
-
-func defaultCipherSuites() []uint16 {
-       once.Do(initDefaultCipherSuites)
-       return varDefaultCipherSuites
-}
-
-func defaultCipherSuitesTLS13() []uint16 {
-       once.Do(initDefaultCipherSuites)
-       return varDefaultCipherSuitesTLS13
-}
-
-var (
-       hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ
-       hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL
-       // Keep in sync with crypto/aes/cipher_s390x.go.
-       hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR && (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM)
-
-       hasAESGCMHardwareSupport = runtime.GOARCH == "amd64" && hasGCMAsmAMD64 ||
-               runtime.GOARCH == "arm64" && hasGCMAsmARM64 ||
-               runtime.GOARCH == "s390x" && hasGCMAsmS390X
-)
-
-func initDefaultCipherSuites() {
-       var topCipherSuites []uint16
-
-       if hasAESGCMHardwareSupport {
-               // If AES-GCM hardware is provided then prioritise AES-GCM
-               // cipher suites.
-               topCipherSuites = []uint16{
-                       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-                       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
-                       TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
-                       TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
-                       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
-                       TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
-               }
-               varDefaultCipherSuitesTLS13 = []uint16{
-                       TLS_AES_128_GCM_SHA256,
-                       TLS_CHACHA20_POLY1305_SHA256,
-                       TLS_AES_256_GCM_SHA384,
-               }
-       } else {
-               // Without AES-GCM hardware, we put the ChaCha20-Poly1305
-               // cipher suites first.
-               topCipherSuites = []uint16{
-                       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
-                       TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
-                       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-                       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
-                       TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
-                       TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
-               }
-               varDefaultCipherSuitesTLS13 = []uint16{
-                       TLS_CHACHA20_POLY1305_SHA256,
-                       TLS_AES_128_GCM_SHA256,
-                       TLS_AES_256_GCM_SHA384,
-               }
-       }
-
-       varDefaultCipherSuites = make([]uint16, 0, len(cipherSuites))
-       varDefaultCipherSuites = append(varDefaultCipherSuites, topCipherSuites...)
-
-NextCipherSuite:
-       for _, suite := range cipherSuites {
-               if suite.flags&suiteDefaultOff != 0 {
-                       continue
-               }
-               for _, existing := range varDefaultCipherSuites {
-                       if existing == suite.id {
-                               continue NextCipherSuite
-                       }
-               }
-               varDefaultCipherSuites = append(varDefaultCipherSuites, suite.id)
-       }
-}
-
 func unexpectedMessageError(wanted, got interface{}) error {
        return fmt.Errorf("tls: received unexpected handshake message of type %T when waiting for %T", got, wanted)
 }
@@ -1512,51 +1456,3 @@ func isSupportedSignatureAlgorithm(sigAlg SignatureScheme, supportedSignatureAlg
        }
        return false
 }
-
-var aesgcmCiphers = map[uint16]bool{
-       // 1.2
-       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:   true,
-       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:   true,
-       TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: true,
-       TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: true,
-       // 1.3
-       TLS_AES_128_GCM_SHA256: true,
-       TLS_AES_256_GCM_SHA384: true,
-}
-
-var nonAESGCMAEADCiphers = map[uint16]bool{
-       // 1.2
-       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305:   true,
-       TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: true,
-       // 1.3
-       TLS_CHACHA20_POLY1305_SHA256: true,
-}
-
-// aesgcmPreferred returns whether the first valid cipher in the preference list
-// is an AES-GCM cipher, implying the peer has hardware support for it.
-func aesgcmPreferred(ciphers []uint16) bool {
-       for _, cID := range ciphers {
-               c := cipherSuiteByID(cID)
-               if c == nil {
-                       c13 := cipherSuiteTLS13ByID(cID)
-                       if c13 == nil {
-                               continue
-                       }
-                       return aesgcmCiphers[cID]
-               }
-               return aesgcmCiphers[cID]
-       }
-       return false
-}
-
-// deprioritizeAES reorders cipher preference lists by rearranging
-// adjacent AEAD ciphers such that AES-GCM based ciphers are moved
-// after other AEAD ciphers. It returns a fresh slice.
-func deprioritizeAES(ciphers []uint16) []uint16 {
-       reordered := make([]uint16, len(ciphers))
-       copy(reordered, ciphers)
-       sort.SliceStable(reordered, func(i, j int) bool {
-               return nonAESGCMAEADCiphers[reordered[i]] && aesgcmCiphers[reordered[j]]
-       })
-       return reordered
-}
index 72ad52c194baf49c988baf83340573ed0e54cd01..969f357834c0a5c1733b7b939248ebf07d514510 100644 (file)
@@ -8,6 +8,7 @@ package tls
 
 import (
        "bytes"
+       "context"
        "crypto/cipher"
        "crypto/subtle"
        "crypto/x509"
@@ -27,7 +28,7 @@ type Conn struct {
        // constant
        conn        net.Conn
        isClient    bool
-       handshakeFn func() error // (*Conn).clientHandshake or serverHandshake
+       handshakeFn func(context.Context) error // (*Conn).clientHandshake or serverHandshake
 
        // handshakeStatus is 1 if the connection is currently transferring
        // application data (i.e. is not currently processing a handshake).
@@ -1190,7 +1191,7 @@ func (c *Conn) handleRenegotiation() error {
        defer c.handshakeMutex.Unlock()
 
        atomic.StoreUint32(&c.handshakeStatus, 0)
-       if c.handshakeErr = c.clientHandshake(); c.handshakeErr == nil {
+       if c.handshakeErr = c.clientHandshake(context.Background()); c.handshakeErr == nil {
                c.handshakes++
        }
        return c.handshakeErr
@@ -1373,8 +1374,61 @@ func (c *Conn) closeNotify() error {
 // first Read or Write will call it automatically.
 //
 // For control over canceling or setting a timeout on a handshake, use
-// the Dialer's DialContext method.
+// HandshakeContext or the Dialer's DialContext method instead.
 func (c *Conn) Handshake() error {
+       return c.HandshakeContext(context.Background())
+}
+
+// HandshakeContext runs the client or server handshake
+// protocol if it has not yet been run.
+//
+// The provided Context must be non-nil. If the context is canceled before
+// the handshake is complete, the handshake is interrupted and an error is returned.
+// Once the handshake has completed, cancellation of the context will not affect the
+// connection.
+//
+// Most uses of this package need not call HandshakeContext explicitly: the
+// first Read or Write will call it automatically.
+func (c *Conn) HandshakeContext(ctx context.Context) error {
+       // Delegate to unexported method for named return
+       // without confusing documented signature.
+       return c.handshakeContext(ctx)
+}
+
+func (c *Conn) handshakeContext(ctx context.Context) (ret error) {
+       handshakeCtx, cancel := context.WithCancel(ctx)
+       // Note: defer this before starting the "interrupter" goroutine
+       // so that we can tell the difference between the input being canceled and
+       // this cancellation. In the former case, we need to close the connection.
+       defer cancel()
+
+       // Start the "interrupter" goroutine, if this context might be canceled.
+       // (The background context cannot).
+       //
+       // The interrupter goroutine waits for the input context to be done and
+       // closes the connection if this happens before the function returns.
+       if ctx.Done() != nil {
+               done := make(chan struct{})
+               interruptRes := make(chan error, 1)
+               defer func() {
+                       close(done)
+                       if ctxErr := <-interruptRes; ctxErr != nil {
+                               // Return context error to user.
+                               ret = ctxErr
+                       }
+               }()
+               go func() {
+                       select {
+                       case <-handshakeCtx.Done():
+                               // Close the connection, discarding the error
+                               _ = c.conn.Close()
+                               interruptRes <- handshakeCtx.Err()
+                       case <-done:
+                               interruptRes <- nil
+                       }
+               }()
+       }
+
        c.handshakeMutex.Lock()
        defer c.handshakeMutex.Unlock()
 
@@ -1388,7 +1442,7 @@ func (c *Conn) Handshake() error {
        c.in.Lock()
        defer c.in.Unlock()
 
-       c.handshakeErr = c.handshakeFn()
+       c.handshakeErr = c.handshakeFn(handshakeCtx)
        if c.handshakeErr == nil {
                c.handshakes++
        } else {
index 1857185fe4d8f0cf49ef9cf36c9e8716d3d34789..7ea90f8a7b51c32f0d7e595a94d96db724872233 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 // Generate a self-signed X.509 certificate for a TLS server. Outputs to
index e684b21d527223e850e8a74d802e9ac0521e9753..4af3d998a36f800c02989a37b9f8ba0d3eaed36a 100644 (file)
@@ -6,6 +6,7 @@ package tls
 
 import (
        "bytes"
+       "context"
        "crypto"
        "crypto/ecdsa"
        "crypto/ed25519"
@@ -24,6 +25,7 @@ import (
 
 type clientHandshakeState struct {
        c            *Conn
+       ctx          context.Context
        serverHello  *serverHelloMsg
        hello        *clientHelloMsg
        suite        *cipherSuite
@@ -82,22 +84,24 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) {
                hello.secureRenegotiation = c.clientFinished[:]
        }
 
-       possibleCipherSuites := config.cipherSuites()
-       hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites))
+       preferenceOrder := cipherSuitesPreferenceOrder
+       if !hasAESGCMHardwareSupport {
+               preferenceOrder = cipherSuitesPreferenceOrderNoAES
+       }
+       configCipherSuites := config.cipherSuites()
+       hello.cipherSuites = make([]uint16, 0, len(configCipherSuites))
 
-       for _, suiteId := range possibleCipherSuites {
-               for _, suite := range cipherSuites {
-                       if suite.id != suiteId {
-                               continue
-                       }
-                       // Don't advertise TLS 1.2-only cipher suites unless
-                       // we're attempting TLS 1.2.
-                       if hello.vers < VersionTLS12 && suite.flags&suiteTLS12 != 0 {
-                               break
-                       }
-                       hello.cipherSuites = append(hello.cipherSuites, suiteId)
-                       break
+       for _, suiteId := range preferenceOrder {
+               suite := mutualCipherSuite(configCipherSuites, suiteId)
+               if suite == nil {
+                       continue
+               }
+               // Don't advertise TLS 1.2-only cipher suites unless
+               // we're attempting TLS 1.2.
+               if hello.vers < VersionTLS12 && suite.flags&suiteTLS12 != 0 {
+                       continue
                }
+               hello.cipherSuites = append(hello.cipherSuites, suiteId)
        }
 
        _, err := io.ReadFull(config.rand(), hello.random)
@@ -118,7 +122,11 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) {
 
        var params ecdheParameters
        if hello.supportedVersions[0] == VersionTLS13 {
-               hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13()...)
+               if hasAESGCMHardwareSupport {
+                       hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13...)
+               } else {
+                       hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13NoAES...)
+               }
 
                curveID := config.curvePreferences()[0]
                if _, ok := curveForCurveID(curveID); curveID != X25519 && !ok {
@@ -134,7 +142,7 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) {
        return hello, params, nil
 }
 
-func (c *Conn) clientHandshake() (err error) {
+func (c *Conn) clientHandshake(ctx context.Context) (err error) {
        if c.config == nil {
                c.config = defaultConfig()
        }
@@ -198,6 +206,7 @@ func (c *Conn) clientHandshake() (err error) {
        if c.vers == VersionTLS13 {
                hs := &clientHandshakeStateTLS13{
                        c:           c,
+                       ctx:         ctx,
                        serverHello: serverHello,
                        hello:       hello,
                        ecdheParams: ecdheParams,
@@ -212,6 +221,7 @@ func (c *Conn) clientHandshake() (err error) {
 
        hs := &clientHandshakeState{
                c:           c,
+               ctx:         ctx,
                serverHello: serverHello,
                hello:       hello,
                session:     session,
@@ -540,7 +550,7 @@ func (hs *clientHandshakeState) doFullHandshake() error {
                certRequested = true
                hs.finishedHash.Write(certReq.marshal())
 
-               cri := certificateRequestInfoFromMsg(c.vers, certReq)
+               cri := certificateRequestInfoFromMsg(hs.ctx, c.vers, certReq)
                if chainToSend, err = c.getClientCertificate(cri); err != nil {
                        c.sendAlert(alertInternalError)
                        return err
@@ -701,17 +711,11 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
                }
        }
 
-       if hs.serverHello.alpnProtocol != "" {
-               if len(hs.hello.alpnProtocols) == 0 {
-                       c.sendAlert(alertUnsupportedExtension)
-                       return false, errors.New("tls: server advertised unrequested ALPN extension")
-               }
-               if mutualProtocol([]string{hs.serverHello.alpnProtocol}, hs.hello.alpnProtocols) == "" {
-                       c.sendAlert(alertUnsupportedExtension)
-                       return false, errors.New("tls: server selected unadvertised ALPN protocol")
-               }
-               c.clientProtocol = hs.serverHello.alpnProtocol
+       if err := checkALPN(hs.hello.alpnProtocols, hs.serverHello.alpnProtocol); err != nil {
+               c.sendAlert(alertUnsupportedExtension)
+               return false, err
        }
+       c.clientProtocol = hs.serverHello.alpnProtocol
 
        c.scts = hs.serverHello.scts
 
@@ -743,6 +747,23 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
        return true, nil
 }
 
+// checkALPN ensure that the server's choice of ALPN protocol is compatible with
+// the protocols that we advertised in the Client Hello.
+func checkALPN(clientProtos []string, serverProto string) error {
+       if serverProto == "" {
+               return nil
+       }
+       if len(clientProtos) == 0 {
+               return errors.New("tls: server advertised unrequested ALPN extension")
+       }
+       for _, proto := range clientProtos {
+               if proto == serverProto {
+                       return nil
+               }
+       }
+       return errors.New("tls: server selected unadvertised ALPN protocol")
+}
+
 func (hs *clientHandshakeState) readFinished(out []byte) error {
        c := hs.c
 
@@ -880,10 +901,11 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error {
 
 // certificateRequestInfoFromMsg generates a CertificateRequestInfo from a TLS
 // <= 1.2 CertificateRequest, making an effort to fill in missing information.
-func certificateRequestInfoFromMsg(vers uint16, certReq *certificateRequestMsg) *CertificateRequestInfo {
+func certificateRequestInfoFromMsg(ctx context.Context, vers uint16, certReq *certificateRequestMsg) *CertificateRequestInfo {
        cri := &CertificateRequestInfo{
                AcceptableCAs: certReq.certificateAuthorities,
                Version:       vers,
+               ctx:           ctx,
        }
 
        var rsaAvail, ecAvail bool
@@ -968,19 +990,6 @@ func clientSessionCacheKey(serverAddr net.Addr, config *Config) string {
        return serverAddr.String()
 }
 
-// mutualProtocol finds the mutual ALPN protocol given list of possible
-// protocols and a list of the preference order.
-func mutualProtocol(protos, preferenceProtos []string) string {
-       for _, s := range preferenceProtos {
-               for _, c := range protos {
-                       if s == c {
-                               return s
-                       }
-               }
-       }
-       return ""
-}
-
 // hostnameInSNI converts name into an appropriate hostname for SNI.
 // Literal IP addresses and absolute FQDNs are not permitted as SNI values.
 // See RFC 6066, Section 3.
index 12b0254123e938a71dd6b8c0592db9cf235bf255..b6eb488a4d7899bc19ad2c6e330ff8c60bf4beb4 100644 (file)
@@ -6,6 +6,7 @@ package tls
 
 import (
        "bytes"
+       "context"
        "crypto/rsa"
        "crypto/x509"
        "encoding/base64"
@@ -20,6 +21,7 @@ import (
        "os/exec"
        "path/filepath"
        "reflect"
+       "runtime"
        "strconv"
        "strings"
        "testing"
@@ -42,7 +44,7 @@ const (
        // opensslSentinel on the connection.
        opensslSendSentinel
 
-       // opensslKeyUpdate causes OpenSSL to send send a key update message to the
+       // opensslKeyUpdate causes OpenSSL to send a key update message to the
        // client and request one back.
        opensslKeyUpdate
 )
@@ -1222,6 +1224,56 @@ func TestHandshakeClientALPNMatch(t *testing.T) {
        runClientTestTLS13(t, test)
 }
 
+func TestServerSelectingUnconfiguredApplicationProtocol(t *testing.T) {
+       // This checks that the server can't select an application protocol that the
+       // client didn't offer.
+
+       c, s := localPipe(t)
+       errChan := make(chan error, 1)
+
+       go func() {
+               client := Client(c, &Config{
+                       ServerName:   "foo",
+                       CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
+                       NextProtos:   []string{"http", "something-else"},
+               })
+               errChan <- client.Handshake()
+       }()
+
+       var header [5]byte
+       if _, err := io.ReadFull(s, header[:]); err != nil {
+               t.Fatal(err)
+       }
+       recordLen := int(header[3])<<8 | int(header[4])
+
+       record := make([]byte, recordLen)
+       if _, err := io.ReadFull(s, record); err != nil {
+               t.Fatal(err)
+       }
+
+       serverHello := &serverHelloMsg{
+               vers:         VersionTLS12,
+               random:       make([]byte, 32),
+               cipherSuite:  TLS_RSA_WITH_AES_128_GCM_SHA256,
+               alpnProtocol: "how-about-this",
+       }
+       serverHelloBytes := serverHello.marshal()
+
+       s.Write([]byte{
+               byte(recordTypeHandshake),
+               byte(VersionTLS12 >> 8),
+               byte(VersionTLS12 & 0xff),
+               byte(len(serverHelloBytes) >> 8),
+               byte(len(serverHelloBytes)),
+       })
+       s.Write(serverHelloBytes)
+       s.Close()
+
+       if err := <-errChan; !strings.Contains(err.Error(), "server selected unadvertised ALPN protocol") {
+               t.Fatalf("Expected error about unconfigured cipher suite but got %q", err)
+       }
+}
+
 // sctsBase64 contains data from `openssl s_client -serverinfo 18 -connect ritter.vg:443`
 const sctsBase64 = "ABIBaQFnAHUApLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFHl5nuFgAABAMARjBEAiAcS4JdlW5nW9sElUv2zvQyPoZ6ejKrGGB03gjaBZFMLwIgc1Qbbn+hsH0RvObzhS+XZhr3iuQQJY8S9G85D9KeGPAAdgBo9pj4H2SCvjqM7rkoHUz8cVFdZ5PURNEKZ6y7T0/7xAAAAUeX4bVwAAAEAwBHMEUCIDIhFDgG2HIuADBkGuLobU5a4dlCHoJLliWJ1SYT05z6AiEAjxIoZFFPRNWMGGIjskOTMwXzQ1Wh2e7NxXE1kd1J0QsAdgDuS723dc5guuFCaR+r4Z5mow9+X7By2IMAxHuJeqj9ywAAAUhcZIqHAAAEAwBHMEUCICmJ1rBT09LpkbzxtUC+Hi7nXLR0J+2PmwLp+sJMuqK+AiEAr0NkUnEVKVhAkccIFpYDqHOlZaBsuEhWWrYpg2RtKp0="
 
@@ -1528,7 +1580,7 @@ func testVerifyConnection(t *testing.T, version uint16) {
                                        }
                                        if c.DidResume {
                                                return nil
-                                               // The SCTs and OCSP Responce are dropped on resumption.
+                                               // The SCTs and OCSP Response are dropped on resumption.
                                                // See http://golang.org/issue/39075.
                                        }
                                        if len(c.OCSPResponse) == 0 {
@@ -1569,7 +1621,7 @@ func testVerifyConnection(t *testing.T, version uint16) {
                                        }
                                        if c.DidResume {
                                                return nil
-                                               // The SCTs and OCSP Responce are dropped on resumption.
+                                               // The SCTs and OCSP Response are dropped on resumption.
                                                // See http://golang.org/issue/39075.
                                        }
                                        if len(c.OCSPResponse) == 0 {
@@ -1619,7 +1671,7 @@ func testVerifyConnection(t *testing.T, version uint16) {
                                        }
                                        if c.DidResume {
                                                return nil
-                                               // The SCTs and OCSP Responce are dropped on resumption.
+                                               // The SCTs and OCSP Response are dropped on resumption.
                                                // See http://golang.org/issue/39075.
                                        }
                                        if len(c.OCSPResponse) == 0 {
@@ -2511,3 +2563,35 @@ func testResumptionKeepsOCSPAndSCT(t *testing.T, ver uint16) {
                        serverConfig.Certificates[0].SignedCertificateTimestamps, ccs.SignedCertificateTimestamps)
        }
 }
+
+// TestClientHandshakeContextCancellation tests that cancelling
+// the context given to the client side conn.HandshakeContext
+// interrupts the in-progress handshake.
+func TestClientHandshakeContextCancellation(t *testing.T) {
+       c, s := localPipe(t)
+       ctx, cancel := context.WithCancel(context.Background())
+       unblockServer := make(chan struct{})
+       defer close(unblockServer)
+       go func() {
+               cancel()
+               <-unblockServer
+               _ = s.Close()
+       }()
+       cli := Client(c, testConfig)
+       // Initiates client side handshake, which will block until the client hello is read
+       // by the server, unless the cancellation works.
+       err := cli.HandshakeContext(ctx)
+       if err == nil {
+               t.Fatal("Client handshake did not error when the context was canceled")
+       }
+       if err != context.Canceled {
+               t.Errorf("Unexpected client handshake error: %v", err)
+       }
+       if runtime.GOARCH == "wasm" {
+               t.Skip("conn.Close does not error as expected when called multiple times on WASM")
+       }
+       err = cli.Close()
+       if err == nil {
+               t.Error("Client connection was not closed when the context was canceled")
+       }
+}
index daa5d97fd35548c4871a2f7f7ffa3b6e5da013a7..eb59ac90d11c2d8cc325889c5deb7f7c7bb3df46 100644 (file)
@@ -6,6 +6,7 @@ package tls
 
 import (
        "bytes"
+       "context"
        "crypto"
        "crypto/hmac"
        "crypto/rsa"
@@ -17,6 +18,7 @@ import (
 
 type clientHandshakeStateTLS13 struct {
        c           *Conn
+       ctx         context.Context
        serverHello *serverHelloMsg
        hello       *clientHelloMsg
        ecdheParams ecdheParameters
@@ -394,17 +396,11 @@ func (hs *clientHandshakeStateTLS13) readServerParameters() error {
        }
        hs.transcript.Write(encryptedExtensions.marshal())
 
-       if encryptedExtensions.alpnProtocol != "" {
-               if len(hs.hello.alpnProtocols) == 0 {
-                       c.sendAlert(alertUnsupportedExtension)
-                       return errors.New("tls: server advertised unrequested ALPN extension")
-               }
-               if mutualProtocol([]string{encryptedExtensions.alpnProtocol}, hs.hello.alpnProtocols) == "" {
-                       c.sendAlert(alertUnsupportedExtension)
-                       return errors.New("tls: server selected unadvertised ALPN protocol")
-               }
-               c.clientProtocol = encryptedExtensions.alpnProtocol
+       if err := checkALPN(hs.hello.alpnProtocols, encryptedExtensions.alpnProtocol); err != nil {
+               c.sendAlert(alertUnsupportedExtension)
+               return err
        }
+       c.clientProtocol = encryptedExtensions.alpnProtocol
 
        return nil
 }
@@ -555,6 +551,7 @@ func (hs *clientHandshakeStateTLS13) sendClientCertificate() error {
                AcceptableCAs:    hs.certReq.certificateAuthorities,
                SignatureSchemes: hs.certReq.supportedSignatureAlgorithms,
                Version:          c.vers,
+               ctx:              hs.ctx,
        })
        if err != nil {
                return err
index 9c3e0f636ea7b548776ad75bf7ff112c65e7c571..43f30e2fefd4fbec79f49f8e5ad78b51876c6dbe 100644 (file)
@@ -5,6 +5,7 @@
 package tls
 
 import (
+       "context"
        "crypto"
        "crypto/ecdsa"
        "crypto/ed25519"
@@ -23,6 +24,7 @@ import (
 // It's discarded once the handshake has completed.
 type serverHandshakeState struct {
        c            *Conn
+       ctx          context.Context
        clientHello  *clientHelloMsg
        hello        *serverHelloMsg
        suite        *cipherSuite
@@ -37,8 +39,8 @@ type serverHandshakeState struct {
 }
 
 // serverHandshake performs a TLS handshake as a server.
-func (c *Conn) serverHandshake() error {
-       clientHello, err := c.readClientHello()
+func (c *Conn) serverHandshake(ctx context.Context) error {
+       clientHello, err := c.readClientHello(ctx)
        if err != nil {
                return err
        }
@@ -46,6 +48,7 @@ func (c *Conn) serverHandshake() error {
        if c.vers == VersionTLS13 {
                hs := serverHandshakeStateTLS13{
                        c:           c,
+                       ctx:         ctx,
                        clientHello: clientHello,
                }
                return hs.handshake()
@@ -53,6 +56,7 @@ func (c *Conn) serverHandshake() error {
 
        hs := serverHandshakeState{
                c:           c,
+               ctx:         ctx,
                clientHello: clientHello,
        }
        return hs.handshake()
@@ -124,7 +128,7 @@ func (hs *serverHandshakeState) handshake() error {
 }
 
 // readClientHello reads a ClientHello message and selects the protocol version.
-func (c *Conn) readClientHello() (*clientHelloMsg, error) {
+func (c *Conn) readClientHello(ctx context.Context) (*clientHelloMsg, error) {
        msg, err := c.readHandshake()
        if err != nil {
                return nil, err
@@ -138,7 +142,7 @@ func (c *Conn) readClientHello() (*clientHelloMsg, error) {
        var configForClient *Config
        originalConfig := c.config
        if c.config.GetConfigForClient != nil {
-               chi := clientHelloInfo(c, clientHello)
+               chi := clientHelloInfo(ctx, c, clientHello)
                if configForClient, err = c.config.GetConfigForClient(chi); err != nil {
                        c.sendAlert(alertInternalError)
                        return nil, err
@@ -213,14 +217,15 @@ func (hs *serverHandshakeState) processClientHello() error {
                c.serverName = hs.clientHello.serverName
        }
 
-       if len(hs.clientHello.alpnProtocols) > 0 {
-               if selectedProto := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); selectedProto != "" {
-                       hs.hello.alpnProtocol = selectedProto
-                       c.clientProtocol = selectedProto
-               }
+       selectedProto, err := negotiateALPN(c.config.NextProtos, hs.clientHello.alpnProtocols)
+       if err != nil {
+               c.sendAlert(alertNoApplicationProtocol)
+               return err
        }
+       hs.hello.alpnProtocol = selectedProto
+       c.clientProtocol = selectedProto
 
-       hs.cert, err = c.config.getCertificate(clientHelloInfo(c, hs.clientHello))
+       hs.cert, err = c.config.getCertificate(clientHelloInfo(hs.ctx, c, hs.clientHello))
        if err != nil {
                if err == errNoCertificates {
                        c.sendAlert(alertUnrecognizedName)
@@ -270,6 +275,34 @@ func (hs *serverHandshakeState) processClientHello() error {
        return nil
 }
 
+// negotiateALPN picks a shared ALPN protocol that both sides support in server
+// preference order. If ALPN is not configured or the peer doesn't support it,
+// it returns "" and no error.
+func negotiateALPN(serverProtos, clientProtos []string) (string, error) {
+       if len(serverProtos) == 0 || len(clientProtos) == 0 {
+               return "", nil
+       }
+       var http11fallback bool
+       for _, s := range serverProtos {
+               for _, c := range clientProtos {
+                       if s == c {
+                               return s, nil
+                       }
+                       if s == "h2" && c == "http/1.1" {
+                               http11fallback = true
+                       }
+               }
+       }
+       // As a special case, let http/1.1 clients connect to h2 servers as if they
+       // didn't support ALPN. We used not to enforce protocol overlap, so over
+       // time a number of HTTP servers were configured with only "h2", but
+       // expected to accept connections from "http/1.1" clients. See Issue 46310.
+       if http11fallback {
+               return "", nil
+       }
+       return "", fmt.Errorf("tls: client requested unsupported application protocols (%s)", clientProtos)
+}
+
 // supportsECDHE returns whether ECDHE key exchanges can be used with this
 // pre-TLS 1.3 client.
 func supportsECDHE(c *Config, supportedCurves []CurveID, supportedPoints []uint8) bool {
@@ -295,30 +328,23 @@ func supportsECDHE(c *Config, supportedCurves []CurveID, supportedPoints []uint8
 func (hs *serverHandshakeState) pickCipherSuite() error {
        c := hs.c
 
-       var preferenceList, supportedList []uint16
-       if c.config.PreferServerCipherSuites {
-               preferenceList = c.config.cipherSuites()
-               supportedList = hs.clientHello.cipherSuites
-
-               // If the client does not seem to have hardware support for AES-GCM,
-               // and the application did not specify a cipher suite preference order,
-               // prefer other AEAD ciphers even if we prioritized AES-GCM ciphers
-               // by default.
-               if c.config.CipherSuites == nil && !aesgcmPreferred(hs.clientHello.cipherSuites) {
-                       preferenceList = deprioritizeAES(preferenceList)
-               }
-       } else {
-               preferenceList = hs.clientHello.cipherSuites
-               supportedList = c.config.cipherSuites()
+       preferenceOrder := cipherSuitesPreferenceOrder
+       if !hasAESGCMHardwareSupport || !aesgcmPreferred(hs.clientHello.cipherSuites) {
+               preferenceOrder = cipherSuitesPreferenceOrderNoAES
+       }
 
-               // If we don't have hardware support for AES-GCM, prefer other AEAD
-               // ciphers even if the client prioritized AES-GCM.
-               if !hasAESGCMHardwareSupport {
-                       preferenceList = deprioritizeAES(preferenceList)
+       configCipherSuites := c.config.cipherSuites()
+       preferenceList := make([]uint16, 0, len(configCipherSuites))
+       for _, suiteID := range preferenceOrder {
+               for _, id := range configCipherSuites {
+                       if id == suiteID {
+                               preferenceList = append(preferenceList, id)
+                               break
+                       }
                }
        }
 
-       hs.suite = selectCipherSuite(preferenceList, supportedList, hs.cipherSuiteOk)
+       hs.suite = selectCipherSuite(preferenceList, hs.clientHello.cipherSuites, hs.cipherSuiteOk)
        if hs.suite == nil {
                c.sendAlert(alertHandshakeFailure)
                return errors.New("tls: no cipher suite supported by both client and server")
@@ -828,7 +854,7 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error {
        return nil
 }
 
-func clientHelloInfo(c *Conn, clientHello *clientHelloMsg) *ClientHelloInfo {
+func clientHelloInfo(ctx context.Context, c *Conn, clientHello *clientHelloMsg) *ClientHelloInfo {
        supportedVersions := clientHello.supportedVersions
        if len(clientHello.supportedVersions) == 0 {
                supportedVersions = supportedVersionsFromMax(clientHello.vers)
@@ -844,5 +870,6 @@ func clientHelloInfo(c *Conn, clientHello *clientHelloMsg) *ClientHelloInfo {
                SupportedVersions: supportedVersions,
                Conn:              c.conn,
                config:            c.config,
+               ctx:               ctx,
        }
 }
index d6bf9e439b01c3e50b509085675ddf2a5953e60a..f61b4c88efaf1d270c00d9bafc7831e4db6bf124 100644 (file)
@@ -6,6 +6,7 @@ package tls
 
 import (
        "bytes"
+       "context"
        "crypto"
        "crypto/elliptic"
        "crypto/x509"
@@ -17,6 +18,7 @@ import (
        "os"
        "os/exec"
        "path/filepath"
+       "runtime"
        "strings"
        "testing"
        "time"
@@ -38,10 +40,12 @@ func testClientHelloFailure(t *testing.T, serverConfig *Config, m handshakeMessa
                cli.writeRecord(recordTypeHandshake, m.marshal())
                c.Close()
        }()
+       ctx := context.Background()
        conn := Server(s, serverConfig)
-       ch, err := conn.readClientHello()
+       ch, err := conn.readClientHello(ctx)
        hs := serverHandshakeState{
                c:           conn,
+               ctx:         ctx,
                clientHello: ch,
        }
        if err == nil {
@@ -393,30 +397,30 @@ func TestVersion(t *testing.T) {
 
 func TestCipherSuitePreference(t *testing.T) {
        serverConfig := &Config{
-               CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA},
+               CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_AES_128_GCM_SHA256,
+                       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
                Certificates: testConfig.Certificates,
-               MaxVersion:   VersionTLS11,
+               MaxVersion:   VersionTLS12,
+               GetConfigForClient: func(chi *ClientHelloInfo) (*Config, error) {
+                       if chi.CipherSuites[0] != TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 {
+                               t.Error("the advertised order should not depend on Config.CipherSuites")
+                       }
+                       if len(chi.CipherSuites) != 2+len(defaultCipherSuitesTLS13) {
+                               t.Error("the advertised TLS 1.2 suites should be filtered by Config.CipherSuites")
+                       }
+                       return nil, nil
+               },
        }
        clientConfig := &Config{
-               CipherSuites:       []uint16{TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_RC4_128_SHA},
+               CipherSuites:       []uint16{TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
                InsecureSkipVerify: true,
        }
        state, _, err := testHandshake(t, clientConfig, serverConfig)
        if err != nil {
                t.Fatalf("handshake failed: %s", err)
        }
-       if state.CipherSuite != TLS_RSA_WITH_AES_128_CBC_SHA {
-               // By default the server should use the client's preference.
-               t.Fatalf("Client's preference was not used, got %x", state.CipherSuite)
-       }
-
-       serverConfig.PreferServerCipherSuites = true
-       state, _, err = testHandshake(t, clientConfig, serverConfig)
-       if err != nil {
-               t.Fatalf("handshake failed: %s", err)
-       }
-       if state.CipherSuite != TLS_RSA_WITH_RC4_128_SHA {
-               t.Fatalf("Server's preference was not used, got %x", state.CipherSuite)
+       if state.CipherSuite != TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 {
+               t.Error("the preference order should not depend on Config.CipherSuites")
        }
 }
 
@@ -916,13 +920,48 @@ func TestHandshakeServerALPNNoMatch(t *testing.T) {
                name: "ALPN-NoMatch",
                // Note that this needs OpenSSL 1.0.2 because that is the first
                // version that supports the -alpn flag.
+               command:                       []string{"openssl", "s_client", "-alpn", "proto2,proto1", "-cipher", "ECDHE-RSA-CHACHA20-POLY1305", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256"},
+               config:                        config,
+               expectHandshakeErrorIncluding: "client requested unsupported application protocol",
+       }
+       runServerTestTLS12(t, test)
+       runServerTestTLS13(t, test)
+}
+
+func TestHandshakeServerALPNNotConfigured(t *testing.T) {
+       config := testConfig.Clone()
+       config.NextProtos = nil
+
+       test := &serverTest{
+               name: "ALPN-NotConfigured",
+               // Note that this needs OpenSSL 1.0.2 because that is the first
+               // version that supports the -alpn flag.
                command: []string{"openssl", "s_client", "-alpn", "proto2,proto1", "-cipher", "ECDHE-RSA-CHACHA20-POLY1305", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256"},
                config:  config,
                validate: func(state ConnectionState) error {
-                       // Rather than reject the connection, Go doesn't select
-                       // a protocol when there is no overlap.
                        if state.NegotiatedProtocol != "" {
-                               return fmt.Errorf("Got protocol %q, wanted ''", state.NegotiatedProtocol)
+                               return fmt.Errorf("Got protocol %q, wanted nothing", state.NegotiatedProtocol)
+                       }
+                       return nil
+               },
+       }
+       runServerTestTLS12(t, test)
+       runServerTestTLS13(t, test)
+}
+
+func TestHandshakeServerALPNFallback(t *testing.T) {
+       config := testConfig.Clone()
+       config.NextProtos = []string{"proto1", "h2", "proto2"}
+
+       test := &serverTest{
+               name: "ALPN-Fallback",
+               // Note that this needs OpenSSL 1.0.2 because that is the first
+               // version that supports the -alpn flag.
+               command: []string{"openssl", "s_client", "-alpn", "proto3,http/1.1,proto4", "-cipher", "ECDHE-RSA-CHACHA20-POLY1305", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256"},
+               config:  config,
+               validate: func(state ConnectionState) error {
+                       if state.NegotiatedProtocol != "" {
+                               return fmt.Errorf("Got protocol %q, wanted nothing", state.NegotiatedProtocol)
                        }
                        return nil
                },
@@ -1032,37 +1071,6 @@ func TestHandshakeServerEmptyCertificates(t *testing.T) {
        testClientHelloFailure(t, serverConfig, clientHello, "no certificates")
 }
 
-// TestCipherSuiteCertPreferance ensures that we select an RSA ciphersuite with
-// an RSA certificate and an ECDSA ciphersuite with an ECDSA certificate.
-func TestCipherSuiteCertPreferenceECDSA(t *testing.T) {
-       config := testConfig.Clone()
-       config.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}
-       config.PreferServerCipherSuites = true
-
-       test := &serverTest{
-               name:   "CipherSuiteCertPreferenceRSA",
-               config: config,
-       }
-       runServerTestTLS12(t, test)
-
-       config = testConfig.Clone()
-       config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}
-       config.Certificates = []Certificate{
-               {
-                       Certificate: [][]byte{testECDSACertificate},
-                       PrivateKey:  testECDSAPrivateKey,
-               },
-       }
-       config.BuildNameToCertificate()
-       config.PreferServerCipherSuites = true
-
-       test = &serverTest{
-               name:   "CipherSuiteCertPreferenceECDSA",
-               config: config,
-       }
-       runServerTestTLS12(t, test)
-}
-
 func TestServerResumption(t *testing.T) {
        sessionFilePath := tempFile("")
        defer os.Remove(sessionFilePath)
@@ -1160,7 +1168,7 @@ func TestFallbackSCSV(t *testing.T) {
 func TestHandshakeServerExportKeyingMaterial(t *testing.T) {
        test := &serverTest{
                name:    "ExportKeyingMaterial",
-               command: []string{"openssl", "s_client", "-cipher", "ECDHE-RSA-CHACHA20-POLY1305", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256"},
+               command: []string{"openssl", "s_client", "-cipher", "ECDHE-RSA-AES256-SHA", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256"},
                config:  testConfig.Clone(),
                validate: func(state ConnectionState) error {
                        if km, err := state.ExportKeyingMaterial("test", nil, 42); err != nil {
@@ -1421,9 +1429,11 @@ func TestSNIGivenOnFailure(t *testing.T) {
                c.Close()
        }()
        conn := Server(s, serverConfig)
-       ch, err := conn.readClientHello()
+       ctx := context.Background()
+       ch, err := conn.readClientHello(ctx)
        hs := serverHandshakeState{
                c:           conn,
+               ctx:         ctx,
                clientHello: ch,
        }
        if err == nil {
@@ -1679,15 +1689,14 @@ func TestMultipleCertificates(t *testing.T) {
 
 func TestAESCipherReordering(t *testing.T) {
        currentAESSupport := hasAESGCMHardwareSupport
-       defer func() { hasAESGCMHardwareSupport = currentAESSupport; initDefaultCipherSuites() }()
+       defer func() { hasAESGCMHardwareSupport = currentAESSupport }()
 
        tests := []struct {
-               name                     string
-               clientCiphers            []uint16
-               serverHasAESGCM          bool
-               preferServerCipherSuites bool
-               serverCiphers            []uint16
-               expectedCipher           uint16
+               name            string
+               clientCiphers   []uint16
+               serverHasAESGCM bool
+               serverCiphers   []uint16
+               expectedCipher  uint16
        }{
                {
                        name: "server has hardware AES, client doesn't (pick ChaCha)",
@@ -1696,25 +1705,8 @@ func TestAESCipherReordering(t *testing.T) {
                                TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
                                TLS_RSA_WITH_AES_128_CBC_SHA,
                        },
-                       serverHasAESGCM:          true,
-                       preferServerCipherSuites: true,
-                       expectedCipher:           TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
-               },
-               {
-                       name: "server strongly prefers AES-GCM, client doesn't (pick AES-GCM)",
-                       clientCiphers: []uint16{
-                               TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
-                               TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-                               TLS_RSA_WITH_AES_128_CBC_SHA,
-                       },
-                       serverHasAESGCM:          true,
-                       preferServerCipherSuites: true,
-                       serverCiphers: []uint16{
-                               TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-                               TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
-                               TLS_RSA_WITH_AES_128_CBC_SHA,
-                       },
-                       expectedCipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+                       serverHasAESGCM: true,
+                       expectedCipher:  TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
                },
                {
                        name: "client prefers AES-GCM, server doesn't have hardware AES (pick ChaCha)",
@@ -1758,14 +1750,14 @@ func TestAESCipherReordering(t *testing.T) {
                        expectedCipher:  TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
                },
                {
-                       name: "client prefers AES-GCM and AES-CBC over ChaCha, server doesn't have hardware AES (pick AES-GCM)",
+                       name: "client prefers AES-GCM and AES-CBC over ChaCha, server doesn't have hardware AES (pick ChaCha)",
                        clientCiphers: []uint16{
                                TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
                                TLS_RSA_WITH_AES_128_CBC_SHA,
                                TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
                        },
                        serverHasAESGCM: false,
-                       expectedCipher:  TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+                       expectedCipher:  TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
                },
                {
                        name: "client prefers AES-GCM over ChaCha and sends GREASE, server doesn't have hardware AES (pick ChaCha)",
@@ -1779,7 +1771,7 @@ func TestAESCipherReordering(t *testing.T) {
                        expectedCipher:  TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
                },
                {
-                       name: "client supports multiple AES-GCM, server doesn't have hardware AES and doesn't support ChaCha (pick corrent AES-GCM)",
+                       name: "client supports multiple AES-GCM, server doesn't have hardware AES and doesn't support ChaCha (AES-GCM)",
                        clientCiphers: []uint16{
                                TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
                                TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
@@ -1790,19 +1782,30 @@ func TestAESCipherReordering(t *testing.T) {
                                TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
                                TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
                        },
-                       expectedCipher: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+                       expectedCipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+               },
+               {
+                       name: "client prefers AES-GCM, server has hardware but doesn't support AES (pick ChaCha)",
+                       clientCiphers: []uint16{
+                               TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+                               TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+                               TLS_RSA_WITH_AES_128_CBC_SHA,
+                       },
+                       serverHasAESGCM: true,
+                       serverCiphers: []uint16{
+                               TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+                       },
+                       expectedCipher: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
                },
        }
 
        for _, tc := range tests {
                t.Run(tc.name, func(t *testing.T) {
                        hasAESGCMHardwareSupport = tc.serverHasAESGCM
-                       initDefaultCipherSuites()
                        hs := &serverHandshakeState{
                                c: &Conn{
                                        config: &Config{
-                                               PreferServerCipherSuites: tc.preferServerCipherSuites,
-                                               CipherSuites:             tc.serverCiphers,
+                                               CipherSuites: tc.serverCiphers,
                                        },
                                        vers: VersionTLS12,
                                },
@@ -1827,16 +1830,15 @@ func TestAESCipherReordering(t *testing.T) {
        }
 }
 
-func TestAESCipherReordering13(t *testing.T) {
+func TestAESCipherReorderingTLS13(t *testing.T) {
        currentAESSupport := hasAESGCMHardwareSupport
-       defer func() { hasAESGCMHardwareSupport = currentAESSupport; initDefaultCipherSuites() }()
+       defer func() { hasAESGCMHardwareSupport = currentAESSupport }()
 
        tests := []struct {
-               name                     string
-               clientCiphers            []uint16
-               serverHasAESGCM          bool
-               preferServerCipherSuites bool
-               expectedCipher           uint16
+               name            string
+               clientCiphers   []uint16
+               serverHasAESGCM bool
+               expectedCipher  uint16
        }{
                {
                        name: "server has hardware AES, client doesn't (pick ChaCha)",
@@ -1844,9 +1846,8 @@ func TestAESCipherReordering13(t *testing.T) {
                                TLS_CHACHA20_POLY1305_SHA256,
                                TLS_AES_128_GCM_SHA256,
                        },
-                       serverHasAESGCM:          true,
-                       preferServerCipherSuites: true,
-                       expectedCipher:           TLS_CHACHA20_POLY1305_SHA256,
+                       serverHasAESGCM: true,
+                       expectedCipher:  TLS_CHACHA20_POLY1305_SHA256,
                },
                {
                        name: "neither server nor client have hardware AES (pick ChaCha)",
@@ -1854,37 +1855,25 @@ func TestAESCipherReordering13(t *testing.T) {
                                TLS_CHACHA20_POLY1305_SHA256,
                                TLS_AES_128_GCM_SHA256,
                        },
-                       serverHasAESGCM:          false,
-                       preferServerCipherSuites: true,
-                       expectedCipher:           TLS_CHACHA20_POLY1305_SHA256,
+                       serverHasAESGCM: false,
+                       expectedCipher:  TLS_CHACHA20_POLY1305_SHA256,
                },
                {
-                       name: "client prefers AES, server doesn't have hardware, prefer server ciphers (pick ChaCha)",
+                       name: "client prefers AES, server doesn't have hardware (pick ChaCha)",
                        clientCiphers: []uint16{
                                TLS_AES_128_GCM_SHA256,
                                TLS_CHACHA20_POLY1305_SHA256,
                        },
-                       serverHasAESGCM:          false,
-                       preferServerCipherSuites: true,
-                       expectedCipher:           TLS_CHACHA20_POLY1305_SHA256,
+                       serverHasAESGCM: false,
+                       expectedCipher:  TLS_CHACHA20_POLY1305_SHA256,
                },
                {
-                       name: "client prefers AES and sends GREASE, server doesn't have hardware, prefer server ciphers (pick ChaCha)",
+                       name: "client prefers AES and sends GREASE, server doesn't have hardware (pick ChaCha)",
                        clientCiphers: []uint16{
                                0x0A0A, // GREASE value
                                TLS_AES_128_GCM_SHA256,
                                TLS_CHACHA20_POLY1305_SHA256,
                        },
-                       serverHasAESGCM:          false,
-                       preferServerCipherSuites: true,
-                       expectedCipher:           TLS_CHACHA20_POLY1305_SHA256,
-               },
-               {
-                       name: "client prefers AES, server doesn't (pick ChaCha)",
-                       clientCiphers: []uint16{
-                               TLS_AES_128_GCM_SHA256,
-                               TLS_CHACHA20_POLY1305_SHA256,
-                       },
                        serverHasAESGCM: false,
                        expectedCipher:  TLS_CHACHA20_POLY1305_SHA256,
                },
@@ -1912,13 +1901,10 @@ func TestAESCipherReordering13(t *testing.T) {
        for _, tc := range tests {
                t.Run(tc.name, func(t *testing.T) {
                        hasAESGCMHardwareSupport = tc.serverHasAESGCM
-                       initDefaultCipherSuites()
                        hs := &serverHandshakeStateTLS13{
                                c: &Conn{
-                                       config: &Config{
-                                               PreferServerCipherSuites: tc.preferServerCipherSuites,
-                                       },
-                                       vers: VersionTLS13,
+                                       config: &Config{},
+                                       vers:   VersionTLS13,
                                },
                                clientHello: &clientHelloMsg{
                                        cipherSuites:       tc.clientCiphers,
@@ -1939,3 +1925,104 @@ func TestAESCipherReordering13(t *testing.T) {
                })
        }
 }
+
+// TestServerHandshakeContextCancellation tests that cancelling
+// the context given to the server side conn.HandshakeContext
+// interrupts the in-progress handshake.
+func TestServerHandshakeContextCancellation(t *testing.T) {
+       c, s := localPipe(t)
+       ctx, cancel := context.WithCancel(context.Background())
+       unblockClient := make(chan struct{})
+       defer close(unblockClient)
+       go func() {
+               cancel()
+               <-unblockClient
+               _ = c.Close()
+       }()
+       conn := Server(s, testConfig)
+       // Initiates server side handshake, which will block until a client hello is read
+       // unless the cancellation works.
+       err := conn.HandshakeContext(ctx)
+       if err == nil {
+               t.Fatal("Server handshake did not error when the context was canceled")
+       }
+       if err != context.Canceled {
+               t.Errorf("Unexpected server handshake error: %v", err)
+       }
+       if runtime.GOARCH == "wasm" {
+               t.Skip("conn.Close does not error as expected when called multiple times on WASM")
+       }
+       err = conn.Close()
+       if err == nil {
+               t.Error("Server connection was not closed when the context was canceled")
+       }
+}
+
+// TestHandshakeContextHierarchy tests whether the contexts
+// available to GetClientCertificate and GetCertificate are
+// derived from the context provided to HandshakeContext, and
+// that those contexts are canceled after HandshakeContext has
+// returned.
+func TestHandshakeContextHierarchy(t *testing.T) {
+       c, s := localPipe(t)
+       clientErr := make(chan error, 1)
+       clientConfig := testConfig.Clone()
+       serverConfig := testConfig.Clone()
+       ctx, cancel := context.WithCancel(context.Background())
+       defer cancel()
+       key := struct{}{}
+       ctx = context.WithValue(ctx, key, true)
+       go func() {
+               defer close(clientErr)
+               defer c.Close()
+               var innerCtx context.Context
+               clientConfig.Certificates = nil
+               clientConfig.GetClientCertificate = func(certificateRequest *CertificateRequestInfo) (*Certificate, error) {
+                       if val, ok := certificateRequest.Context().Value(key).(bool); !ok || !val {
+                               t.Errorf("GetClientCertificate context was not child of HandshakeContext")
+                       }
+                       innerCtx = certificateRequest.Context()
+                       return &Certificate{
+                               Certificate: [][]byte{testRSACertificate},
+                               PrivateKey:  testRSAPrivateKey,
+                       }, nil
+               }
+               cli := Client(c, clientConfig)
+               err := cli.HandshakeContext(ctx)
+               if err != nil {
+                       clientErr <- err
+                       return
+               }
+               select {
+               case <-innerCtx.Done():
+               default:
+                       t.Errorf("GetClientCertificate context was not canceled after HandshakeContext returned.")
+               }
+       }()
+       var innerCtx context.Context
+       serverConfig.Certificates = nil
+       serverConfig.ClientAuth = RequestClientCert
+       serverConfig.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) {
+               if val, ok := clientHello.Context().Value(key).(bool); !ok || !val {
+                       t.Errorf("GetClientCertificate context was not child of HandshakeContext")
+               }
+               innerCtx = clientHello.Context()
+               return &Certificate{
+                       Certificate: [][]byte{testRSACertificate},
+                       PrivateKey:  testRSAPrivateKey,
+               }, nil
+       }
+       conn := Server(s, serverConfig)
+       err := conn.HandshakeContext(ctx)
+       if err != nil {
+               t.Errorf("Unexpected server handshake error: %v", err)
+       }
+       select {
+       case <-innerCtx.Done():
+       default:
+               t.Errorf("GetCertificate context was not canceled after HandshakeContext returned.")
+       }
+       if err := <-clientErr; err != nil {
+               t.Errorf("Unexpected client error: %v", err)
+       }
+}
index c2c288aed4325b280f435fcb26239d0d9f49780e..08251b84def7eee0deb1f961c025dbe350856749 100644 (file)
@@ -6,6 +6,7 @@ package tls
 
 import (
        "bytes"
+       "context"
        "crypto"
        "crypto/hmac"
        "crypto/rsa"
@@ -23,6 +24,7 @@ const maxClientPSKIdentities = 5
 
 type serverHandshakeStateTLS13 struct {
        c               *Conn
+       ctx             context.Context
        clientHello     *clientHelloMsg
        hello           *serverHelloMsg
        sentDummyCCS    bool
@@ -147,29 +149,12 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error {
        hs.hello.sessionId = hs.clientHello.sessionId
        hs.hello.compressionMethod = compressionNone
 
-       var preferenceList, supportedList []uint16
-       if c.config.PreferServerCipherSuites {
-               preferenceList = defaultCipherSuitesTLS13()
-               supportedList = hs.clientHello.cipherSuites
-
-               // If the client does not seem to have hardware support for AES-GCM,
-               // prefer other AEAD ciphers even if we prioritized AES-GCM ciphers
-               // by default.
-               if !aesgcmPreferred(hs.clientHello.cipherSuites) {
-                       preferenceList = deprioritizeAES(preferenceList)
-               }
-       } else {
-               preferenceList = hs.clientHello.cipherSuites
-               supportedList = defaultCipherSuitesTLS13()
-
-               // If we don't have hardware support for AES-GCM, prefer other AEAD
-               // ciphers even if the client prioritized AES-GCM.
-               if !hasAESGCMHardwareSupport {
-                       preferenceList = deprioritizeAES(preferenceList)
-               }
+       preferenceList := defaultCipherSuitesTLS13
+       if !hasAESGCMHardwareSupport || !aesgcmPreferred(hs.clientHello.cipherSuites) {
+               preferenceList = defaultCipherSuitesTLS13NoAES
        }
        for _, suiteID := range preferenceList {
-               hs.suite = mutualCipherSuiteTLS13(supportedList, suiteID)
+               hs.suite = mutualCipherSuiteTLS13(hs.clientHello.cipherSuites, suiteID)
                if hs.suite != nil {
                        break
                }
@@ -374,7 +359,7 @@ func (hs *serverHandshakeStateTLS13) pickCertificate() error {
                return c.sendAlert(alertMissingExtension)
        }
 
-       certificate, err := c.config.getCertificate(clientHelloInfo(c, hs.clientHello))
+       certificate, err := c.config.getCertificate(clientHelloInfo(hs.ctx, c, hs.clientHello))
        if err != nil {
                if err == errNoCertificates {
                        c.sendAlert(alertUnrecognizedName)
@@ -565,12 +550,13 @@ func (hs *serverHandshakeStateTLS13) sendServerParameters() error {
 
        encryptedExtensions := new(encryptedExtensionsMsg)
 
-       if len(hs.clientHello.alpnProtocols) > 0 {
-               if selectedProto := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); selectedProto != "" {
-                       encryptedExtensions.alpnProtocol = selectedProto
-                       c.clientProtocol = selectedProto
-               }
+       selectedProto, err := negotiateALPN(c.config.NextProtos, hs.clientHello.alpnProtocols)
+       if err != nil {
+               c.sendAlert(alertNoApplicationProtocol)
+               return err
        }
+       encryptedExtensions.alpnProtocol = selectedProto
+       c.clientProtocol = selectedProto
 
        hs.transcript.Write(encryptedExtensions.marshal())
        if _, err := c.writeRecord(recordTypeHandshake, encryptedExtensions.marshal()); err != nil {
index d9ff9fe948f16f768baa572fda89a9eab87b05c6..9bfb1177f27d04402ae687e2e1365154bbc8a818 100644 (file)
@@ -335,15 +335,9 @@ func TestMain(m *testing.M) {
 }
 
 func runMain(m *testing.M) int {
-       // TLS 1.3 cipher suites preferences are not configurable and change based
-       // on the architecture. Force them to the version with AES acceleration for
-       // test consistency.
-       once.Do(initDefaultCipherSuites)
-       varDefaultCipherSuitesTLS13 = []uint16{
-               TLS_AES_128_GCM_SHA256,
-               TLS_CHACHA20_POLY1305_SHA256,
-               TLS_AES_256_GCM_SHA384,
-       }
+       // Cipher suites preferences change based on the architecture. Force them to
+       // the version without AES acceleration for test consistency.
+       hasAESGCMHardwareSupport = false
 
        // Set up localPipe.
        l, err := net.Listen("tcp", "127.0.0.1:0")
index 72718544ae6bdd04ed005e1e61f7f1b319c06864..19fc6986769f62fdb5eb29ca1c84694b51e8013b 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
 
 package tls
index 7e6534bd465e30c7f2663f73cf40b6d4a86e863d..c28a64f3a8b8c5a2eeae3f62cee7966cf7b7a4d4 100644 (file)
@@ -15,6 +15,25 @@ import (
        "io"
 )
 
+// a keyAgreement implements the client and server side of a TLS key agreement
+// protocol by generating and processing key exchange messages.
+type keyAgreement interface {
+       // On the server side, the first two methods are called in order.
+
+       // In the case that the key agreement protocol doesn't use a
+       // ServerKeyExchange message, generateServerKeyExchange can return nil,
+       // nil.
+       generateServerKeyExchange(*Config, *Certificate, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error)
+       processClientKeyExchange(*Config, *Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error)
+
+       // On the client side, the next two methods are called in order.
+
+       // This method may not be called if the server doesn't send a
+       // ServerKeyExchange message.
+       processServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) error
+       generateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error)
+}
+
 var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message")
 var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message")
 
@@ -67,7 +86,11 @@ func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello
                return nil, nil, err
        }
 
-       encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret)
+       rsaKey, ok := cert.PublicKey.(*rsa.PublicKey)
+       if !ok {
+               return nil, nil, errors.New("tls: server certificate contains incorrect key type for selected ciphersuite")
+       }
+       encrypted, err := rsa.EncryptPKCS1v15(config.rand(), rsaKey, preMasterSecret)
        if err != nil {
                return nil, nil, err
        }
index 9de3f1437b473227fca09728692188d20623d33a..c7fa530b921bc9ebc64a76284451a1bbcfc74550 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 01 00 59 02 00 00  55 03 01 94 1f ba 79 da  |....Y...U.....y.|
-00000010  4b 58 3e 08 2c c5 31 36  a4 7e 32 bf e1 a0 f7 71  |KX>.,.16.~2....q|
-00000020  01 48 63 3c 5f cb 08 7a  25 80 c7 20 35 0c c0 8b  |.Hc<_..z%.. 5...|
-00000030  df 30 fc dc 3d f1 48 96  0d b6 ff a8 cd 35 29 57  |.0..=.H......5)W|
-00000040  7d 3f c2 9d e2 32 b1 c2  4c 05 5e 3b c0 09 00 00  |}?...2..L.^;....|
+00000000  16 03 01 00 59 02 00 00  55 03 01 92 4c b7 e6 07  |....Y...U...L...|
+00000010  09 b4 4a 47 6a 29 c7 79  18 0d 43 37 86 26 21 5a  |..JGj).y..C7.&!Z|
+00000020  25 35 db 5f ae d0 20 0d  85 67 f7 20 75 e5 cb 25  |%5._.. ..g. u..%|
+00000030  4b 5d 95 87 78 00 fc 3f  78 26 e8 77 b5 0d d4 0e  |K]..x..?x&.w....|
+00000040  54 06 66 b4 14 dc 6b db  f2 af f3 2a c0 09 00 00  |T.f...k....*....|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  01 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
 00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
 00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
 00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
 00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
-00000270  2a 16 03 01 00 b5 0c 00  00 b1 03 00 1d 20 1a 74  |*............ .t|
-00000280  c4 96 9e 65 45 9a 0a 01  7c ed 7b 51 01 d8 ba 5b  |...eE...|.{Q...[|
-00000290  3e 2f b1 4b 36 69 e8 47  75 7e 27 be b3 2f 00 8b  |>/.K6i.Gu~'../..|
-000002a0  30 81 88 02 42 01 cb 20  d9 1e ae 05 6f 1f 37 ce  |0...B.. ....o.7.|
-000002b0  dc 38 20 2f 8f 52 9a 92  f6 80 d6 f9 97 99 a5 8b  |.8 /.R..........|
-000002c0  6e 73 0b 95 a4 4e 82 67  bd 1a 34 d9 5c 4e b4 d7  |ns...N.g..4.\N..|
-000002d0  35 e6 45 81 14 23 9c 4e  5a 4c 1b 93 fd 7f 43 18  |5.E..#.NZL....C.|
-000002e0  db 54 4b e0 d1 d3 fa 02  42 00 ab 8e 34 d5 c2 04  |.TK.....B...4...|
-000002f0  d0 a4 44 b1 b3 25 a0 af  c8 80 b3 88 ae da b3 c6  |..D..%..........|
-00000300  4f 57 ae 31 54 c6 d9 ee  4e 21 56 01 cc b9 6a e9  |OW.1T...N!V...j.|
-00000310  e9 7e 62 2a 64 0e a4 a0  79 1e a3 64 52 70 b1 a5  |.~b*d...y..dRp..|
-00000320  19 2c a4 6d 4b 3b a3 63  ed 56 2f 16 03 01 00 0a  |.,.mK;.c.V/.....|
+00000270  2a 16 03 01 00 b5 0c 00  00 b1 03 00 1d 20 d7 b5  |*............ ..|
+00000280  51 8e b5 01 4f 02 2f 43  11 2b de 94 7d 82 e6 49  |Q...O./C.+..}..I|
+00000290  1b a6 ee a0 7f 12 35 a2  3a 62 46 ce 07 25 00 8b  |......5.:bF..%..|
+000002a0  30 81 88 02 42 00 83 45  db 03 db b9 74 ce 77 35  |0...B..E....t.w5|
+000002b0  1b e5 76 18 dc 3a d3 ee  32 18 f3 16 a6 c3 62 be  |..v..:..2.....b.|
+000002c0  46 47 40 80 2d a0 08 c5  1e 5a 4a 42 69 8c ee e5  |FG@.-....ZJBi...|
+000002d0  70 b5 71 30 2f 54 32 54  5f 5b 26 62 e1 81 52 9e  |p.q0/T2T_[&b..R.|
+000002e0  49 70 d4 81 e4 76 f1 02  42 01 70 f6 87 84 bb 58  |Ip...v..B.p....X|
+000002f0  5d e4 a1 72 87 d5 35 53  99 9c 3f 30 2b 80 7e c9  |]..r..5S..?0+.~.|
+00000300  79 eb d8 97 3c 82 ff 37  a5 8d 36 bc 27 c1 51 58  |y...<..7..6.'.QX|
+00000310  e6 2a 48 05 bf 9b a4 a5  b1 7f 77 b8 d9 3e 37 c6  |.*H.......w..>7.|
+00000320  67 ad ef 8c 72 ea f6 ba  bb af 00 16 03 01 00 0a  |g...r...........|
 00000330  0d 00 00 06 03 01 02 40  00 00 16 03 01 00 04 0e  |.......@........|
 00000340  00 00 00                                          |...|
 >>> Flow 3 (client to server)
 00000200  e4 fa cc b1 8a ce e2 23  a0 87 f0 e1 67 51 eb 16  |.......#....gQ..|
 00000210  03 01 00 25 10 00 00 21  20 2f e5 7d a3 47 cd 62  |...%...! /.}.G.b|
 00000220  43 15 28 da ac 5f bb 29  07 30 ff f6 84 af c4 cf  |C.(.._.).0......|
-00000230  c2 ed 90 99 5f 58 cb 3b  74 16 03 01 00 90 0f 00  |...._X.;t.......|
-00000240  00 8c 00 8a 30 81 87 02  42 01 89 0f 43 df a8 34  |....0...B...C..4|
-00000250  dd d7 c9 d4 2b 8d ec 29  77 7b 64 d0 0e 8c e8 2b  |....+..)w{d....+|
-00000260  e3 25 1c ed 0a 1b 05 e0  66 42 37 c0 e6 fa 3e 81  |.%......fB7...>.|
-00000270  ec e1 06 99 f4 62 3f ea  55 79 ae 68 56 9e e3 3c  |.....b?.Uy.hV..<|
-00000280  83 ba 9b 1c 65 b9 eb a6  e7 f7 4e 02 41 61 2c 52  |....e.....N.Aa,R|
-00000290  4c 48 92 b0 93 d8 31 58  c3 90 b0 e3 7d 55 94 fc  |LH....1X....}U..|
-000002a0  70 bf 18 42 51 73 d0 45  17 2e 0e 00 b0 12 76 0d  |p..BQs.E......v.|
-000002b0  35 78 cb fd 34 60 36 ff  ed 19 ef 0a 1e 21 cc 4c  |5x..4`6......!.L|
-000002c0  9a ff a0 f7 cf 72 03 cd  00 bb 73 0d 1d e5 14 03  |.....r....s.....|
-000002d0  01 00 01 01 16 03 01 00  30 69 76 1f 5b 81 5f 62  |........0iv.[._b|
-000002e0  cf d5 d9 2c 19 71 80 d0  2a 97 8a 89 21 7f 6d 02  |...,.q..*...!.m.|
-000002f0  b6 01 a4 ed fe 18 9f 34  ae 95 f6 a1 29 0b 9a 1c  |.......4....)...|
-00000300  04 b6 ce c7 d1 0c 5a b5  3f                       |......Z.?|
+00000230  c2 ed 90 99 5f 58 cb 3b  74 16 03 01 00 91 0f 00  |...._X.;t.......|
+00000240  00 8d 00 8b 30 81 88 02  42 01 f0 c3 b2 6e e2 a3  |....0...B....n..|
+00000250  cd 76 02 7a d5 b5 66 fa  b6 66 4e 4b a0 17 d6 bd  |.v.z..f..fNK....|
+00000260  ec f6 8c 1f f9 b4 32 18  a9 ba 66 a8 67 a4 fa c8  |......2...f.g...|
+00000270  f7 73 5f 22 fb f2 22 e2  4d a1 f6 30 a2 55 76 51  |.s_"..".M..0.UvQ|
+00000280  b7 61 7d 13 68 0a 89 9d  34 31 46 02 42 01 fa 8b  |.a}.h...41F.B...|
+00000290  61 f6 91 8e 88 ca 84 e6  33 e0 da 92 7e ee 21 1c  |a.......3...~.!.|
+000002a0  df 47 c2 5d 07 d8 ae 1b  04 58 f9 50 16 13 74 ea  |.G.].....X.P..t.|
+000002b0  04 cc 18 2d 2b 9a 08 89  24 e8 b8 01 bb c6 84 6c  |...-+...$......l|
+000002c0  e6 9a c6 8a 44 74 1c 3a  79 0c e9 3c 11 ba 1b 14  |....Dt.:y..<....|
+000002d0  03 01 00 01 01 16 03 01  00 30 1d 4b df 00 de 1c  |.........0.K....|
+000002e0  b5 30 7b ea 64 a0 09 89  8c c5 be fc 9b 07 7e 45  |.0{.d.........~E|
+000002f0  27 00 e7 78 da 3e a3 04  97 87 b0 c2 17 32 01 91  |'..x.>.......2..|
+00000300  6e 66 7b dd 9e 28 bc cc  66 65                    |nf{..(..fe|
 >>> Flow 4 (server to client)
-00000000  14 03 01 00 01 01 16 03  01 00 30 7d 4b fc 73 20  |..........0}K.s |
-00000010  e4 ac c4 39 15 79 e3 89  e1 24 ce 28 30 e5 f1 87  |...9.y...$.(0...|
-00000020  cd c0 cc 39 a8 77 3b 06  a5 f9 b0 a1 3d 54 53 3b  |...9.w;.....=TS;|
-00000030  53 ec ac b2 ea 24 1b 2d  6a ef c3                 |S....$.-j..|
+00000000  14 03 01 00 01 01 16 03  01 00 30 51 68 ca 97 63  |..........0Qh..c|
+00000010  c6 c0 24 1c 87 20 70 ac  f7 47 16 45 44 17 cc 92  |..$.. p..G.ED...|
+00000020  b3 6d 8b fa d1 3c b8 10  d7 da e4 a7 35 3c a2 d0  |.m...<......5<..|
+00000030  da 4b 50 e4 89 94 4b bc  20 6b e3                 |.KP...K. k.|
 >>> Flow 5 (client to server)
-00000000  17 03 01 00 20 9d 57 d2  4b 5b 7e 7d 7c 28 f7 8e  |.... .W.K[~}|(..|
-00000010  00 0a b6 1c 3c 6b df 4d  06 c0 f8 db 86 2e 8f 8e  |....<k.M........|
-00000020  28 a9 ab 6c c2 17 03 01  00 20 b4 4e cc 55 14 1c  |(..l..... .N.U..|
-00000030  64 a4 3d 69 1a dc 3b 12  8e d8 15 f2 31 3a 71 1f  |d.=i..;.....1:q.|
-00000040  eb fe c3 b3 22 f7 2c 6e  01 e9 15 03 01 00 20 2a  |....".,n...... *|
-00000050  2e 34 ca 96 e5 a3 a0 53  c4 0c e2 0a b1 14 a3 c8  |.4.....S........|
-00000060  a5 db 72 09 31 25 11 11  2f ce 61 3a 55 48 0c     |..r.1%../.a:UH.|
+00000000  17 03 01 00 20 fc fa 90  90 d0 51 0d 35 0f 6a 6d  |.... .....Q.5.jm|
+00000010  c2 32 ec 92 46 9f d7 e9  66 37 02 2a f6 c6 2e e2  |.2..F...f7.*....|
+00000020  13 aa fa fa d3 17 03 01  00 20 45 a9 36 19 7d a8  |......... E.6.}.|
+00000030  44 4c 8b aa 4e 47 c8 79  0c 97 a5 20 fa 6f 1f f7  |DL..NG.y... .o..|
+00000040  d3 bc d7 6d c2 67 23 c8  d6 05 15 03 01 00 20 f1  |...m.g#....... .|
+00000050  f1 ed f9 fc c2 f6 61 c8  42 9d c9 8a b0 d0 de d3  |......a.B.......|
+00000060  42 c7 04 64 eb 9e eb 58  3b c3 7d 0d 4d 16 d4     |B..d...X;.}.M..|
index 754b76ece9549237d32233dac175c2fb48d6c2e6..81e519192573cfac6f9b75d521cd0ffcc80a8166 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 01 00 59 02 00 00  55 03 01 97 0c 7e fc 7f  |....Y...U....~..|
-00000010  96 47 02 21 a7 19 45 a5  79 5c 5e fc c2 15 b3 fa  |.G.!..E.y\^.....|
-00000020  84 98 7d 67 65 c8 48 58  a1 5d 67 20 ad 2a c6 b3  |..}ge.HX.]g .*..|
-00000030  a4 17 82 12 4a c5 97 af  12 6b 7d f6 9e 49 f1 38  |....J....k}..I.8|
-00000040  d0 56 76 bc 81 23 ad 3a  3e 7f bc 2d c0 13 00 00  |.Vv..#.:>..-....|
+00000000  16 03 01 00 59 02 00 00  55 03 01 ca 72 6a a1 69  |....Y...U...rj.i|
+00000010  18 a4 f8 76 4a c3 5c e8  d5 c1 fb 06 c6 9a 14 67  |...vJ.\........g|
+00000020  ce e4 f6 52 67 ab 64 48  28 5a 63 20 55 ea ff 87  |...Rg.dH(Zc U...|
+00000030  5a 78 5c cb 21 af 83 a5  ed 1b d3 2c 39 81 e5 ca  |Zx\.!......,9...|
+00000040  63 d2 5c 57 27 1d d0 f9  41 40 43 b0 c0 13 00 00  |c.\W'...A@C.....|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  01 02 59 0b 00 02 55 00  02 52 00 02 4f 30 82 02  |..Y...U..R..O0..|
 00000070  4b 30 82 01 b4 a0 03 02  01 02 02 09 00 e8 f0 9d  |K0..............|
 00000290  77 8d 0c 1c f1 0f a1 d8  40 83 61 c9 4c 72 2b 9d  |w.......@.a.Lr+.|
 000002a0  ae db 46 06 06 4d f4 c1  b3 3e c0 d1 bd 42 d4 db  |..F..M...>...B..|
 000002b0  fe 3d 13 60 84 5c 21 d3  3b e9 fa e7 16 03 01 00  |.=.`.\!.;.......|
-000002c0  aa 0c 00 00 a6 03 00 1d  20 a4 24 f7 67 e3 da fa  |........ .$.g...|
-000002d0  10 33 95 b4 46 00 c0 3c  cd 74 12 e4 a3 3b 01 70  |.3..F..<.t...;.p|
-000002e0  fb 98 01 9a e9 2d d0 18  7b 00 80 ce c5 7b 4b 87  |.....-..{....{K.|
-000002f0  cd bc 5d 63 09 7e d4 ce  09 53 7a 1b e5 b4 10 54  |..]c.~...Sz....T|
-00000300  89 52 ac 82 9c 78 88 ed  e8 1a 8c 3a 7a 2c 9a c5  |.R...x.....:z,..|
-00000310  2b 97 1c 79 43 bd b1 ee  93 6f 4c 4d fc 3c 47 91  |+..yC....oLM.<G.|
-00000320  a6 ac ad be a9 39 12 98  40 f7 6a a3 e7 21 76 90  |.....9..@.j..!v.|
-00000330  c9 80 2b bc 80 3f 7e 60  59 7d cd 38 84 a8 53 2a  |..+..?~`Y}.8..S*|
-00000340  92 24 08 8f 84 da cd 9a  86 80 10 05 8f 1b fd 86  |.$..............|
-00000350  93 b6 ef 13 70 e5 6a d5  0e a5 bf 80 bf 50 a8 d4  |....p.j......P..|
-00000360  87 99 b8 d6 f0 4f 45 d5  e6 8b e1 16 03 01 00 0a  |.....OE.........|
+000002c0  aa 0c 00 00 a6 03 00 1d  20 e8 a5 9c e4 73 3d 75  |........ ....s=u|
+000002d0  0c 3e f2 de 21 9c 0f 91  b4 fd 94 f0 27 f6 d9 7d  |.>..!.......'..}|
+000002e0  cd 0c 4c 50 b0 47 db dd  12 00 80 04 c0 be d5 bb  |..LP.G..........|
+000002f0  e8 e2 a2 2e d9 2e 75 fa  b6 07 d0 f7 75 52 fb 2f  |......u.....uR./|
+00000300  50 cd 43 68 bd 42 11 6d  d6 9f a3 d1 00 fd a9 14  |P.Ch.B.m........|
+00000310  0c 2a dd 76 ea 73 21 52  00 3a 83 cf d7 07 c7 bd  |.*.v.s!R.:......|
+00000320  78 21 ce 35 80 b3 06 22  f1 96 a7 20 41 f8 aa 61  |x!.5..."... A..a|
+00000330  94 b4 77 d4 d9 92 f2 66  c5 1c d1 82 f3 b9 e2 9d  |..w....f........|
+00000340  a9 30 1c e2 4e ec 0d 32  3d 0d 61 22 c8 e5 95 9f  |.0..N..2=.a"....|
+00000350  cf 3e fc a8 c5 c3 f8 45  45 29 ea a7 e7 b7 a6 17  |.>.....EE)......|
+00000360  9e 5f 83 d4 b3 f0 da 31  73 94 f2 16 03 01 00 0a  |._.....1s.......|
 00000370  0d 00 00 06 03 01 02 40  00 00 16 03 01 00 04 0e  |.......@........|
 00000380  00 00 00                                          |...|
 >>> Flow 3 (client to server)
 00000210  03 01 00 25 10 00 00 21  20 2f e5 7d a3 47 cd 62  |...%...! /.}.G.b|
 00000220  43 15 28 da ac 5f bb 29  07 30 ff f6 84 af c4 cf  |C.(.._.).0......|
 00000230  c2 ed 90 99 5f 58 cb 3b  74 16 03 01 00 91 0f 00  |...._X.;t.......|
-00000240  00 8d 00 8b 30 81 88 02  42 01 71 f3 c4 3a 85 08  |....0...B.q..:..|
-00000250  3b 18 26 48 5c 3f c3 8a  4f e9 d7 29 48 59 1a 35  |;.&H\?..O..)HY.5|
-00000260  ee b3 0d 5e 29 03 1d 34  95 0e 40 73 85 13 14 d0  |...^)..4..@s....|
-00000270  fb fb 96 77 21 fb d8 43  d7 e2 bf 2c 95 7b 75 5d  |...w!..C...,.{u]|
-00000280  59 15 81 71 d2 b6 82 96  d9 cc 78 02 42 01 d3 51  |Y..q......x.B..Q|
-00000290  af 25 d0 f8 a4 e2 e7 8e  7e 46 56 53 8f d1 09 f6  |.%......~FVS....|
-000002a0  76 88 5a 42 83 89 92 7b  c7 e4 40 9c 3d 05 ac 43  |v.ZB...{..@.=..C|
-000002b0  bf 6e 24 14 fe 36 f8 43  a6 90 8e a1 bd e2 92 84  |.n$..6.C........|
-000002c0  60 e3 92 34 1c 7b 53 d5  57 6d 23 32 12 a8 23 14  |`..4.{S.Wm#2..#.|
-000002d0  03 01 00 01 01 16 03 01  00 30 6f 06 c7 84 fa 7f  |.........0o.....|
-000002e0  c9 66 a9 6f 26 37 45 db  42 c8 8f 63 c3 5b 05 07  |.f.o&7E.B..c.[..|
-000002f0  ef 07 41 be 71 60 35 d3  16 8f 92 f6 89 cb c7 dc  |..A.q`5.........|
-00000300  4e 45 61 99 31 45 66 40  36 86                    |NEa.1Ef@6.|
+00000240  00 8d 00 8b 30 81 88 02  42 00 9a b9 f6 98 e3 ed  |....0...B.......|
+00000250  ed 0d a3 0e 54 51 9f 73  d4 87 40 4e a9 39 4b 2d  |....TQ.s..@N.9K-|
+00000260  2a b9 4d 8d e3 46 c3 b6  39 f2 ca a9 c9 0f 79 c1  |*.M..F..9.....y.|
+00000270  0c 90 6f de 58 97 72 fc  a8 c1 4c 12 aa a4 85 57  |..o.X.r...L....W|
+00000280  50 7c a0 02 8a 12 c5 80  aa b6 39 02 42 00 9c b7  |P|........9.B...|
+00000290  95 b4 04 83 5b 3a e1 ac  da 78 86 11 f5 30 75 4a  |....[:...x...0uJ|
+000002a0  25 67 6c fd ef 5a d8 56  d3 60 93 cf 65 07 2b 1f  |%gl..Z.V.`..e.+.|
+000002b0  a9 40 a8 ba cd 0e 41 2d  10 43 a4 61 93 b7 0a 11  |.@....A-.C.a....|
+000002c0  78 d1 72 2b 20 07 49 5a  76 02 17 57 87 78 c7 14  |x.r+ .IZv..W.x..|
+000002d0  03 01 00 01 01 16 03 01  00 30 93 de 1b 64 0e 56  |.........0...d.V|
+000002e0  d9 a8 da f7 37 cb ac ac  3e f5 e2 f9 87 19 f2 79  |....7...>......y|
+000002f0  24 76 19 a4 a2 41 d6 9e  7d ca aa 3e 1d d7 22 dd  |$v...A..}..>..".|
+00000300  05 aa dd 74 03 db fd a2  de ee                    |...t......|
 >>> Flow 4 (server to client)
-00000000  14 03 01 00 01 01 16 03  01 00 30 d3 83 ac 08 7f  |..........0.....|
-00000010  a1 91 51 7c b7 99 6f 24  cd b1 cd 31 7b 12 20 47  |..Q|..o$...1{. G|
-00000020  66 08 22 f6 28 ea 81 fe  92 b5 c8 40 60 bc 5b 19  |f.".(......@`.[.|
-00000030  e0 2b d1 26 fd 4c 12 22  c5 13 9a                 |.+.&.L."...|
+00000000  14 03 01 00 01 01 16 03  01 00 30 4d 4f d6 67 05  |..........0MO.g.|
+00000010  32 8c 16 cb 19 35 b3 b9  02 d8 5e 24 b6 c8 b7 3a  |2....5....^$...:|
+00000020  17 34 98 77 e1 73 e0 cd  a9 30 a8 15 60 8c f4 9a  |.4.w.s...0..`...|
+00000030  dc cf 7a fd 86 85 1c 2b  33 21 e8                 |..z....+3!.|
 >>> Flow 5 (client to server)
-00000000  17 03 01 00 20 79 06 89  7e e0 17 9a e3 dc 4c ee  |.... y..~.....L.|
-00000010  70 63 13 bc 27 f5 43 fa  f8 90 49 d9 89 43 7a 15  |pc..'.C...I..Cz.|
-00000020  d4 e2 a8 e6 3e 17 03 01  00 20 ea 84 0e 21 62 d5  |....>.... ...!b.|
-00000030  ee 26 5e fc 3e 0c 83 3b  91 01 c4 a7 8e 9b c4 1a  |.&^.>..;........|
-00000040  86 f8 a0 44 21 44 2f 31  cf a1 15 03 01 00 20 c6  |...D!D/1...... .|
-00000050  11 f1 65 ea f3 39 d1 d2  ac 95 1f 81 36 ae db b1  |..e..9......6...|
-00000060  88 a8 42 25 86 ec 1b c1  7e 12 60 a9 6b 7f 66     |..B%....~.`.k.f|
+00000000  17 03 01 00 20 b8 c5 17  b7 92 d8 93 7a b2 fd 4f  |.... .......z..O|
+00000010  15 d1 db b9 47 54 00 a0  f6 77 92 03 a8 89 e5 ba  |....GT...w......|
+00000020  cc eb d9 bd 27 17 03 01  00 20 57 d5 9a f6 36 b2  |....'.... W...6.|
+00000030  57 ba cd 64 77 36 b9 74  fb bd 95 51 03 61 e8 45  |W..dw6.t...Q.a.E|
+00000040  cb b8 35 f0 05 17 b3 08  c6 cb 15 03 01 00 20 28  |..5........... (|
+00000050  43 03 ab 3f e2 f5 d0 33  4c 7f 50 a4 ee 7b 46 e6  |C..?...3L.P..{F.|
+00000060  12 76 d0 fd c3 99 5c 63  a4 04 ea 4b e3 bd 99     |.v....\c...K...|
index 641ab1bd156109914a49dee46d5c2f761bdf2c82..3ee661ecec517894e77ea2e386f2fbf831e3648d 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 01 00 59 02 00 00  55 03 01 3b 4c b9 76 d2  |....Y...U..;L.v.|
-00000010  c3 d1 ea 81 71 1a 10 e1  b1 69 5c 54 c2 df 17 0a  |....q....i\T....|
-00000020  de 41 cb d1 69 c3 9a da  90 fd 25 20 1e 02 11 16  |.A..i.....% ....|
-00000030  ab 66 13 56 3d 94 00 a9  80 7c d8 57 12 99 1c 5f  |.f.V=....|.W..._|
-00000040  7a b2 02 8c 23 f3 76 b8  59 5e 16 dd c0 09 00 00  |z...#.v.Y^......|
+00000000  16 03 01 00 59 02 00 00  55 03 01 b4 ff c0 49 36  |....Y...U.....I6|
+00000010  1d 31 9a a7 f6 33 f5 16  78 d7 10 9e 19 eb 1d 67  |.1...3..x......g|
+00000020  20 39 f8 73 7e 27 e2 dc  d1 ab 03 20 79 64 67 f7  | 9.s~'..... ydg.|
+00000030  8b c8 97 f0 b4 87 0e 2d  4b 22 6c ed 92 48 85 52  |.......-K"l..H.R|
+00000040  eb 57 56 a8 cf 19 9f 4d  e3 38 5e a0 c0 09 00 00  |.WV....M.8^.....|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  01 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
 00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
 00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
 00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
 00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
-00000270  2a 16 03 01 00 b5 0c 00  00 b1 03 00 1d 20 16 64  |*............ .d|
-00000280  ca 24 70 6f 61 2f 9e 2d  43 0a 73 ac 67 f0 7a e5  |.$poa/.-C.s.g.z.|
-00000290  c7 4e c4 1f ad 13 0d eb  df ff 0d ff a3 27 00 8b  |.N...........'..|
-000002a0  30 81 88 02 42 01 1a 33  8b 88 78 ed 5c c1 56 0d  |0...B..3..x.\.V.|
-000002b0  75 51 69 a0 e7 45 6d ae  b0 67 55 3f be 23 3e 92  |uQi..Em..gU?.#>.|
-000002c0  fe 26 68 a2 30 84 2f b3  33 66 f6 dd 71 67 99 5e  |.&h.0./.3f..qg.^|
-000002d0  1c 6f bf 87 ed 33 a0 87  69 f6 35 65 8d cb 3a 7e  |.o...3..i.5e..:~|
-000002e0  95 a7 a4 40 54 cb 97 02  42 00 a3 fe 50 34 68 9f  |...@T...B...P4h.|
-000002f0  f2 43 98 23 e4 24 ad 36  e9 d3 e0 75 2c 11 46 6c  |.C.#.$.6...u,.Fl|
-00000300  48 33 c5 bc 2d 04 ff cc  bb ec 38 ec f4 b3 55 31  |H3..-.....8...U1|
-00000310  8a 6e 38 a5 6d a0 9c fc  f6 98 75 48 c6 79 53 de  |.n8.m.....uH.yS.|
-00000320  dd 91 49 f0 b6 32 83 45  61 89 4e 16 03 01 00 0a  |..I..2.Ea.N.....|
-00000330  0d 00 00 06 03 01 02 40  00 00 16 03 01 00 04 0e  |.......@........|
-00000340  00 00 00                                          |...|
+00000270  2a 16 03 01 00 b4 0c 00  00 b0 03 00 1d 20 ec 38  |*............ .8|
+00000280  f7 41 d0 f3 f4 6a ca 47  18 74 f1 22 2c 47 ee 39  |.A...j.G.t.",G.9|
+00000290  c9 a2 db 64 05 01 ae 5d  08 65 53 7f 24 78 00 8a  |...d...].eS.$x..|
+000002a0  30 81 87 02 41 64 39 65  56 fa d4 69 e7 c5 a5 32  |0...Ad9eV..i...2|
+000002b0  4c 52 55 96 fe 01 cd 41  3c 18 ed df fd 09 c3 89  |LRU....A<.......|
+000002c0  80 bd 88 9e d7 a1 85 16  d1 a4 5a f0 9a 76 e9 2f  |..........Z..v./|
+000002d0  d2 a4 42 a4 89 98 6c 87  64 b1 49 4e 6a 68 d2 43  |..B...l.d.INjh.C|
+000002e0  41 a2 c7 a6 2f f7 02 42  01 6c bb 32 c0 47 7e 08  |A.../..B.l.2.G~.|
+000002f0  6b 7a 44 18 b7 5d 4c 4d  6d 80 92 bb e5 65 98 1b  |kzD..]LMm....e..|
+00000300  d7 a6 a3 1b b5 f3 46 1a  e7 e0 89 04 40 b0 29 aa  |......F.....@.).|
+00000310  fe 85 6a 9a 4b 18 75 ab  00 52 71 54 41 8d eb 31  |..j.K.u..RqTA..1|
+00000320  47 69 9b 9d dc 3b 1b 3e  76 27 16 03 01 00 0a 0d  |Gi...;.>v'......|
+00000330  00 00 06 03 01 02 40 00  00 16 03 01 00 04 0e 00  |......@.........|
+00000340  00 00                                             |..|
 >>> Flow 3 (client to server)
 00000000  16 03 01 01 fd 0b 00 01  f9 00 01 f6 00 01 f3 30  |...............0|
 00000010  82 01 ef 30 82 01 58 a0  03 02 01 02 02 10 5c 19  |...0..X.......\.|
 00000200  e5 35 16 03 01 00 25 10  00 00 21 20 2f e5 7d a3  |.5....%...! /.}.|
 00000210  47 cd 62 43 15 28 da ac  5f bb 29 07 30 ff f6 84  |G.bC.(.._.).0...|
 00000220  af c4 cf c2 ed 90 99 5f  58 cb 3b 74 16 03 01 00  |......._X.;t....|
-00000230  86 0f 00 00 82 00 80 90  68 a8 2f 6f 2b 70 e4 25  |........h./o+p.%|
-00000240  7d fb b7 85 db 44 ec 1a  ad 6d 84 fb 95 21 fa 24  |}....D...m...!.$|
-00000250  7b 31 6a 97 4f 06 ee 87  22 c3 7c 81 70 ed e3 2a  |{1j.O...".|.p..*|
-00000260  d5 2c d1 4e 6d f0 12 52  2f 98 05 08 af 41 fa 87  |.,.Nm..R/....A..|
-00000270  d1 62 98 6c 06 47 ec 7a  44 e0 7d ae 7a 7d ef 1b  |.b.l.G.zD.}.z}..|
-00000280  d5 2c fa 1b 70 a3 fb 9a  5d 8c 60 b4 44 6a e5 b8  |.,..p...].`.Dj..|
-00000290  80 4c 29 fc f1 2d f1 11  46 81 c4 01 e4 11 2e 05  |.L)..-..F.......|
-000002a0  cb 2b ca d9 4a 14 39 06  93 77 19 db 80 03 82 38  |.+..J.9..w.....8|
-000002b0  e5 c1 0f 11 17 47 a7 14  03 01 00 01 01 16 03 01  |.....G..........|
-000002c0  00 30 a6 68 28 50 75 6d  eb f4 32 c8 a3 57 3f b1  |.0.h(Pum..2..W?.|
-000002d0  37 84 8e 7e 1d 1d 93 7d  9f ec ff ac 1c 8d bf 30  |7..~...}.......0|
-000002e0  d2 b0 0f 3f 02 c3 ef ac  a3 62 94 26 1c 8f 7e 8d  |...?.....b.&..~.|
-000002f0  74 99                                             |t.|
+00000230  86 0f 00 00 82 00 80 05  7e 70 eb cb ef e3 d9 6f  |........~p.....o|
+00000240  59 29 b5 da f2 07 f5 42  62 4e 74 9b cf 00 e1 5c  |Y).....BbNt....\|
+00000250  69 a5 67 3a b0 b2 ca f2  10 ed 1c b4 81 5d 7d 9e  |i.g:.........]}.|
+00000260  1a 45 69 42 13 c5 b0 86  dc 3d 60 e5 cf fd ae 0f  |.EiB.....=`.....|
+00000270  17 bb 4a ed d7 06 eb f1  6d 47 98 b7 e8 87 eb 3c  |..J.....mG.....<|
+00000280  12 55 2c 06 de 55 48 c7  59 85 cb 62 d6 e7 1d 05  |.U,..UH.Y..b....|
+00000290  1e 6d 69 84 cd 16 8e dd  ed 5b 5a 2f f2 97 b7 78  |.mi......[Z/...x|
+000002a0  93 c1 fb 75 26 c8 b5 58  43 17 c7 52 54 20 4f 7d  |...u&..XC..RT O}|
+000002b0  7c 46 89 65 fe 51 29 14  03 01 00 01 01 16 03 01  ||F.e.Q).........|
+000002c0  00 30 d9 59 e6 7e c0 a6  2a af 36 0c 2e cf 0f 42  |.0.Y.~..*.6....B|
+000002d0  54 d4 41 c6 3c f8 84 d9  2a a6 82 94 22 2d ac ae  |T.A.<...*..."-..|
+000002e0  d9 f7 68 22 f6 f0 2e 56  c1 97 80 73 0d b3 f0 70  |..h"...V...s...p|
+000002f0  49 78                                             |Ix|
 >>> Flow 4 (server to client)
-00000000  14 03 01 00 01 01 16 03  01 00 30 80 3e 0d 50 13  |..........0.>.P.|
-00000010  5f 00 ba 2e 47 46 5d 63  1b 72 a8 02 24 1c 3e 1f  |_...GF]c.r..$.>.|
-00000020  ed e2 3a 45 d7 7d 3a f2  33 97 c3 ab 13 9b 0e 4a  |..:E.}:.3......J|
-00000030  04 f0 08 48 ab d3 46 0b  40 7d 5c                 |...H..F.@}\|
+00000000  14 03 01 00 01 01 16 03  01 00 30 06 19 79 49 41  |..........0..yIA|
+00000010  f9 9c 75 84 73 95 96 bd  1e 25 56 a9 49 ed 8e 38  |..u.s....%V.I..8|
+00000020  34 40 60 dc f0 2d f3 6c  cf 5b 80 84 2b 81 db 5f  |4@`..-.l.[..+.._|
+00000030  f4 27 03 ad b8 8d 80 0c  99 69 6f                 |.'.......io|
 >>> Flow 5 (client to server)
-00000000  17 03 01 00 20 f7 32 e7  36 4f 77 2f 4a 05 fd 27  |.... .2.6Ow/J..'|
-00000010  19 57 52 f7 8a 0c 7f fb  14 78 b2 06 bf ca 86 73  |.WR......x.....s|
-00000020  32 13 33 04 91 17 03 01  00 20 7e e4 fe c5 6d f7  |2.3...... ~...m.|
-00000030  d4 69 30 57 89 a0 76 70  40 a7 b5 17 74 2f 5d 16  |.i0W..vp@...t/].|
-00000040  c1 19 30 73 f8 37 c4 10  5b b7 15 03 01 00 20 08  |..0s.7..[..... .|
-00000050  41 5e 0b 9f 36 23 bd 9a  09 f7 58 9d a3 d7 26 3a  |A^..6#....X...&:|
-00000060  f4 5e 6b bf 9c d4 6f 0c  d3 9e cd de cb 95 57     |.^k...o.......W|
+00000000  17 03 01 00 20 20 67 bd  ff 84 9b 0e 58 f3 45 1e  |....  g.....X.E.|
+00000010  7a 25 d5 ae f0 26 4b 42  c7 f3 a5 77 7b 2f 42 21  |z%...&KB...w{/B!|
+00000020  2e c6 c9 81 23 17 03 01  00 20 69 1c 2a b9 05 16  |....#.... i.*...|
+00000030  8b 71 3a c2 18 76 bd 25  1f de 83 e9 14 e2 a3 5c  |.q:..v.%.......\|
+00000040  9b 33 ee 14 39 da e2 e7  a3 a7 15 03 01 00 20 e9  |.3..9......... .|
+00000050  dc 16 0c 13 56 7a e5 fd  ce b9 4f d1 c7 20 3f ca  |....Vz....O.. ?.|
+00000060  72 20 15 f7 11 81 fe 88  ab 90 4c dc 0b a5 11     |r ........L....|
index c46a9670e845b3c02cc133d98e347ca19d5bb9b9..980f93328f68a117add002a992b842467fe22616 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 01 00 59 02 00 00  55 03 01 97 fe 7f 92 37  |....Y...U......7|
-00000010  67 99 e0 d8 62 a9 31 80  bd 1f 31 8e 7d 0b 08 0a  |g...b.1...1.}...|
-00000020  de a5 82 a2 f2 d0 c1 35  66 34 6e 20 39 46 b1 b0  |.......5f4n 9F..|
-00000030  6e 2d 0e fe 8c 48 ea ab  1c c4 49 ee f4 21 cf cb  |n-...H....I..!..|
-00000040  2a 20 57 78 18 99 a1 b9  7f 88 4f 64 c0 13 00 00  |* Wx......Od....|
+00000000  16 03 01 00 59 02 00 00  55 03 01 4d 6d 71 59 6b  |....Y...U..MmqYk|
+00000010  cd 8c 6e b0 11 bf 4a 9e  25 90 12 cc ac b4 3f be  |..n...J.%.....?.|
+00000020  86 1b 13 47 a6 be 3d a0  8f 0b 77 20 6b b5 57 6d  |...G..=...w k.Wm|
+00000030  39 74 b0 9d b4 ae 2e 72  7e 90 d2 ab ed 32 fa 65  |9t.....r~....2.e|
+00000040  ed 85 63 d2 16 ef 47 af  a6 37 17 88 c0 13 00 00  |..c...G..7......|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  01 02 59 0b 00 02 55 00  02 52 00 02 4f 30 82 02  |..Y...U..R..O0..|
 00000070  4b 30 82 01 b4 a0 03 02  01 02 02 09 00 e8 f0 9d  |K0..............|
 00000290  77 8d 0c 1c f1 0f a1 d8  40 83 61 c9 4c 72 2b 9d  |w.......@.a.Lr+.|
 000002a0  ae db 46 06 06 4d f4 c1  b3 3e c0 d1 bd 42 d4 db  |..F..M...>...B..|
 000002b0  fe 3d 13 60 84 5c 21 d3  3b e9 fa e7 16 03 01 00  |.=.`.\!.;.......|
-000002c0  aa 0c 00 00 a6 03 00 1d  20 07 80 79 40 4b b1 0e  |........ ..y@K..|
-000002d0  05 ce e4 ca 9d f5 d7 ad  a6 98 f2 40 f9 b9 66 a8  |...........@..f.|
-000002e0  04 6e ae b5 da 99 67 09  69 00 80 01 4a f2 c1 c9  |.n....g.i...J...|
-000002f0  2f 46 4f b8 9e 8b 2c c4  a1 32 44 3c dc 2c 5e b9  |/FO...,..2D<.,^.|
-00000300  76 5f 41 20 23 1b 82 dd  ec 37 b4 24 68 6d a7 39  |v_A #....7.$hm.9|
-00000310  4f f2 e5 97 09 75 64 2a  64 16 b8 99 04 8a 74 77  |O....ud*d.....tw|
-00000320  19 bb 12 5f 27 f6 41 09  f7 2e 1c 33 80 3b 01 57  |..._'.A....3.;.W|
-00000330  5c f9 20 6e 0c 48 76 59  e1 8b 1f bb 2a 33 1a 28  |\. n.HvY....*3.(|
-00000340  a0 5a 05 44 94 eb 35 62  5e ae 7f e4 01 76 b6 b4  |.Z.D..5b^....v..|
-00000350  64 91 bf 25 09 ff 88 8a  af 73 00 d0 7e ea 0f ca  |d..%.....s..~...|
-00000360  4a 2b d4 6f 02 26 98 28  5a ed 11 16 03 01 00 0a  |J+.o.&.(Z.......|
+000002c0  aa 0c 00 00 a6 03 00 1d  20 96 0b 2f 57 e1 1e 07  |........ ../W...|
+000002d0  e0 7f a4 91 67 97 d0 a0  19 d3 9a b2 49 79 f9 5f  |....g.......Iy._|
+000002e0  7f b5 65 d4 3a 89 92 8f  11 00 80 08 29 72 0b f7  |..e.:.......)r..|
+000002f0  7b 68 38 5e 47 15 89 f1  ee be f3 a9 26 a4 9c 6d  |{h8^G.......&..m|
+00000300  2c 2a ff f0 d6 2d 25 a5  b0 93 66 7d 8c fb fe a5  |,*...-%...f}....|
+00000310  3b cc b6 71 f4 1b 55 c4  ef 08 73 b1 49 47 2c e6  |;..q..U...s.IG,.|
+00000320  a1 ef 53 ca bb 15 e3 25  ea e7 48 44 18 88 e1 d2  |..S....%..HD....|
+00000330  3b e9 f6 92 61 5e 5c 06  44 83 37 6c e6 b6 26 32  |;...a^\.D.7l..&2|
+00000340  fd d6 00 fc 87 a2 37 e3  84 d2 ad 2d 99 0d e1 ba  |......7....-....|
+00000350  bb 2f 3b 0b dd 56 5c c2  14 af 86 58 2c 8b f8 64  |./;..V\....X,..d|
+00000360  75 ab d3 35 41 59 fa fe  a5 48 26 16 03 01 00 0a  |u..5AY...H&.....|
 00000370  0d 00 00 06 03 01 02 40  00 00 16 03 01 00 04 0e  |.......@........|
 00000380  00 00 00                                          |...|
 >>> Flow 3 (client to server)
 00000200  e5 35 16 03 01 00 25 10  00 00 21 20 2f e5 7d a3  |.5....%...! /.}.|
 00000210  47 cd 62 43 15 28 da ac  5f bb 29 07 30 ff f6 84  |G.bC.(.._.).0...|
 00000220  af c4 cf c2 ed 90 99 5f  58 cb 3b 74 16 03 01 00  |......._X.;t....|
-00000230  86 0f 00 00 82 00 80 81  aa 68 1f a9 a4 de f1 4d  |.........h.....M|
-00000240  30 9a fe e6 a5 f6 f6 18  b6 3e d2 c7 f1 e6 77 e3  |0........>....w.|
-00000250  6a cd 61 01 81 3a 02 31  a5 aa d6 db b6 02 9d 4b  |j.a..:.1.......K|
-00000260  f5 78 50 c3 95 fe 43 88  33 3a 95 32 bc e8 02 1a  |.xP...C.3:.2....|
-00000270  e6 f4 d5 54 b9 fc e0 4a  4e f0 92 21 35 4b de c8  |...T...JN..!5K..|
-00000280  a4 b0 01 c3 ca 3a 87 ed  cb 21 1c ce c2 14 7b 8d  |.....:...!....{.|
-00000290  90 68 b9 21 49 13 dd cd  e7 68 83 41 7c 84 6a 75  |.h.!I....h.A|.ju|
-000002a0  76 ee 19 8b fa d5 a6 57  3d a7 f1 f1 6f 11 ca 77  |v......W=...o..w|
-000002b0  95 0e b5 c7 3d 99 d4 14  03 01 00 01 01 16 03 01  |....=...........|
-000002c0  00 30 5e be 40 82 f8 db  05 20 23 45 a4 42 48 e8  |.0^.@.... #E.BH.|
-000002d0  06 69 eb 4c ef 79 53 52  4a 5a 3a ba cc d6 99 59  |.i.L.ySRJZ:....Y|
-000002e0  4d c2 b0 34 0f 14 68 03  93 8b a4 95 7e cf 26 f8  |M..4..h.....~.&.|
-000002f0  5c 8a                                             |\.|
+00000230  86 0f 00 00 82 00 80 8f  5d a5 27 13 09 5e 49 5f  |........].'..^I_|
+00000240  ff fd d6 88 75 83 cc 74  f3 e1 af 44 76 6a 35 16  |....u..t...Dvj5.|
+00000250  e8 36 5f b7 dc 21 69 77  61 12 c5 69 f7 0d 98 1f  |.6_..!iwa..i....|
+00000260  d5 15 f1 e8 88 c5 30 e8  b5 c3 2a e5 26 93 cc a4  |......0...*.&...|
+00000270  eb 31 c6 d7 f5 f4 7c d5  f7 a2 3f 1f 75 cd b2 b2  |.1....|...?.u...|
+00000280  82 3a 03 8c 5e 15 0a d2  98 b8 65 cb 5f d5 db d0  |.:..^.....e._...|
+00000290  b6 36 8c 89 7e 48 fa 3a  9f 9a bd c1 48 e7 d6 20  |.6..~H.:....H.. |
+000002a0  ef 45 5b 24 32 04 58 82  b3 7b 42 fd fe ba 78 32  |.E[$2.X..{B...x2|
+000002b0  2a f5 b7 81 33 da db 14  03 01 00 01 01 16 03 01  |*...3...........|
+000002c0  00 30 5f 96 98 94 17 6d  ff 84 72 d3 63 fd 14 59  |.0_....m..r.c..Y|
+000002d0  eb bf 5f 3e 8f dc f1 c1  dc 77 8a 33 f6 2e a2 4a  |.._>.....w.3...J|
+000002e0  15 d1 2e a4 ec 0d 3c 0b  18 07 09 6c 0d 09 34 2e  |......<....l..4.|
+000002f0  a4 6f                                             |.o|
 >>> Flow 4 (server to client)
-00000000  14 03 01 00 01 01 16 03  01 00 30 ef 9b 5c da 0a  |..........0..\..|
-00000010  2e c4 79 fa ea 8a 9c 78  4a 1f 08 77 56 73 6e fa  |..y....xJ..wVsn.|
-00000020  3a 5b 3c cd cd e9 0c a8  bb 59 9e 22 ab 67 2c 03  |:[<......Y.".g,.|
-00000030  de ad 7c e4 cb 85 d7 8f  c1 1c e3                 |..|........|
+00000000  14 03 01 00 01 01 16 03  01 00 30 b7 4a 5c 0c e6  |..........0.J\..|
+00000010  7c d9 43 7c e7 b4 2f d7  b5 c6 5e 36 c7 87 dd 82  ||.C|../...^6....|
+00000020  da d3 b2 4e 05 ae f5 8c  b0 4d db c2 53 62 55 73  |...N.....M..SbUs|
+00000030  8c 2a 1b d5 df e4 7c a4  cf db 8b                 |.*....|....|
 >>> Flow 5 (client to server)
-00000000  17 03 01 00 20 48 1a 1a  1c 6c 7d 6c 2a e0 b2 e3  |.... H...l}l*...|
-00000010  b3 9f ec 39 a8 cd 9a f9  a2 3e 2d 46 3b cf 17 ed  |...9.....>-F;...|
-00000020  70 99 ce d7 3c 17 03 01  00 20 69 27 e9 89 78 e6  |p...<.... i'..x.|
-00000030  64 c0 a9 40 4f 0d 97 53  b2 2e 15 f3 2b 54 3b 77  |d..@O..S....+T;w|
-00000040  f2 24 2c 94 dc b3 8b f0  c4 ce 15 03 01 00 20 1b  |.$,........... .|
-00000050  50 55 83 d8 6b b4 04 b2  f0 2d 1c 9c 0d fa de 58  |PU..k....-.....X|
-00000060  cd 0a 1d 55 d6 36 f4 a4  fb cc 55 c5 b1 f3 d3     |...U.6....U....|
+00000000  17 03 01 00 20 b9 26 60  87 38 9c d9 c4 65 17 8e  |.... .&`.8...e..|
+00000010  3c 7f 1a b4 23 cd 27 fd  4e 92 ee 0e f2 11 dc e2  |<...#.'.N.......|
+00000020  23 e4 26 f3 55 17 03 01  00 20 5e 89 33 21 f0 dc  |#.&.U.... ^.3!..|
+00000030  e8 4f 33 1c 66 56 99 38  a5 4c 0e 0e 93 41 b7 48  |.O3.fV.8.L...A.H|
+00000040  5d ce 49 d0 d2 8a 56 a6  2d 68 15 03 01 00 20 05  |].I...V.-h.... .|
+00000050  e0 ed f9 c2 56 ec 64 e5  e7 0b f4 8a e2 41 96 9e  |....V.d......A..|
+00000060  ed 94 c8 95 69 d7 ce 2d  0e bb 5b 18 5f 30 52     |....i..-..[._0R|
index 7d6683c026ab433a6b59c976f9833eb4582fc011..6fc506f0997bd031681e2d04b18de31c0ea90216 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 01 00 59 02 00 00  55 03 01 a7 ea 63 8c 7d  |....Y...U....c.}|
-00000010  54 70 04 d5 5e a2 2e 8b  75 4f 17 c8 a8 8c 3d bc  |Tp..^...uO....=.|
-00000020  08 aa 82 48 85 ed 1a ff  42 e1 54 20 3b 77 9d 32  |...H....B.T ;w.2|
-00000030  4d 60 f2 81 f8 20 aa d2  b0 eb ea 7c 6a 39 52 20  |M`... .....|j9R |
-00000040  94 4a 2a 88 05 8a fe 6c  50 5c 95 39 c0 09 00 00  |.J*....lP\.9....|
+00000000  16 03 01 00 59 02 00 00  55 03 01 a3 4e 79 27 af  |....Y...U...Ny'.|
+00000010  c8 a3 15 a4 c2 7a 54 58  54 0e 0d 93 c2 ff e1 f9  |.....zTXT.......|
+00000020  55 ab 2c ea 32 cf d2 47  2e d7 8e 20 49 08 d1 66  |U.,.2..G... I..f|
+00000030  9b 9e aa af c9 90 95 ec  cb 64 2e 3d f6 27 d5 f6  |.........d.=.'..|
+00000040  23 10 d5 6e 50 5f bc 89  fe c7 d7 de c0 09 00 00  |#..nP_..........|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  01 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
 00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
 00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
 00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
 00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
-00000270  2a 16 03 01 00 b5 0c 00  00 b1 03 00 1d 20 3a 1f  |*............ :.|
-00000280  18 e9 f2 09 3e 79 4b a0  62 73 ef 87 0d ea 90 51  |....>yK.bs.....Q|
-00000290  7f 9d d2 79 59 e4 11 7f  69 f7 a9 d7 78 7f 00 8b  |...yY...i...x...|
-000002a0  30 81 88 02 42 01 65 ac  eb e6 b0 86 73 95 a4 27  |0...B.e.....s..'|
-000002b0  e3 82 55 cf 88 16 80 c2  68 4b 39 77 2a b1 a9 d3  |..U.....hK9w*...|
-000002c0  08 d5 ac 77 ce 5b 16 73  2c ad b5 57 2a 7a 75 34  |...w.[.s,..W*zu4|
-000002d0  ec 99 23 bd df b2 27 36  5a 4b 40 e0 d3 b0 d2 31  |..#...'6ZK@....1|
-000002e0  9b c7 9e 0a cb 5b 69 02  42 00 88 d7 5a 6a 9e 4c  |.....[i.B...Zj.L|
-000002f0  c5 7b 2c 8e 93 3b 75 27  b4 00 11 88 ba cf 99 8c  |.{,..;u'........|
-00000300  e5 f2 60 22 de f2 fe 86  a6 48 86 9c 40 31 08 75  |..`".....H..@1.u|
-00000310  aa bc 5d 6d fa 2e a4 a9  a1 0d fc e1 d9 5a a1 60  |..]m.........Z.`|
-00000320  93 b9 69 c7 c2 3e f5 a9  cb 31 41 16 03 01 00 04  |..i..>...1A.....|
+00000270  2a 16 03 01 00 b5 0c 00  00 b1 03 00 1d 20 4a 7c  |*............ J||
+00000280  0a 86 8a 81 f2 60 4a 3c  ac d7 7d 3b fc 00 a5 b4  |.....`J<..};....|
+00000290  85 45 45 45 fb 09 53 d7  4a cf 24 9d c8 1a 00 8b  |.EEE..S.J.$.....|
+000002a0  30 81 88 02 42 01 7a c9  c0 76 8c 26 98 63 4e a3  |0...B.z..v.&.cN.|
+000002b0  ad 4f 4e a3 d7 c7 d6 4a  69 28 cf d2 7b 0b 36 fb  |.ON....Ji(..{.6.|
+000002c0  a3 ae 2f e1 83 ea ea 4a  b7 2d ef a8 2d 13 96 e4  |../....J.-..-...|
+000002d0  73 83 66 70 5e 5c d9 5a  d1 1c d1 33 18 0b b3 30  |s.fp^\.Z...3...0|
+000002e0  2a 21 d7 78 d8 70 18 02  42 00 c4 ab 80 33 8f f1  |*!.x.p..B....3..|
+000002f0  c2 74 1b 58 2f 59 d4 27  a1 19 42 bf 14 ea a8 a2  |.t.X/Y.'..B.....|
+00000300  cb bf 96 2d 60 7b 84 40  cc 31 f5 c4 e8 51 87 b8  |...-`{.@.1...Q..|
+00000310  7b 47 ec c4 c0 4a 9b 09  59 1e f8 b5 9a e1 45 a4  |{G...J..Y.....E.|
+00000320  a1 9b ee 78 55 f8 f5 fa  1a fb c5 16 03 01 00 04  |...xU...........|
 00000330  0e 00 00 00                                       |....|
 >>> Flow 3 (client to server)
 00000000  16 03 01 00 25 10 00 00  21 20 2f e5 7d a3 47 cd  |....%...! /.}.G.|
 00000010  62 43 15 28 da ac 5f bb  29 07 30 ff f6 84 af c4  |bC.(.._.).0.....|
 00000020  cf c2 ed 90 99 5f 58 cb  3b 74 14 03 01 00 01 01  |....._X.;t......|
-00000030  16 03 01 00 30 30 25 15  82 a1 7f 11 32 13 52 17  |....00%.....2.R.|
-00000040  b8 bd 5b b9 1e 69 88 0b  b3 5f 12 40 e3 4b 03 cb  |..[..i..._.@.K..|
-00000050  cd 07 3c 43 4f ab f7 5d  2c 6a a3 02 a9 64 d0 77  |..<CO..],j...d.w|
-00000060  27 dc 4a ae 8a                                    |'.J..|
+00000030  16 03 01 00 30 b0 5e 4a  8a 07 e3 86 43 05 16 68  |....0.^J....C..h|
+00000040  0e d1 58 a6 05 49 e9 a6  42 89 2c 3f 33 68 8b 26  |..X..I..B.,?3h.&|
+00000050  23 21 3b 62 ab 7a 21 74  d8 49 15 03 b3 1e c6 53  |#!;b.z!t.I.....S|
+00000060  74 1e 1c 4e 0f                                    |t..N.|
 >>> Flow 4 (server to client)
-00000000  14 03 01 00 01 01 16 03  01 00 30 b5 3e 18 97 a1  |..........0.>...|
-00000010  ca 2e 7f 5f b9 72 cb aa  d4 f6 85 86 d3 27 40 13  |..._.r.......'@.|
-00000020  e3 99 35 13 67 a8 9e 6e  bb 63 15 97 96 42 e4 b3  |..5.g..n.c...B..|
-00000030  fc 15 ee b7 d8 cb a2 64  3d 55 b8                 |.......d=U.|
+00000000  14 03 01 00 01 01 16 03  01 00 30 64 4b 3c 1a e3  |..........0dK<..|
+00000010  7d bb bb bb 64 d8 51 c3  eb 92 65 65 58 35 dd 7b  |}...d.Q...eeX5.{|
+00000020  d2 fd f0 0c c1 10 71 a5  a8 f7 14 84 69 b4 81 18  |......q.....i...|
+00000030  1e 0d d3 19 b6 23 72 1a  a7 43 0e                 |.....#r..C.|
 >>> Flow 5 (client to server)
-00000000  17 03 01 00 20 12 6c bf  f2 39 2d e6 ad a8 38 d5  |.... .l..9-...8.|
-00000010  1c ea 5b 79 e5 c7 4a 41  eb 58 70 f0 7d f7 60 e7  |..[y..JA.Xp.}.`.|
-00000020  ee 77 98 75 f2 17 03 01  00 20 ac 5e 6d b0 81 0b  |.w.u..... .^m...|
-00000030  14 ca c2 70 53 d8 6d 55  49 63 da 8a 61 66 80 2d  |...pS.mUIc..af.-|
-00000040  e4 7c 2e 60 1f eb 3c f2  27 66 15 03 01 00 20 7a  |.|.`..<.'f.... z|
-00000050  2b 80 f8 00 0f 06 f5 6e  fe b7 b7 6b 12 6c 8d 8e  |+......n...k.l..|
-00000060  c4 11 23 2b a2 bb 16 93  b4 e0 e0 fd 8c 42 db     |..#+.........B.|
+00000000  17 03 01 00 20 c3 e6 70  2c 44 4f 04 0c fb 0b 7f  |.... ..p,DO.....|
+00000010  1d 2c ef 4d cc c3 21 ba  a2 db 74 76 46 ea 00 40  |.,.M..!...tvF..@|
+00000020  54 2d 4a fe 59 17 03 01  00 20 0c 6b 39 0d b5 f3  |T-J.Y.... .k9...|
+00000030  ed 7e d0 de 01 18 0c 32  4e 59 93 46 d3 c5 4f c0  |.~.....2NY.F..O.|
+00000040  f5 fd f1 d2 79 07 7d 07  b0 24 15 03 01 00 20 1d  |....y.}..$.... .|
+00000050  f7 53 a2 e7 3f 88 87 35  01 6e a5 b1 d6 81 37 5b  |.S..?..5.n....7[|
+00000060  a7 64 4c 29 f4 71 59 a1  36 c1 1a 24 93 31 7d     |.dL).qY.6..$.1}|
index c0e842d155cb906736eae388a0e45bf935f90a29..24da556b25621209b55f10e8d0c45fe19bf4df2f 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 01 00 59 02 00 00  55 03 01 16 f4 24 01 94  |....Y...U....$..|
-00000010  68 d2 0f 15 4d d6 65 54  84 73 ab 2c b2 11 c5 64  |h...M.eT.s.,...d|
-00000020  d8 93 66 50 cd b0 f0 ab  11 5c 72 20 b1 13 c1 f5  |..fP.....\r ....|
-00000030  63 ed 70 0b 21 52 85 36  84 99 1d b6 bb dc d3 1c  |c.p.!R.6........|
-00000040  b3 76 13 d9 ef 47 c4 c0  18 57 23 3b c0 13 00 00  |.v...G...W#;....|
+00000000  16 03 01 00 59 02 00 00  55 03 01 63 68 ea 52 0b  |....Y...U..ch.R.|
+00000010  dc 68 c7 d0 75 3e 7d 6f  0b 8c cb 25 48 b0 bb df  |.h..u>}o...%H...|
+00000020  7a 56 93 a9 d5 4f 0c 3a  e2 37 ab 20 1f 0f a4 d3  |zV...O.:.7. ....|
+00000030  b4 f6 66 6f 39 6f 62 fb  6a 1f 41 09 4b 02 5c 15  |..fo9ob.j.A.K.\.|
+00000040  a0 ba cb a6 f9 bd 3b ec  cb 76 6e ea c0 13 00 00  |......;..vn.....|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  01 02 59 0b 00 02 55 00  02 52 00 02 4f 30 82 02  |..Y...U..R..O0..|
 00000070  4b 30 82 01 b4 a0 03 02  01 02 02 09 00 e8 f0 9d  |K0..............|
 00000290  77 8d 0c 1c f1 0f a1 d8  40 83 61 c9 4c 72 2b 9d  |w.......@.a.Lr+.|
 000002a0  ae db 46 06 06 4d f4 c1  b3 3e c0 d1 bd 42 d4 db  |..F..M...>...B..|
 000002b0  fe 3d 13 60 84 5c 21 d3  3b e9 fa e7 16 03 01 00  |.=.`.\!.;.......|
-000002c0  aa 0c 00 00 a6 03 00 1d  20 7e aa 30 94 7b fb 09  |........ ~.0.{..|
-000002d0  b5 55 ce b3 e9 e0 5b 55  82 f4 e6 7c d0 e4 57 eb  |.U....[U...|..W.|
-000002e0  9b ec 82 48 d6 0e 2a bb  16 00 80 80 da c5 75 4f  |...H..*.......uO|
-000002f0  82 95 ee 47 28 af 09 08  d5 13 68 33 5d 91 dd 13  |...G(.....h3]...|
-00000300  43 84 e9 54 d9 e7 39 7c  38 74 d5 92 8f 46 37 86  |C..T..9|8t...F7.|
-00000310  44 68 ae c7 3a ad e1 33  5f cd d8 c6 a5 7c 5e 83  |Dh..:..3_....|^.|
-00000320  44 ba b1 09 44 ec 42 7f  41 80 d6 b6 4c 6d ae 24  |D...D.B.A...Lm.$|
-00000330  a9 3b 53 87 2f 3b 3a 1f  da 87 2b 7d cf 9e ed a5  |.;S./;:...+}....|
-00000340  04 54 ad c2 3c 7b 21 60  55 67 41 47 60 02 1e 62  |.T..<{!`UgAG`..b|
-00000350  bb 9f ee 2c 6e 79 20 6e  65 e2 d0 ae 73 70 3e a7  |...,ny ne...sp>.|
-00000360  3f 74 96 8e 2a 6e a6 7e  7a e0 e4 16 03 01 00 04  |?t..*n.~z.......|
+000002c0  aa 0c 00 00 a6 03 00 1d  20 04 9f 8b 4f 13 83 26  |........ ...O..&|
+000002d0  a3 cf 08 6e 59 bf b5 49  b8 ff 95 94 21 8d 2a 56  |...nY..I....!.*V|
+000002e0  2e 4b be ad ac 89 6e 52  4d 00 80 5f 63 93 43 a2  |.K....nRM.._c.C.|
+000002f0  a6 fb 53 b0 ac 93 3f 55  1d c1 0f 71 1e 96 ba 9f  |..S...?U...q....|
+00000300  86 19 f3 83 7d 90 ce 06  24 9a 60 69 f0 35 24 5d  |....}...$.`i.5$]|
+00000310  9d ce 49 0d 6f ba 31 59  3c f2 64 27 66 76 0e f1  |..I.o.1Y<.d'fv..|
+00000320  33 eb b8 70 61 d3 0c 93  a3 62 c7 5e c2 06 9d 48  |3..pa....b.^...H|
+00000330  16 2e a6 62 50 18 f6 c0  79 c2 09 f3 d5 74 bf db  |...bP...y....t..|
+00000340  b8 d4 25 06 a7 be 4a b0  62 82 86 d0 00 86 5e a2  |..%...J.b.....^.|
+00000350  34 49 9b 37 37 9a b6 eb  cc b9 8b 17 1f 29 4b a3  |4I.77........)K.|
+00000360  51 e3 c3 e8 3e 6e df c4  1d e5 48 16 03 01 00 04  |Q...>n....H.....|
 00000370  0e 00 00 00                                       |....|
 >>> Flow 3 (client to server)
 00000000  16 03 01 00 25 10 00 00  21 20 2f e5 7d a3 47 cd  |....%...! /.}.G.|
 00000010  62 43 15 28 da ac 5f bb  29 07 30 ff f6 84 af c4  |bC.(.._.).0.....|
 00000020  cf c2 ed 90 99 5f 58 cb  3b 74 14 03 01 00 01 01  |....._X.;t......|
-00000030  16 03 01 00 30 5a cb 36  c8 1c 43 a8 e1 88 db c9  |....0Z.6..C.....|
-00000040  ae 78 b0 af 97 e4 c3 f6  25 51 8e 4d 57 94 ee ca  |.x......%Q.MW...|
-00000050  a4 8b 3f 4d 17 75 34 58  c3 fa a6 6f d4 e5 ae 3a  |..?M.u4X...o...:|
-00000060  cb 5a cb 11 ef                                    |.Z...|
+00000030  16 03 01 00 30 a6 3a 66  02 e6 09 6a dd 68 56 bc  |....0.:f...j.hV.|
+00000040  aa ec 82 c4 69 9b b9 45  44 ec e2 c2 5b 49 5d 9b  |....i..ED...[I].|
+00000050  f8 0e 81 1e 23 9e 13 72  d1 d2 0c 24 01 4f 35 aa  |....#..r...$.O5.|
+00000060  27 fc b3 cc 08                                    |'....|
 >>> Flow 4 (server to client)
-00000000  14 03 01 00 01 01 16 03  01 00 30 96 92 50 6f f0  |..........0..Po.|
-00000010  d1 ff 7c 39 fb 75 0c 8b  c9 d7 29 7d 9d 32 4c 19  |..|9.u....)}.2L.|
-00000020  2e 93 ea 11 87 07 fc 5a  7d 3c 30 e1 bd 64 7f 90  |.......Z}<0..d..|
-00000030  fd 70 1d 50 eb ec f2 d6  de 09 61                 |.p.P......a|
+00000000  14 03 01 00 01 01 16 03  01 00 30 0e 25 d7 a9 c0  |..........0.%...|
+00000010  18 3b bf 55 c0 47 3a 95  2d cb 6f c2 2c de e3 94  |.;.U.G:.-.o.,...|
+00000020  32 d3 eb e2 b6 6b 5f 42  9c 1e 47 d6 76 0c eb 95  |2....k_B..G.v...|
+00000030  fd 2d c3 9a ee ee 83 87  e8 8d 83                 |.-.........|
 >>> Flow 5 (client to server)
-00000000  17 03 01 00 20 fd a4 ba  f1 78 a9 a2 45 d3 d2 5a  |.... ....x..E..Z|
-00000010  1e 41 6b 89 8d bd a4 21  69 03 a1 7c b8 56 ff df  |.Ak....!i..|.V..|
-00000020  67 bc 85 5e 21 17 03 01  00 20 a7 6d 4c 11 d0 f3  |g..^!.... .mL...|
-00000030  7d e2 f0 69 18 7c 42 71  78 e4 3b 71 7d 13 27 bb  |}..i.|Bqx.;q}.'.|
-00000040  79 fd d7 b2 d7 28 ca 92  83 f1 15 03 01 00 20 10  |y....(........ .|
-00000050  b3 79 d4 1d 70 db b7 6c  f2 15 05 3c 4d 65 ba ec  |.y..p..l...<Me..|
-00000060  e8 0e 6a ba 88 90 53 2e  6e 29 9c 56 9f 52 5e     |..j...S.n).V.R^|
+00000000  17 03 01 00 20 ba b0 c4  22 ee 52 81 ca 55 97 4d  |.... ...".R..U.M|
+00000010  39 16 b9 37 bf df 7b d1  ae 4b 47 ac 10 12 a9 77  |9..7..{..KG....w|
+00000020  69 50 f3 60 13 17 03 01  00 20 90 d5 17 e4 96 38  |iP.`..... .....8|
+00000030  cd f7 30 6e 19 45 4e 32  ad 5f 1b 00 bf 22 9d c2  |..0n.EN2._..."..|
+00000040  16 30 fe 92 c7 fc 91 38  29 30 15 03 01 00 20 c0  |.0.....8)0.... .|
+00000050  02 ff 81 82 c9 25 c6 b0  06 ee 18 61 19 c8 d2 20  |.....%.....a... |
+00000060  d8 4e 7b a4 a5 57 17 64  4d ad 1e 1e 16 1e 52     |.N{..W.dM.....R|
index 1c65914281461fef58817817deb1d5243e538384..6a40d8327935d949cb7068e3483d679102bbf9c3 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 01 00 59 02 00 00  55 03 01 7a a4 22 4f 19  |....Y...U..z."O.|
-00000010  54 37 47 cb e5 dd b4 54  86 9e 9e d6 3f f1 bd ca  |T7G....T....?...|
-00000020  9a 3e 16 3c 7e 1a 29 22  0d c8 95 20 ac 85 42 c1  |.>.<~.)"... ..B.|
-00000030  e7 f3 38 62 38 24 a8 24  d2 67 bd 0d 06 44 74 cf  |..8b8$.$.g...Dt.|
-00000040  3d a4 37 17 bc 8c 5d 41  9f 5a 74 69 c0 13 00 00  |=.7...]A.Zti....|
+00000000  16 03 01 00 59 02 00 00  55 03 01 05 31 9d 41 04  |....Y...U...1.A.|
+00000010  c0 d4 34 1a fc 0f 63 26  47 d6 13 7f a0 d8 aa bf  |..4...c&G.......|
+00000020  28 92 04 80 02 75 58 e6  01 e1 30 20 3c fc b0 02  |(....uX...0 <...|
+00000030  8b a4 9e 9e b2 5c 17 3c  48 0b 96 6f 15 80 d5 38  |.....\.<H..o...8|
+00000040  25 a2 f8 fb 6b fd 47 27  c2 53 6c 60 c0 13 00 00  |%...k.G'.Sl`....|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  01 02 59 0b 00 02 55 00  02 52 00 02 4f 30 82 02  |..Y...U..R..O0..|
 00000070  4b 30 82 01 b4 a0 03 02  01 02 02 09 00 e8 f0 9d  |K0..............|
 00000290  77 8d 0c 1c f1 0f a1 d8  40 83 61 c9 4c 72 2b 9d  |w.......@.a.Lr+.|
 000002a0  ae db 46 06 06 4d f4 c1  b3 3e c0 d1 bd 42 d4 db  |..F..M...>...B..|
 000002b0  fe 3d 13 60 84 5c 21 d3  3b e9 fa e7 16 03 01 00  |.=.`.\!.;.......|
-000002c0  aa 0c 00 00 a6 03 00 1d  20 71 52 12 72 a7 56 0b  |........ qR.r.V.|
-000002d0  51 81 af 9f e1 95 43 44  54 0e 9e 3d cc 6f 3c 4c  |Q.....CDT..=.o<L|
-000002e0  d7 9c e4 ae d5 ad 13 8b  28 00 80 46 29 b1 46 71  |........(..F).Fq|
-000002f0  ba 0a 3d be 29 0f 57 43  02 05 4e 49 a4 5b cd 39  |..=.).WC..NI.[.9|
-00000300  1c 44 6d 84 02 60 84 b6  7f ff 4e d8 0e e7 16 5a  |.Dm..`....N....Z|
-00000310  dd 3b 5a e0 e5 d0 b6 2c  fb 95 35 94 a0 b6 97 24  |.;Z....,..5....$|
-00000320  92 d7 b1 71 78 ee 15 6f  b2 47 fd c7 a6 a4 94 eb  |...qx..o.G......|
-00000330  44 61 9f 96 83 1d 89 a6  62 d9 9e 5b b2 3d 69 9d  |Da......b..[.=i.|
-00000340  59 c5 a4 4e e0 33 69 0c  56 6f 86 6c 6b e5 be c4  |Y..N.3i.Vo.lk...|
-00000350  ed e4 39 53 f3 fd ea 60  d2 b7 d9 5e 90 fd a3 3e  |..9S...`...^...>|
-00000360  cb 59 5d 81 da 58 07 83  e7 af 25 16 03 01 00 04  |.Y]..X....%.....|
+000002c0  aa 0c 00 00 a6 03 00 1d  20 a4 50 9a 0d c7 2a 1b  |........ .P...*.|
+000002d0  f6 d4 78 49 68 ac 5f 8b  e7 78 68 05 4b f8 c6 b3  |..xIh._..xh.K...|
+000002e0  eb 28 79 96 d5 e6 aa c1  54 00 80 22 66 ec fd 14  |.(y.....T.."f...|
+000002f0  83 7b 03 86 14 75 84 a4  a6 d0 ee d3 d0 f7 95 d8  |.{...u..........|
+00000300  43 48 a4 eb 83 af 96 ac  cf e8 65 20 05 c3 18 9a  |CH........e ....|
+00000310  54 63 f5 2f b7 17 06 e0  2a b3 65 6a 2f cc cd 93  |Tc./....*.ej/...|
+00000320  1e b3 5a 4d 09 da 70 b0  12 46 60 11 e4 9f ee 9f  |..ZM..p..F`.....|
+00000330  3b 6f ef df bc db 69 22  5e e8 4c 41 d6 b7 7b 06  |;o....i"^.LA..{.|
+00000340  b6 99 1c 6d 01 5a 61 7c  4e 3a af 3e 01 7e 46 bd  |...m.Za|N:.>.~F.|
+00000350  c8 15 28 ba 7f b3 d6 9d  95 74 04 36 6c 38 16 86  |..(......t.6l8..|
+00000360  d2 1d 8a 85 d1 21 5c 33  17 50 a1 16 03 01 00 04  |.....!\3.P......|
 00000370  0e 00 00 00                                       |....|
 >>> Flow 3 (client to server)
 00000000  16 03 01 00 25 10 00 00  21 20 2f e5 7d a3 47 cd  |....%...! /.}.G.|
 00000010  62 43 15 28 da ac 5f bb  29 07 30 ff f6 84 af c4  |bC.(.._.).0.....|
 00000020  cf c2 ed 90 99 5f 58 cb  3b 74 14 03 01 00 01 01  |....._X.;t......|
-00000030  16 03 01 00 30 c3 26 49  92 5a 8c d0 da 48 ba 60  |....0.&I.Z...H.`|
-00000040  29 c0 5c d5 44 04 11 7a  25 b5 d6 9f a4 cf fe bf  |).\.D..z%.......|
-00000050  33 a7 ba c2 96 2b 4d c1  fb dc 4c ba b8 2b 6f 20  |3....+M...L..+o |
-00000060  2d 2a 02 ee 17                                    |-*...|
+00000030  16 03 01 00 30 f0 15 ea  81 0f a6 22 0a cd a5 a1  |....0......"....|
+00000040  38 4a da 1b 6c 81 19 d5  35 b7 af e9 ec 16 4d 98  |8J..l...5.....M.|
+00000050  21 c2 0e f7 0b fb ff d8  1e 2d 8b 04 56 82 48 c4  |!........-..V.H.|
+00000060  e5 f9 38 8c d2                                    |..8..|
 >>> Flow 4 (server to client)
-00000000  14 03 01 00 01 01 16 03  01 00 30 f4 4e 0a ea 58  |..........0.N..X|
-00000010  18 c6 9d 5f aa 5d f0 03  d4 63 0d e7 83 cb a8 18  |..._.]...c......|
-00000020  06 fa b6 82 da df 16 89  5c 8b 5d 92 87 b1 42 da  |........\.]...B.|
-00000030  cd 2a ee dc 43 08 f1 0d  1f 18 5c                 |.*..C.....\|
+00000000  14 03 01 00 01 01 16 03  01 00 30 f0 b5 a3 bb bb  |..........0.....|
+00000010  9d 85 7d 6f e7 a9 17 31  65 74 82 69 56 a9 33 21  |..}o...1et.iV.3!|
+00000020  16 9d 75 3a 28 88 a5 c2  a9 e1 a7 43 6e 03 26 96  |..u:(......Cn.&.|
+00000030  37 4b de 63 be 49 cb c8  d4 a2 b6                 |7K.c.I.....|
 >>> Flow 5 (client to server)
-00000000  17 03 01 00 20 e6 95 10  e0 98 07 9f 2b 42 06 b8  |.... .......+B..|
-00000010  2a 6c 5d 4a 95 2a 2c 17  d5 cc 68 42 18 bd 72 58  |*l]J.*,...hB..rX|
-00000020  c1 39 73 05 75 17 03 01  00 20 d4 ae 70 ee a0 ed  |.9s.u.... ..p...|
-00000030  3e dd f9 aa 93 03 ff f5  a4 f6 f3 0d e7 a6 59 a9  |>.............Y.|
-00000040  40 b4 f6 ad a5 46 0b eb  ee 0e 15 03 01 00 20 7c  |@....F........ ||
-00000050  1a 29 f3 49 60 47 2e 52  ec 00 4a 62 44 30 93 5f  |.).I`G.R..JbD0._|
-00000060  df 73 2f 44 65 3f 77 c1  3d 04 32 c8 bb 86 ed     |.s/De?w.=.2....|
+00000000  17 03 01 00 20 a9 9c 8f  74 ce f9 77 bc b3 86 2e  |.... ...t..w....|
+00000010  a5 8e 94 3d 08 a6 96 bf  25 0b 10 c4 66 c2 59 9a  |...=....%...f.Y.|
+00000020  4a 1a b4 77 12 17 03 01  00 20 03 72 60 38 58 88  |J..w..... .r`8X.|
+00000030  86 20 20 3f 18 52 c5 ca  55 3c 04 04 c7 e1 74 6f  |.  ?.R..U<....to|
+00000040  ca 1f cd 27 64 f2 51 12  9c ee 15 03 01 00 20 30  |...'d.Q....... 0|
+00000050  71 2a 78 bf 8b d5 11 7c  63 11 c7 25 0e 56 25 ce  |q*x....|c..%.V%.|
+00000060  24 d5 d7 de a0 ba c7 ba  e6 dc db 8e e3 93 a6     |$..............|
index 1fe13b9f97a20353d67b7195a8e5f1496431dca1..dcc18ad01dad4f03c98f607d7894b24ef8b3f2bc 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 01 00 51 02 00 00  4d 03 01 5a 4f 78 41 d5  |....Q...M..ZOxA.|
-00000010  86 2f d2 0a c6 05 bc c9  8e cc bd b2 39 ac a5 78  |./..........9..x|
-00000020  e3 e5 31 b9 cb 01 af cb  ca fc 88 20 c9 61 c6 91  |..1........ .a..|
-00000030  b2 e5 70 df ca d0 41 a8  20 61 ab 08 f6 dc fe c0  |..p...A. a......|
-00000040  cc ea 1e 80 89 02 6a 26  ea f0 c8 71 00 05 00 00  |......j&...q....|
+00000000  16 03 01 00 51 02 00 00  4d 03 01 2a 09 26 d2 61  |....Q...M..*.&.a|
+00000010  ac 38 91 3d 18 3f f7 a9  3c 34 91 b0 b1 e1 29 68  |.8.=.?..<4....)h|
+00000020  dd cb b9 a9 d8 39 0b 64  c6 93 7d 20 ea 51 ff 63  |.....9.d..} .Q.c|
+00000030  97 03 b2 6f a3 d6 55 0d  64 65 2a 5d 3a fe e9 3e  |...o..U.de*]:..>|
+00000040  47 c1 7d c5 d8 03 c6 22  19 2f 6c 5a 00 05 00 00  |G.}...."./lZ....|
 00000050  05 ff 01 00 01 00 16 03  01 02 59 0b 00 02 55 00  |..........Y...U.|
 00000060  02 52 00 02 4f 30 82 02  4b 30 82 01 b4 a0 03 02  |.R..O0..K0......|
 00000070  01 02 02 09 00 e8 f0 9d  3f e2 5b ea a6 30 0d 06  |........?.[..0..|
 00000060  c5 70 0f 08 83 48 e9 48  ef 6e 50 8b 05 7e e5 84  |.p...H.H.nP..~..|
 00000070  25 fa 55 c7 ae 31 02 27  00 ef 3f 98 86 20 12 89  |%.U..1.'..?.. ..|
 00000080  91 59 28 b4 f7 d7 af d2  69 61 35 14 03 01 00 01  |.Y(.....ia5.....|
-00000090  01 16 03 01 00 24 48 fd  e6 fc 4a 94 33 82 22 ff  |.....$H...J.3.".|
-000000a0  af c3 44 98 d2 c6 4e 8a  39 43 dd 4b 2a 11 2b 4e  |..D...N.9C.K*.+N|
-000000b0  5b d9 a4 fc 6c 95 d7 69  05 f9                    |[...l..i..|
+00000090  01 16 03 01 00 24 29 ee  6c 54 d6 21 5e 31 30 9e  |.....$).lT.!^10.|
+000000a0  fd 02 69 bb 32 c2 9e ad  28 b1 2d 94 49 0a 12 0c  |..i.2...(.-.I...|
+000000b0  a1 12 b0 98 a6 33 eb 63  2b e4                    |.....3.c+.|
 >>> Flow 4 (server to client)
-00000000  14 03 01 00 01 01 16 03  01 00 24 61 d2 68 5e 12  |..........$a.h^.|
-00000010  91 6e 7f fe bf b7 42 58  e9 06 38 09 c1 16 34 e5  |.n....BX..8...4.|
-00000020  a1 46 d6 cf 23 ca 48 c1  ed 76 f9 48 a1 9a 2a     |.F..#.H..v.H..*|
+00000000  14 03 01 00 01 01 16 03  01 00 24 32 3e 45 f2 3a  |..........$2>E.:|
+00000010  01 05 50 db 37 25 f6 b5  67 8e 38 3d f5 ba b7 90  |..P.7%..g.8=....|
+00000020  e0 05 a8 cb e0 33 1a 79  ab 44 86 d5 0c fd 86     |.....3.y.D.....|
 >>> Flow 5 (client to server)
-00000000  17 03 01 00 1a 3a e1 39  7c fe 25 50 dc 66 3f b6  |.....:.9|.%P.f?.|
-00000010  6f fd 79 3b 12 83 af 89  b1 c5 f6 75 56 ad a1 15  |o.y;.......uV...|
-00000020  03 01 00 16 07 d1 d3 7a  54 1c 71 0b c8 64 10 46  |.......zT.q..d.F|
-00000030  30 d0 bf df 75 a6 dc 10  b1 d1                    |0...u.....|
+00000000  17 03 01 00 1a ac 0c 1f  12 4e d4 31 10 dd c1 04  |.........N.1....|
+00000010  8b 55 a2 2e a5 f4 e4 80  aa 23 7e bd 79 b0 ee 15  |.U.......#~.y...|
+00000020  03 01 00 16 fa d9 ff 50  7d 41 01 2a d2 13 ee 33  |.......P}A.*...3|
+00000030  52 ab 20 c5 e7 73 81 5d  81 60                    |R. ..s.].`|
index 9d18cd62f78d151a074373c64a34ea8a36367c4c..92cdc4c024738ee7728c5cff95137478c1a7cf0b 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 02 00 59 02 00 00  55 03 02 23 a8 e7 14 3f  |....Y...U..#...?|
-00000010  64 61 3c ee 80 a2 94 84  ab b8 66 76 30 84 06 78  |da<.......fv0..x|
-00000020  96 ba a7 d3 1e 81 1b 16  64 76 88 20 3d 21 21 b3  |........dv. =!!.|
-00000030  45 dd fe cb 5b d7 9a 86  39 ee 4f f8 60 eb 95 ea  |E...[...9.O.`...|
-00000040  ab 64 48 14 74 16 fd e9  47 07 66 60 c0 09 00 00  |.dH.t...G.f`....|
+00000000  16 03 02 00 59 02 00 00  55 03 02 bf ac 6b 91 53  |....Y...U....k.S|
+00000010  dc 1f d6 ee 0e 71 d6 a4  f5 a2 7c f0 10 69 41 dd  |.....q....|..iA.|
+00000020  4a b7 30 53 e6 28 07 31  34 8f e5 20 59 d1 bd e1  |J.0S.(.14.. Y...|
+00000030  20 44 c4 05 07 e9 07 90  5d de 08 73 72 55 04 a6  | D......]..srU..|
+00000040  11 20 bf 32 e0 dd 46 d4  1d ed 45 62 c0 09 00 00  |. .2..F...Eb....|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  02 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
 00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
 00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
 00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
 00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
-00000270  2a 16 03 02 00 b4 0c 00  00 b0 03 00 1d 20 a7 a4  |*............ ..|
-00000280  33 20 48 6a 74 8e 07 fc  c0 b6 10 61 84 d6 67 d1  |3 Hjt......a..g.|
-00000290  ae cf 65 36 4d d5 13 a1  07 fc 1f aa 77 44 00 8a  |..e6M.......wD..|
-000002a0  30 81 87 02 42 01 02 5b  f9 4a af 8d 0a d5 a3 de  |0...B..[.J......|
-000002b0  11 62 d8 f1 db 49 7a 0c  34 3e 2d 61 f9 6f 6b c2  |.b...Iz.4>-a.ok.|
-000002c0  1d 32 4b 88 93 9b 22 b0  3d 09 c3 93 9e 25 31 d6  |.2K...".=....%1.|
-000002d0  5f 06 3a f0 4a 61 0b 06  03 5d 6c 0e b3 5e 48 5a  |_.:.Ja...]l..^HZ|
-000002e0  f0 5b 21 48 58 8f b2 02  41 1c 57 f1 51 04 d6 f8  |.[!HX...A.W.Q...|
-000002f0  a2 51 e6 e6 3e e0 99 63  aa d2 1c 7b 92 be 44 ec  |.Q..>..c...{..D.|
-00000300  86 c3 31 fa e7 9b 98 1a  59 a5 93 3e a9 73 f0 ec  |..1.....Y..>.s..|
-00000310  03 22 37 19 db 78 30 27  ab bf 52 07 6c 3a 79 f5  |."7..x0'..R.l:y.|
-00000320  ad 70 59 76 84 44 f0 47  e0 3d 16 03 02 00 04 0e  |.pYv.D.G.=......|
-00000330  00 00 00                                          |...|
+00000270  2a 16 03 02 00 b5 0c 00  00 b1 03 00 1d 20 ab ea  |*............ ..|
+00000280  ff 17 1e b1 ef f6 22 03  40 8b e1 1a fa ab 01 cf  |......".@.......|
+00000290  0f f0 b0 6d 43 3c 1f 03  a1 d6 4a 9d 79 43 00 8b  |...mC<....J.yC..|
+000002a0  30 81 88 02 42 00 a1 b4  50 4b 9b a3 a5 ec ef dc  |0...B...PK......|
+000002b0  bf c1 a2 65 24 2a 6c aa  ab 26 01 ed d1 ad 2e 37  |...e$*l..&.....7|
+000002c0  4f f5 8b ff 98 ac ef 15  3e d9 46 07 a3 d2 35 de  |O.......>.F...5.|
+000002d0  91 bc 3d a0 1f f1 68 55  28 ef 60 ad 13 05 ac 65  |..=...hU(.`....e|
+000002e0  e5 67 02 3f 85 8b 1b 02  42 01 26 3f fc 62 e3 93  |.g.?....B.&?.b..|
+000002f0  8e fa fb 93 0f 0b ff 68  25 46 ea 71 16 ae 6e d4  |.......h%F.q..n.|
+00000300  36 9e 48 2c 77 2b d8 f5  f6 1d 69 68 ed 28 8f e7  |6.H,w+....ih.(..|
+00000310  79 7e 78 56 52 ff e8 62  fc e2 bd 2e c7 e8 9f 3f  |y~xVR..b.......?|
+00000320  93 47 d2 62 6c f6 5c 0e  a2 b8 fe 16 03 02 00 04  |.G.bl.\.........|
+00000330  0e 00 00 00                                       |....|
 >>> Flow 3 (client to server)
 00000000  16 03 02 00 25 10 00 00  21 20 2f e5 7d a3 47 cd  |....%...! /.}.G.|
 00000010  62 43 15 28 da ac 5f bb  29 07 30 ff f6 84 af c4  |bC.(.._.).0.....|
 00000020  cf c2 ed 90 99 5f 58 cb  3b 74 14 03 02 00 01 01  |....._X.;t......|
 00000030  16 03 02 00 40 00 00 00  00 00 00 00 00 00 00 00  |....@...........|
-00000040  00 00 00 00 00 ef 0f 92  ac 11 fe 97 1a 46 69 e4  |.............Fi.|
-00000050  b3 26 8d d7 92 46 02 25  5b 2e 86 3e 96 3d 64 ed  |.&...F.%[..>.=d.|
-00000060  37 92 dd ae a5 a6 9f 03  f0 c2 42 78 9f b9 78 ac  |7.........Bx..x.|
-00000070  97 ab 82 25 e2                                    |...%.|
+00000040  00 00 00 00 00 0f 55 37  4b 93 d5 ce b1 1c 6f a3  |......U7K.....o.|
+00000050  6d 56 32 f5 de 19 f6 a3  15 b0 6a 90 06 92 60 ca  |mV2.......j...`.|
+00000060  ec 0e 2b d4 24 16 0a 26  f3 bd 3d ca c5 9f d2 9b  |..+.$..&..=.....|
+00000070  79 2f af b6 b0                                    |y/...|
 >>> Flow 4 (server to client)
-00000000  14 03 02 00 01 01 16 03  02 00 40 df a9 23 37 74  |..........@..#7t|
-00000010  47 d8 98 87 53 b4 0a 4d  b0 a5 fb cb d6 37 c8 7c  |G...S..M.....7.||
-00000020  61 95 81 ef b3 63 78 2b  53 c2 86 fc 39 df c4 5f  |a....cx+S...9.._|
-00000030  e4 4b af 1d fe bc 4c fe  1b 6a 28 c3 46 6f 24 94  |.K....L..j(.Fo$.|
-00000040  a8 bf ef ce e8 e8 ad 2c  d9 10 32                 |.......,..2|
+00000000  14 03 02 00 01 01 16 03  02 00 40 4d e3 a9 af 51  |..........@M...Q|
+00000010  f5 d1 cd 04 f1 cf c5 48  0f 2e 0b 6e 57 4c 11 28  |.......H...nWL.(|
+00000020  dd 89 19 14 98 8e 2e 92  db 3c a4 0f 85 32 90 7e  |.........<...2.~|
+00000030  49 13 17 a0 85 fa c6 25  79 24 13 90 86 dc ec 45  |I......%y$.....E|
+00000040  7c 74 35 92 e4 89 04 c2  51 27 66                 ||t5.....Q'f|
 >>> Flow 5 (client to server)
 00000000  17 03 02 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
-00000010  00 00 00 00 00 34 50 ce  9c 7f f5 2d a2 c1 e4 5c  |.....4P....-...\|
-00000020  fa d1 a0 f4 38 e8 4f 51  54 36 07 da f1 af 6d ef  |....8.OQT6....m.|
-00000030  b8 b0 bc bc a6 15 03 02  00 30 00 00 00 00 00 00  |.........0......|
-00000040  00 00 00 00 00 00 00 00  00 00 0b d4 8e e8 69 64  |..............id|
-00000050  53 38 7c 72 d8 1d 9f d5  8a 83 74 a7 37 6b e2 c0  |S8|r......t.7k..|
-00000060  8f 26 e7 5d 0e 06 ae e0  db fb                    |.&.]......|
+00000010  00 00 00 00 00 f9 ac 17  1f 08 b7 80 fb 70 87 e2  |.............p..|
+00000020  53 00 27 60 78 6c 80 5b  57 e7 70 72 8a e3 1b 32  |S.'`xl.[W.pr...2|
+00000030  8c f0 67 82 82 15 03 02  00 30 00 00 00 00 00 00  |..g......0......|
+00000040  00 00 00 00 00 00 00 00  00 00 01 e1 86 47 7f 65  |.............G.e|
+00000050  a9 d2 1c 22 7d 99 7c 41  dc 17 f5 16 40 5b b3 7f  |..."}.|A....@[..|
+00000060  cc 0b 97 41 0c ae 1f 0c  39 e0                    |...A....9.|
index 4cc9610faa970d2c6a870197c858a9275f5bc4e9..b2b7ecb1655a183467ccf23beebd49466c005f7c 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 02 00 59 02 00 00  55 03 02 6e ff 3b 26 66  |....Y...U..n.;&f|
-00000010  7c 32 3f 42 fd 92 7c 12  db 26 b2 45 6e 28 b9 49  ||2?B..|..&.En(.I|
-00000020  86 6b 00 54 92 3b 65 a6  02 6d 94 20 ea 44 db 5c  |.k.T.;e..m. .D.\|
-00000030  d1 39 35 b2 ea 1c 6d 3e  94 bb 47 60 25 1e 9c 74  |.95...m>..G`%..t|
-00000040  e7 bd 54 cc 2b 36 14 6a  12 54 5b 6c c0 13 00 00  |..T.+6.j.T[l....|
+00000000  16 03 02 00 59 02 00 00  55 03 02 95 6e 24 5a ab  |....Y...U...n$Z.|
+00000010  ae 3c 73 52 9d 31 63 50  cf f9 50 99 3c e4 94 22  |.<sR.1cP..P.<.."|
+00000020  5b 6f 0e f8 e3 a8 64 4c  d2 8c 00 20 8b 2d 25 47  |[o....dL... .-%G|
+00000030  f9 74 41 93 b1 82 b5 c5  fc 3e 42 c9 35 fc 68 27  |.tA......>B.5.h'|
+00000040  c4 2b 35 0f f8 1c e3 28  e6 8a 59 dc c0 13 00 00  |.+5....(..Y.....|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  02 02 59 0b 00 02 55 00  02 52 00 02 4f 30 82 02  |..Y...U..R..O0..|
 00000070  4b 30 82 01 b4 a0 03 02  01 02 02 09 00 e8 f0 9d  |K0..............|
 00000290  77 8d 0c 1c f1 0f a1 d8  40 83 61 c9 4c 72 2b 9d  |w.......@.a.Lr+.|
 000002a0  ae db 46 06 06 4d f4 c1  b3 3e c0 d1 bd 42 d4 db  |..F..M...>...B..|
 000002b0  fe 3d 13 60 84 5c 21 d3  3b e9 fa e7 16 03 02 00  |.=.`.\!.;.......|
-000002c0  aa 0c 00 00 a6 03 00 1d  20 82 3b d2 56 dd cd d8  |........ .;.V...|
-000002d0  e1 98 a7 90 d1 08 2d 37  dc e8 21 cd 29 af 29 a5  |......-7..!.).).|
-000002e0  78 8e 59 9e 4c ac c9 d2  4b 00 80 25 20 91 4e 0d  |x.Y.L...K..% .N.|
-000002f0  74 12 9e 1c 98 fb 5f 4b  ad fd c8 68 df 6b 82 98  |t....._K...h.k..|
-00000300  a8 7c ee 17 44 47 91 2a  42 c1 82 d0 ce aa cd f8  |.|..DG.*B.......|
-00000310  69 1e 85 79 27 fe ef 5a  a2 e1 35 30 9a 2d c6 b0  |i..y'..Z..50.-..|
-00000320  43 84 39 7f 8d 68 09 d6  6c 1a 84 0f c0 9a c0 9f  |C.9..h..l.......|
-00000330  64 56 cb fc 32 f2 4a a3  26 e8 c2 5f d7 16 3e 7c  |dV..2.J.&.._..>||
-00000340  4e 8b 89 f8 7f f4 c2 26  fe 01 cd 48 b6 61 9c 93  |N......&...H.a..|
-00000350  1a bc a1 d1 01 c5 bf ef  43 b4 ca 86 62 37 b4 99  |........C...b7..|
-00000360  54 69 db 74 51 92 92 dd  c1 b1 75 16 03 02 00 04  |Ti.tQ.....u.....|
+000002c0  aa 0c 00 00 a6 03 00 1d  20 b5 75 ee e5 26 6b c0  |........ .u..&k.|
+000002d0  af 34 8a 24 f7 c5 25 58  29 38 4c 08 d3 a2 0c 48  |.4.$..%X)8L....H|
+000002e0  18 eb a0 5b e8 64 62 62  78 00 80 d0 1c 9c 11 1a  |...[.dbbx.......|
+000002f0  58 4c 46 5f 18 03 d7 d7  76 47 d5 56 7a bb bd 95  |XLF_....vG.Vz...|
+00000300  16 46 e8 0b 28 6e df 15  65 1a f6 95 fb 4a 6c 42  |.F..(n..e....JlB|
+00000310  1b 4c 5c 30 c5 de d0 83  08 d3 2e 4d 59 7e 7b 1b  |.L\0.......MY~{.|
+00000320  20 9e b5 19 76 fe a3 dd  87 04 f4 9a 3e 3c c0 4a  | ...v.......><.J|
+00000330  16 7f e3 4e 9a 1f 0a 36  1d f5 09 b4 88 09 b1 1b  |...N...6........|
+00000340  9b 60 97 dc d7 ea 97 f4  d6 06 16 45 98 ee 5c 39  |.`.........E..\9|
+00000350  62 3f 7c 82 7b c3 52 59  01 d4 89 8c a6 e2 d5 eb  |b?|.{.RY........|
+00000360  e8 30 a6 78 49 1e ec a5  92 ad 24 16 03 02 00 04  |.0.xI.....$.....|
 00000370  0e 00 00 00                                       |....|
 >>> Flow 3 (client to server)
 00000000  16 03 02 00 25 10 00 00  21 20 2f e5 7d a3 47 cd  |....%...! /.}.G.|
 00000010  62 43 15 28 da ac 5f bb  29 07 30 ff f6 84 af c4  |bC.(.._.).0.....|
 00000020  cf c2 ed 90 99 5f 58 cb  3b 74 14 03 02 00 01 01  |....._X.;t......|
 00000030  16 03 02 00 40 00 00 00  00 00 00 00 00 00 00 00  |....@...........|
-00000040  00 00 00 00 00 c5 bf e6  b3 86 12 92 df 68 fa 75  |.............h.u|
-00000050  79 5f ee fe 60 91 d1 fd  8a 48 3b 97 b4 da 7f 58  |y_..`....H;....X|
-00000060  3e 7e 40 d7 93 1d 6b e2  0e 2a a4 45 20 e0 9d f9  |>~@...k..*.E ...|
-00000070  b6 5e b1 f1 4f                                    |.^..O|
+00000040  00 00 00 00 00 28 ab ed  77 d3 56 29 a8 4a 38 c8  |.....(..w.V).J8.|
+00000050  64 1c a5 d9 4e f9 6b 0e  fa 82 42 ad 0d be 15 69  |d...N.k...B....i|
+00000060  9a ff 79 64 db 8f 3e 16  b3 86 93 82 6f 78 c4 2e  |..yd..>.....ox..|
+00000070  7c 54 6c 4f 90                                    ||TlO.|
 >>> Flow 4 (server to client)
-00000000  14 03 02 00 01 01 16 03  02 00 40 bf 58 92 80 02  |..........@.X...|
-00000010  75 91 40 30 35 e0 16 76  f4 97 bd 77 46 a3 a3 4e  |u.@05..v...wF..N|
-00000020  f1 be 53 eb b8 56 45 b1  71 c9 f8 a9 bf c6 9a 00  |..S..VE.q.......|
-00000030  83 46 91 88 d5 7b 72 95  27 33 80 43 3f 3e f6 60  |.F...{r.'3.C?>.`|
-00000040  c6 55 90 6a 87 8e 7d 48  27 e2 40                 |.U.j..}H'.@|
+00000000  14 03 02 00 01 01 16 03  02 00 40 15 e9 c5 15 59  |..........@....Y|
+00000010  b3 0d 46 22 0c ae a6 41  02 b4 f3 da 11 dc 85 79  |..F"...A.......y|
+00000020  bb d9 3f 23 38 51 24 1a  08 b5 a0 63 dc 4b 86 50  |..?#8Q$....c.K.P|
+00000030  ef b2 32 07 fd b5 e1 01  06 19 42 ce ba 69 ab 1a  |..2.......B..i..|
+00000040  c9 bb db 7d d0 9f f9 7c  f2 6c 18                 |...}...|.l.|
 >>> Flow 5 (client to server)
 00000000  17 03 02 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
-00000010  00 00 00 00 00 f5 6b bc  6d 2c 70 b1 c0 f0 ab 78  |......k.m,p....x|
-00000020  44 c9 97 f6 59 ef 15 e4  05 cf e0 55 ee a4 68 8c  |D...Y......U..h.|
-00000030  86 57 82 bd 84 15 03 02  00 30 00 00 00 00 00 00  |.W.......0......|
-00000040  00 00 00 00 00 00 00 00  00 00 ef b2 a9 a5 bb a3  |................|
-00000050  6e e5 d1 2b ef 83 1d 11  de 29 d2 30 2c fc 78 73  |n..+.....).0,.xs|
-00000060  6b 6e 0a d2 55 67 5c d4  58 b3                    |kn..Ug\.X.|
+00000010  00 00 00 00 00 67 ef de  df a4 91 69 58 b8 3f 06  |.....g.....iX.?.|
+00000020  c4 05 4e ad 88 9b c5 12  35 cf 63 39 3a 61 e9 4c  |..N.....5.c9:a.L|
+00000030  49 22 93 f4 10 15 03 02  00 30 00 00 00 00 00 00  |I".......0......|
+00000040  00 00 00 00 00 00 00 00  00 00 00 2a 5a ba 39 7e  |...........*Z.9~|
+00000050  a8 be 2e 72 f3 ba 7e 0a  32 b5 8c d8 f5 1b 93 6c  |...r..~.2......l|
+00000060  3e 35 d8 ba cc f3 9f f4  19 74                    |>5.......t|
index 9dae5dd6d2bf6dcafdaff95f046b8cc1c92d8d7e..aeba311f51fe20cdb7002bf7f86f66593e8bee81 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 02 00 51 02 00 00  4d 03 02 96 ca 2a e7 23  |....Q...M....*.#|
-00000010  af 2e 45 62 15 fa 5a 84  bc aa 7c 79 03 1b 37 69  |..Eb..Z...|y..7i|
-00000020  a0 77 ce 03 81 b7 e5 7d  31 34 6e 20 93 83 5d 7c  |.w.....}14n ..]||
-00000030  e8 c7 48 f9 67 ec 97 b1  27 b6 de de 89 07 5a cf  |..H.g...'.....Z.|
-00000040  44 77 48 4b e9 62 43 e3  87 fd de 87 00 05 00 00  |DwHK.bC.........|
+00000000  16 03 02 00 51 02 00 00  4d 03 02 82 5b 12 ac 33  |....Q...M...[..3|
+00000010  08 d4 28 8c 91 6e 52 c4  c6 09 13 24 bf 42 d2 37  |..(..nR....$.B.7|
+00000020  6d 78 60 b0 ea bd 9e b3  08 99 43 20 05 5a 93 f9  |mx`.......C .Z..|
+00000030  a4 39 43 4f c4 e3 27 20  7d 4c fa 7a 28 c1 c7 33  |.9CO..' }L.z(..3|
+00000040  72 fa 14 b8 ba c3 89 b0  a5 54 a3 7c 00 05 00 00  |r........T.|....|
 00000050  05 ff 01 00 01 00 16 03  02 02 59 0b 00 02 55 00  |..........Y...U.|
 00000060  02 52 00 02 4f 30 82 02  4b 30 82 01 b4 a0 03 02  |.R..O0..K0......|
 00000070  01 02 02 09 00 e8 f0 9d  3f e2 5b ea a6 30 0d 06  |........?.[..0..|
 00000060  c5 70 0f 08 83 48 e9 48  ef 6e 50 8b 05 7e e5 84  |.p...H.H.nP..~..|
 00000070  25 fa 55 c7 ae 31 02 27  00 ef 3f 98 86 20 12 89  |%.U..1.'..?.. ..|
 00000080  91 59 28 b4 f7 d7 af d2  69 61 35 14 03 02 00 01  |.Y(.....ia5.....|
-00000090  01 16 03 02 00 24 33 5d  7f cb 6e 36 19 8b db 35  |.....$3]..n6...5|
-000000a0  88 16 87 7a 9d 5a 51 27  51 13 17 64 0e 57 d5 e1  |...z.ZQ'Q..d.W..|
-000000b0  6e 34 8d e6 99 a8 38 b2  e7 3a                    |n4....8..:|
+00000090  01 16 03 02 00 24 e1 1a  bf e9 fd 4c fb 56 41 82  |.....$.....L.VA.|
+000000a0  c2 48 fc ca d9 d5 ec 2a  0a ee 63 25 e0 5f 53 cf  |.H.....*..c%._S.|
+000000b0  24 ff fe da 6f f5 8b 61  b7 b9                    |$...o..a..|
 >>> Flow 4 (server to client)
-00000000  14 03 02 00 01 01 16 03  02 00 24 e0 8b 90 9b 83  |..........$.....|
-00000010  f5 3d 00 e9 cf 7b 1d 75  cf c8 16 f2 29 8d de 0b  |.=...{.u....)...|
-00000020  75 82 b1 c4 6e 1c 1f ab  e9 90 74 31 99 f2 ad     |u...n.....t1...|
+00000000  14 03 02 00 01 01 16 03  02 00 24 99 2c e7 fa d0  |..........$.,...|
+00000010  29 d9 92 07 39 56 b0 0c  ad 23 30 c8 d7 0b 38 da  |)...9V...#0...8.|
+00000020  6f d3 c7 f9 66 d2 ec 8c  52 85 cb db a6 22 50     |o...f...R...."P|
 >>> Flow 5 (client to server)
-00000000  17 03 02 00 1a ca 2a 95  13 de 40 0d af 44 a4 aa  |......*...@..D..|
-00000010  9a 35 d7 38 c7 9f 74 4f  3a bf d1 9c cd 9e ee 15  |.5.8..tO:.......|
-00000020  03 02 00 16 d3 a4 32 78  a9 00 1b 7a 48 3e 7c 2b  |......2x...zH>|+|
-00000030  f9 3b 92 32 20 0b f4 16  39 18                    |.;.2 ...9.|
+00000000  17 03 02 00 1a 9f 70 c4  77 f3 0a a8 e0 1a 75 87  |......p.w.....u.|
+00000010  ab 2a f1 23 52 79 9f 5c  8e af 5d ba 27 45 f9 15  |.*.#Ry.\..].'E..|
+00000020  03 02 00 16 f0 28 f3 71  a0 97 6b ba 7e 97 81 85  |.....(.q..k.~...|
+00000030  11 59 1b c9 fa a0 48 32  e9 65                    |.Y....H2.e|
index 4412f53c90ac0c10d80a38bf0677583604cf8000..ce928728b416a302b92577b51d6cbc862d7bf8df 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 51 02 00 00  4d 03 03 1d be be 1e eb  |....Q...M.......|
-00000010  59 2c d5 07 b9 7a 64 47  95 84 ef cf d9 3e 82 4c  |Y,...zdG.....>.L|
-00000020  00 c0 0a 69 8a 01 2a b3  42 78 02 20 5e 32 5c 88  |...i..*.Bx. ^2\.|
-00000030  50 ed d5 44 41 4f bf a9  4e 49 83 5d aa 7c 2e 5d  |P..DAO..NI.].|.]|
-00000040  85 e8 64 92 5e 49 5d 8a  d0 0e 89 eb 00 9c 00 00  |..d.^I].........|
+00000000  16 03 03 00 51 02 00 00  4d 03 03 a4 26 bb e9 70  |....Q...M...&..p|
+00000010  57 4e ec f8 ea 23 01 75  c3 f3 a9 d4 d6 e8 71 2b  |WN...#.u......q+|
+00000020  01 5e c0 73 19 2b b9 d8  8e 3e d1 20 c8 c3 0a 22  |.^.s.+...>. ..."|
+00000030  7b ee cd 2e c9 e8 95 db  90 db 70 f5 59 e6 90 65  |{.........p.Y..e|
+00000040  35 87 a6 d4 bb dd 85 34  43 e8 66 49 00 9c 00 00  |5......4C.fI....|
 00000050  05 ff 01 00 01 00 16 03  03 02 59 0b 00 02 55 00  |..........Y...U.|
 00000060  02 52 00 02 4f 30 82 02  4b 30 82 01 b4 a0 03 02  |.R..O0..K0......|
 00000070  01 02 02 09 00 e8 f0 9d  3f e2 5b ea a6 30 0d 06  |........?.[..0..|
 00000060  c5 70 0f 08 83 48 e9 48  ef 6e 50 8b 05 7e e5 84  |.p...H.H.nP..~..|
 00000070  25 fa 55 c7 ae 31 02 27  00 ef 3f 98 86 20 12 89  |%.U..1.'..?.. ..|
 00000080  91 59 28 b4 f7 d7 af d2  69 61 35 14 03 03 00 01  |.Y(.....ia5.....|
-00000090  01 16 03 03 00 28 00 00  00 00 00 00 00 00 69 38  |.....(........i8|
-000000a0  97 84 2e 77 5c b8 58 82  b5 78 85 2e f3 7b 92 81  |...w\.X..x...{..|
-000000b0  00 72 91 23 41 ae 59 6c  18 64 f0 62 f2 c9        |.r.#A.Yl.d.b..|
+00000090  01 16 03 03 00 28 00 00  00 00 00 00 00 00 64 6c  |.....(........dl|
+000000a0  08 78 1d 03 0c ed dd 01  30 d4 fb 7c 3f 24 45 cc  |.x......0..|?$E.|
+000000b0  f6 b2 e3 42 07 93 8f 34  a8 21 d1 b0 08 e3        |...B...4.!....|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 28 37 f7 98 2f 78  |..........(7../x|
-00000010  54 85 5f 2e cb a9 b7 bf  4b 2d 62 06 e2 32 cd 18  |T._.....K-b..2..|
-00000020  de f5 54 c8 e0 54 2d c5  b4 98 07 7e c7 b7 79 a0  |..T..T-....~..y.|
-00000030  75 af 5c                                          |u.\|
+00000000  14 03 03 00 01 01 16 03  03 00 28 75 9b 91 cd 7d  |..........(u...}|
+00000010  8d f7 3c a0 d6 5e d4 f2  24 1a 0a f3 04 b1 d9 0b  |..<..^..$.......|
+00000020  1d 31 ca 1c 8b e7 38 c0  8e 7d 12 19 89 33 28 4d  |.1....8..}...3(M|
+00000030  83 28 b6                                          |.(.|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 78 c1 c0  |.............x..|
-00000010  7d 1b a8 b2 80 0e a3 64  cf e0 fa 71 9d 37 5d 32  |}......d...q.7]2|
-00000020  8d 36 38 15 03 03 00 1a  00 00 00 00 00 00 00 02  |.68.............|
-00000030  c2 f3 41 1a 2c a4 4f 48  fa 61 14 40 60 51 e5 99  |..A.,.OH.a.@`Q..|
-00000040  c6 e5                                             |..|
+00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 7d fe 53  |.............}.S|
+00000010  73 aa ca 3d f3 27 b7 01  56 9e e7 c9 6d 79 2a 97  |s..=.'..V...my*.|
+00000020  b2 21 42 15 03 03 00 1a  00 00 00 00 00 00 00 02  |.!B.............|
+00000030  de bd 3e 9e 8f c0 98 ec  bd b4 9b 89 90 a2 26 a8  |..>...........&.|
+00000040  28 97                                             |(.|
index d7568843b48a7afbf12b1c3296c40eeeed76298e..15394c7e34b3954bcd81d4ced22206fbb7c0e9a3 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 51 02 00 00  4d 03 03 c3 41 d7 9c 1b  |....Q...M...A...|
-00000010  9a ff f8 17 af 41 df 8d  96 70 bb b8 f6 9a 4c a2  |.....A...p....L.|
-00000020  03 25 31 2c 58 fa 05 5b  12 85 6a 20 18 3c 34 d6  |.%1,X..[..j .<4.|
-00000030  08 44 46 a5 5c b1 40 0d  38 33 c0 2d ea a6 46 53  |.DF.\.@.83.-..FS|
-00000040  0e 09 39 6f 11 35 02 63  cf 21 74 c2 00 3c 00 00  |..9o.5.c.!t..<..|
+00000000  16 03 03 00 51 02 00 00  4d 03 03 8a a8 2c 00 d8  |....Q...M....,..|
+00000010  d8 87 53 14 1e 7b ff ca  19 a2 6d bc 47 6f 73 12  |..S..{....m.Gos.|
+00000020  0d 54 6e 33 21 80 01 86  f8 81 9f 20 46 f6 8c e8  |.Tn3!...... F...|
+00000030  8b 90 02 b2 da e2 83 3a  2a 0f b3 f7 96 2b f8 96  |.......:*....+..|
+00000040  56 77 39 52 9e a1 bd 74  1e 2e b1 b0 00 3c 00 00  |Vw9R...t.....<..|
 00000050  05 ff 01 00 01 00 16 03  03 02 59 0b 00 02 55 00  |..........Y...U.|
 00000060  02 52 00 02 4f 30 82 02  4b 30 82 01 b4 a0 03 02  |.R..O0..K0......|
 00000070  01 02 02 09 00 e8 f0 9d  3f e2 5b ea a6 30 0d 06  |........?.[..0..|
 00000070  25 fa 55 c7 ae 31 02 27  00 ef 3f 98 86 20 12 89  |%.U..1.'..?.. ..|
 00000080  91 59 28 b4 f7 d7 af d2  69 61 35 14 03 03 00 01  |.Y(.....ia5.....|
 00000090  01 16 03 03 00 50 00 00  00 00 00 00 00 00 00 00  |.....P..........|
-000000a0  00 00 00 00 00 00 88 20  99 51 5e fb 72 79 7f f8  |....... .Q^.ry..|
-000000b0  b2 a9 56 96 a3 03 1d a0  e0 38 1a be 4c ea 80 f9  |..V......8..L...|
-000000c0  c0 ef 45 81 91 7f b9 1b  f7 91 3b 4e 05 87 d6 73  |..E.......;N...s|
-000000d0  c0 27 94 50 4f 00 ee c1  02 af 5f 6f 4c a5 0e 5b  |.'.PO....._oL..[|
-000000e0  6c 76 87 28 b4 bf                                 |lv.(..|
+000000a0  00 00 00 00 00 00 8f d8  ac 7f ec 16 9e d8 e9 f2  |................|
+000000b0  ce 30 51 dc 87 e0 f9 80  57 66 d9 87 20 77 3a b1  |.0Q.....Wf.. w:.|
+000000c0  43 db fc 36 f5 64 6e 96  e9 b8 e2 ab bb 00 48 36  |C..6.dn.......H6|
+000000d0  60 9c 5a 7c 38 3f 13 e1  9c ef d9 15 96 91 56 e2  |`.Z|8?........V.|
+000000e0  87 2e 23 1a 98 40                                 |..#..@|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 50 93 14 a5 13 16  |..........P.....|
-00000010  d7 af 14 81 94 33 2d ae  f7 7a b1 b1 a5 38 fb e8  |.....3-..z...8..|
-00000020  c8 38 b3 ce f1 eb 70 e7  84 b6 fc 25 25 32 a9 09  |.8....p....%%2..|
-00000030  d1 0d 2d 59 57 6d d0 42  e8 c1 81 92 d0 af fb 5a  |..-YWm.B.......Z|
-00000040  08 7e 0f 3d 10 e5 42 6d  27 cd 8c 32 b2 20 4b 0a  |.~.=..Bm'..2. K.|
-00000050  75 76 ed 08 54 fe 74 94  72 35 9e                 |uv..T.t.r5.|
+00000000  14 03 03 00 01 01 16 03  03 00 50 80 01 08 cc d8  |..........P.....|
+00000010  08 a8 81 20 b2 bb 5b 50  79 74 4a b5 10 c4 7a 30  |... ..[PytJ...z0|
+00000020  6c 46 d6 e5 36 6e 4d cc  e5 0c 2c ab 3b de 92 45  |lF..6nM...,.;..E|
+00000030  ee 20 58 a9 0f 03 26 3e  6c 05 a7 ef f2 7c a7 9b  |. X...&>l....|..|
+00000040  57 c0 20 8d d0 69 0e b0  5a cc e6 26 5f e2 c3 24  |W. ..i..Z..&_..$|
+00000050  c4 db df 20 03 08 e1 aa  59 2b d2                 |... ....Y+.|
 >>> Flow 5 (client to server)
 00000000  17 03 03 00 40 00 00 00  00 00 00 00 00 00 00 00  |....@...........|
-00000010  00 00 00 00 00 53 91 38  34 33 20 94 0d 76 d7 72  |.....S.843 ..v.r|
-00000020  48 f3 17 34 01 ae 0e 89  db 60 f1 4e 64 a5 cf 0c  |H..4.....`.Nd...|
-00000030  32 52 3f a0 18 f8 c5 57  ed 3a d1 41 19 81 cf 0a  |2R?....W.:.A....|
-00000040  f2 d8 90 4b ba 15 03 03  00 40 00 00 00 00 00 00  |...K.....@......|
-00000050  00 00 00 00 00 00 00 00  00 00 05 2b 31 3c 1b a2  |...........+1<..|
-00000060  11 87 5f 0f 49 72 bb 67  e6 75 18 9c b1 f4 6c ed  |.._.Ir.g.u....l.|
-00000070  4d 01 58 35 30 43 44 e8  ee 1d f2 81 9d 67 6d 77  |M.X50CD......gmw|
-00000080  1e 36 61 7f f3 32 3d 60  73 6d                    |.6a..2=`sm|
+00000010  00 00 00 00 00 a2 dd a6  ff 57 60 80 dd 97 cf 20  |.........W`.... |
+00000020  10 04 60 80 53 17 37 ce  ce 39 b6 21 f4 06 61 aa  |..`.S.7..9.!..a.|
+00000030  49 7b f0 d5 e0 72 4c 6f  38 d2 ab af 1c 94 bd 5b  |I{...rLo8......[|
+00000040  1b ee 8a 9b e3 15 03 03  00 40 00 00 00 00 00 00  |.........@......|
+00000050  00 00 00 00 00 00 00 00  00 00 ba 18 32 e7 6d f5  |............2.m.|
+00000060  fa 2e 61 55 cc fe 3c 4d  19 fd 84 6d c4 2a 46 92  |..aU..<M...m.*F.|
+00000070  ae b7 f3 67 c8 3c ce cd  b0 66 de ee 5d 3f 07 3b  |...g.<...f..]?.;|
+00000080  a9 85 a1 93 1f 98 f7 95  c9 ac                    |..........|
index 2f552cbb62747527470fc4c0e352ff1861baf308..766bf95067a6e9c0cab421e32e30d39cf0a0bc35 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 51 02 00 00  4d 03 03 2b 59 94 f3 9e  |....Q...M..+Y...|
-00000010  23 ae d3 58 82 1f 2e be  38 1d 14 e4 4c a4 b8 ed  |#..X....8...L...|
-00000020  95 08 b9 44 60 02 4b 0b  a9 6e ae 20 9b 43 e5 2a  |...D`.K..n. .C.*|
-00000030  0f 08 8e a4 c1 c0 15 79  9f af a5 ab a3 67 9d 09  |.......y.....g..|
-00000040  23 0e 8e 96 a9 aa 7d 26  74 d8 0c 9a 00 9d 00 00  |#.....}&t.......|
+00000000  16 03 03 00 51 02 00 00  4d 03 03 de 7a 77 5b eb  |....Q...M...zw[.|
+00000010  fa 84 a0 ac ba 3b ca 25  dc b3 c0 06 44 da 31 5c  |.....;.%....D.1\|
+00000020  27 e0 4e af be 47 07 5a  a5 ab 20 20 72 b2 67 0c  |'.N..G.Z..  r.g.|
+00000030  7e 71 5d e3 55 89 91 27  7f 65 ac 71 c6 e8 a5 4a  |~q].U..'.e.q...J|
+00000040  ae e1 a2 0d 3f a6 62 08  17 7e 26 fd 00 9d 00 00  |....?.b..~&.....|
 00000050  05 ff 01 00 01 00 16 03  03 02 59 0b 00 02 55 00  |..........Y...U.|
 00000060  02 52 00 02 4f 30 82 02  4b 30 82 01 b4 a0 03 02  |.R..O0..K0......|
 00000070  01 02 02 09 00 e8 f0 9d  3f e2 5b ea a6 30 0d 06  |........?.[..0..|
 00000060  c5 70 0f 08 83 48 e9 48  ef 6e 50 8b 05 7e e5 84  |.p...H.H.nP..~..|
 00000070  25 fa 55 c7 ae 31 02 27  00 ef 3f 98 86 20 12 89  |%.U..1.'..?.. ..|
 00000080  91 59 28 b4 f7 d7 af d2  69 61 35 14 03 03 00 01  |.Y(.....ia5.....|
-00000090  01 16 03 03 00 28 00 00  00 00 00 00 00 00 59 fc  |.....(........Y.|
-000000a0  aa b1 84 ab 09 82 00 88  8e e4 82 6e cd 24 9f b5  |...........n.$..|
-000000b0  01 95 d3 c3 f4 a2 16 54  25 91 77 76 fc f0        |.......T%.wv..|
+00000090  01 16 03 03 00 28 00 00  00 00 00 00 00 00 0b 7d  |.....(.........}|
+000000a0  83 0f 79 e2 4b ef d3 0e  ff 57 d2 55 cd ea e9 be  |..y.K....W.U....|
+000000b0  8b 38 1e 33 b0 6a eb e3  aa 51 52 82 e6 15        |.8.3.j...QR...|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 28 67 ac 20 d9 b6  |..........(g. ..|
-00000010  a9 f0 ec f6 7b 34 31 3a  5e 06 20 0f 5b 32 86 1b  |....{41:^. .[2..|
-00000020  da 5a c5 54 47 d0 ad 4f  95 2c b5 1f 17 3f ec 17  |.Z.TG..O.,...?..|
-00000030  a3 01 fc                                          |...|
+00000000  14 03 03 00 01 01 16 03  03 00 28 1a a3 bb d4 c4  |..........(.....|
+00000010  53 c7 5c 09 8c fb e7 51  41 73 d5 76 ef e6 40 9a  |S.\....QAs.v..@.|
+00000020  06 27 c6 e8 9f 1b 25 f5  d1 7b 39 b7 74 ab e8 83  |.'....%..{9.t...|
+00000030  26 f6 40                                          |&.@|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 6c 9c 0a  |.............l..|
-00000010  ae 0b 40 57 8b 24 6d 09  77 ae 2f 14 be 06 26 9e  |..@W.$m.w./...&.|
-00000020  0a bf 18 15 03 03 00 1a  00 00 00 00 00 00 00 02  |................|
-00000030  32 50 20 68 3d 05 68 ed  0c ac 7a db 24 21 7e e0  |2P h=.h...z.$!~.|
-00000040  9e f0                                             |..|
+00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 1c 0d 06  |................|
+00000010  d2 25 8a 06 d9 b4 d6 76  89 1c c6 b7 22 9f 44 63  |.%.....v....".Dc|
+00000020  a3 f9 89 15 03 03 00 1a  00 00 00 00 00 00 00 02  |................|
+00000030  cb 34 e8 4b f7 b1 ab 1a  74 60 2c 2d cf a4 7d 9f  |.4.K....t`,-..}.|
+00000040  f4 b4                                             |..|
index 358b211fc19d18ecb977206e757f9e5627b70d82..8b9a510c4cdea354b6400cb17efe8f68e305325d 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 8f 00 05 00 05  01 00 00 00 00 00 0a 00  |................|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 00000100  bb 29 07 30 ff f6 84 af  c4 cf c2 ed 90 99 5f 58  |.).0.........._X|
 00000110  cb 3b 74                                          |.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 66 02 00 00  62 03 03 95 14 55 52 0b  |....f...b....UR.|
-00000010  e7 c1 15 6b dc 19 3b 17  9e bb 6a b7 61 82 dc 59  |...k..;...j.a..Y|
-00000020  d3 a4 7c e1 c3 83 cc e2  e5 56 e0 20 3c 82 0d 54  |..|......V. <..T|
-00000030  2b 78 fe 50 cb 4e c1 69  d7 6f b3 9f ac 2e 27 c8  |+x.P.N.i.o....'.|
-00000040  c6 7a 70 27 1e 14 67 43  4c f1 7d d7 cc a8 00 00  |.zp'..gCL.}.....|
+00000000  16 03 03 00 66 02 00 00  62 03 03 2d b3 e1 a8 44  |....f...b..-...D|
+00000010  c6 3e 20 b9 50 49 ab b8  48 c3 bf d6 f3 7b 2e 0a  |.> .PI..H....{..|
+00000020  8c 49 ba e5 8e 54 5e 02  59 01 75 20 f0 a0 60 c2  |.I...T^.Y.u ..`.|
+00000030  81 df 62 f9 f8 7d 3c 3c  ee 1e 0c 1d c2 11 58 7f  |..b..}<<......X.|
+00000040  e0 dc b1 6c 17 9e 19 60  ca c2 40 84 cc a8 00 00  |...l...`..@.....|
 00000050  1a ff 01 00 01 00 00 0b  00 04 03 00 01 02 00 10  |................|
 00000060  00 09 00 07 06 70 72 6f  74 6f 31 16 03 03 02 59  |.....proto1....Y|
 00000070  0b 00 02 55 00 02 52 00  02 4f 30 82 02 4b 30 82  |...U..R..O0..K0.|
 000002a0  1c f1 0f a1 d8 40 83 61  c9 4c 72 2b 9d ae db 46  |.....@.a.Lr+...F|
 000002b0  06 06 4d f4 c1 b3 3e c0  d1 bd 42 d4 db fe 3d 13  |..M...>...B...=.|
 000002c0  60 84 5c 21 d3 3b e9 fa  e7 16 03 03 00 ac 0c 00  |`.\!.;..........|
-000002d0  00 a8 03 00 1d 20 c3 e3  43 9c 5d 0f 09 61 ae 18  |..... ..C.]..a..|
-000002e0  66 05 b1 7d c1 9f e5 26  9c a7 97 d6 1f 9a 7c ff  |f..}...&......|.|
-000002f0  8c 34 a1 32 a2 35 08 04  00 80 6c 50 a1 80 d9 20  |.4.2.5....lP... |
-00000300  56 08 da d9 5b 77 4d ad  43 66 71 15 ec fe db 02  |V...[wM.Cfq.....|
-00000310  fb 40 d8 8d 67 22 e2 1b  ec 8d b9 4e ba 65 01 8b  |.@..g".....N.e..|
-00000320  70 e0 83 bc 06 1b 14 8f  07 cf a6 08 58 c3 77 94  |p...........X.w.|
-00000330  0f 94 53 62 54 6c 1f 92  22 9d ae f8 5a ad d5 f3  |..SbTl.."...Z...|
-00000340  8a f7 e6 93 8c 0e 48 1b  23 89 d8 bd e9 5c 50 cd  |......H.#....\P.|
-00000350  07 3d 7e 8e b0 d6 65 44  58 62 03 a1 d9 94 72 f0  |.=~...eDXb....r.|
-00000360  25 a9 e0 c1 be ac 32 05  59 f7 7f 6e 13 23 70 5a  |%.....2.Y..n.#pZ|
-00000370  65 ba a2 d7 da 3c a2 9e  6b 13 16 03 03 00 04 0e  |e....<..k.......|
+000002d0  00 a8 03 00 1d 20 7b 47  ec ef 4d 39 ec 65 b9 7c  |..... {G..M9.e.||
+000002e0  08 da b5 41 0d 62 0b 52  29 24 25 3d 39 21 ed d3  |...A.b.R)$%=9!..|
+000002f0  30 37 0c 15 66 49 08 04  00 80 4b 01 8e 80 78 ed  |07..fI....K...x.|
+00000300  d1 44 e5 98 a4 43 9a 73  b7 dc 67 72 83 29 f3 e3  |.D...C.s..gr.)..|
+00000310  5b 72 ee d6 36 12 db bf  ab d6 86 fd a8 54 a5 a0  |[r..6........T..|
+00000320  0e 76 ca ea a7 f5 f2 e1  87 94 a7 c5 d8 69 b7 58  |.v...........i.X|
+00000330  d2 f0 10 08 8c 08 ac bd  aa 60 f5 45 20 15 77 71  |.........`.E .wq|
+00000340  5a bb 2a 8b 0a 4b a3 08  71 88 82 01 3c bc 54 ba  |Z.*..K..q...<.T.|
+00000350  f4 42 7a 08 64 d7 57 5b  dc ea 6a 72 e1 7d ca 96  |.Bz.d.W[..jr.}..|
+00000360  d9 89 eb 60 9e d2 a4 f5  cb d5 45 d1 4d 09 4e 18  |...`......E.M.N.|
+00000370  a2 4f 0f 59 97 a1 5f 7f  65 4f 16 03 03 00 04 0e  |.O.Y.._.eO......|
 00000380  00 00 00                                          |...|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 25 10 00 00  21 20 2f e5 7d a3 47 cd  |....%...! /.}.G.|
 00000010  62 43 15 28 da ac 5f bb  29 07 30 ff f6 84 af c4  |bC.(.._.).0.....|
 00000020  cf c2 ed 90 99 5f 58 cb  3b 74 14 03 03 00 01 01  |....._X.;t......|
-00000030  16 03 03 00 20 5e 91 45  7d ab 7c b7 6f 57 a6 d0  |.... ^.E}.|.oW..|
-00000040  17 83 cb 40 1b 76 6b 5e  80 39 03 2f 6d 2f 10 8e  |...@.vk^.9./m/..|
-00000050  74 33 12 54 8d                                    |t3.T.|
+00000030  16 03 03 00 20 b9 f7 58  6f d3 29 b8 41 35 06 b7  |.... ..Xo.).A5..|
+00000040  55 85 c1 f0 63 fe 4f 5f  87 01 cc 67 0b f1 4c b4  |U...c.O_...g..L.|
+00000050  ca 92 bd c0 6d                                    |....m|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 20 f1 3c 7a 28 eb  |.......... .<z(.|
-00000010  0a b1 bf 42 28 de 07 83  76 c6 2c 94 b7 d5 ef f3  |...B(...v.,.....|
-00000020  0b 9c 0c 2e d3 ab 8a a9  03 d2 c0                 |...........|
+00000000  14 03 03 00 01 01 16 03  03 00 20 68 92 93 84 bd  |.......... h....|
+00000010  0e de 33 1b db ca 54 b8  a0 2f 53 c5 76 de d2 c5  |..3...T../S.v...|
+00000020  7a 54 bb db 0c 08 86 79  d2 6c 58                 |zT.....y.lX|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 16 dc f6 18  54 22 e0 9c 08 bf db a8  |........T"......|
-00000010  62 2a 64 9e 06 43 0f 22  18 0e 34 15 03 03 00 12  |b*d..C."..4.....|
-00000020  20 2f f4 76 cd dc 82 eb  30 f9 e0 42 6b 29 16 ed  | /.v....0..Bk)..|
-00000030  7c f0                                             ||.|
+00000000  17 03 03 00 16 79 38 07  9b be 83 44 9a 3e 11 1a  |.....y8....D.>..|
+00000010  99 2f f2 4e 33 84 0b c7  8e ed c3 15 03 03 00 12  |./.N3...........|
+00000020  ca bd 7e 59 04 8c e0 52  80 1e 56 1e af c1 5f 61  |..~Y...R..V..._a|
+00000030  6c 6a                                             |lj|
index e40999fb852cb7e442da4f268f01e436b77c4dcc..e1fb8a8e76ba8b14a620a4d997e4686b676a3a91 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 08 a4 b1 ad 21  |....Y...U......!|
-00000010  3a 60 7a d3 3b 60 67 48  5d de da ff 3f a8 55 a9  |:`z.;`gH]...?.U.|
-00000020  c4 72 69 32 12 c1 d1 4e  d4 78 e1 20 6e 9f ed 1e  |.ri2...N.x. n...|
-00000030  50 9a 31 e2 ae e2 6a f4  01 cc 94 21 25 73 f3 a5  |P.1...j....!%s..|
-00000040  f6 28 b3 c6 6b c1 b3 2d  fc 0c d3 66 c0 09 00 00  |.(..k..-...f....|
+00000000  16 03 03 00 59 02 00 00  55 03 03 36 60 84 12 26  |....Y...U..6`..&|
+00000010  51 e4 32 33 26 ef c3 31  bf ea ac 27 0f c3 fb cb  |Q.23&..1...'....|
+00000020  05 89 af df 56 a9 3f 14  6e 5e 2c 20 ad 6e 60 2d  |....V.?.n^, .n`-|
+00000030  94 aa e5 73 22 eb 68 92  77 1c 6c cb f4 5a 14 f2  |...s".h.w.l..Z..|
+00000040  29 85 88 aa 2e 56 2a ad  80 e1 f0 b1 c0 09 00 00  |)....V*.........|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
 00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
 00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
 00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
 00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
-00000270  2a 16 03 03 00 b7 0c 00  00 b3 03 00 1d 20 ec f3  |*............ ..|
-00000280  2b 3b be 93 68 53 f2 ab  6c 97 5a fa 9b 8c bf eb  |+;..hS..l.Z.....|
-00000290  37 6f af d7 b8 02 f3 8c  0b f9 75 29 11 32 04 03  |7o........u).2..|
-000002a0  00 8b 30 81 88 02 42 01  9d 90 aa b3 19 d2 9d cf  |..0...B.........|
-000002b0  92 c1 64 05 89 db d0 dd  80 f3 a4 7e 09 ec 36 22  |..d........~..6"|
-000002c0  95 79 c4 36 0e 21 80 7d  4b 72 a5 38 a4 b0 a7 5f  |.y.6.!.}Kr.8..._|
-000002d0  fb ae f7 66 23 82 91 c2  f8 95 df 60 ce dc e8 1a  |...f#......`....|
-000002e0  3f 2b 2c fa 5e 58 67 98  78 02 42 00 fa 88 7f ae  |?+,.^Xg.x.B.....|
-000002f0  00 55 2c a1 c2 47 ed c8  11 74 64 e7 c6 30 63 fb  |.U,..G...td..0c.|
-00000300  bb 42 2a 02 9b 80 60 88  e7 3f af 17 a3 7f 1e f6  |.B*...`..?......|
-00000310  31 9c 1f 8c 89 e5 a0 b1  01 2a 4e d8 d2 1e 9f 11  |1........*N.....|
-00000320  f5 e3 35 38 3e b0 da 30  f1 fb ed e5 d1 16 03 03  |..58>..0........|
+00000270  2a 16 03 03 00 b7 0c 00  00 b3 03 00 1d 20 87 2c  |*............ .,|
+00000280  f2 fd 8e b9 3d 5f 1c c8  bb 04 f5 1e 01 a8 ba d8  |....=_..........|
+00000290  b6 8e 61 78 15 9e 3b a7  da 96 8e 77 d7 70 04 03  |..ax..;....w.p..|
+000002a0  00 8b 30 81 88 02 42 01  dc e2 26 f9 18 39 da 7d  |..0...B...&..9.}|
+000002b0  bd a1 30 c6 6f dd cd aa  a0 4f 71 cf 42 76 61 ba  |..0.o....Oq.Bva.|
+000002c0  e7 9f 09 b5 05 f2 76 c7  db 2a 93 83 3b 0b 3a cf  |......v..*..;.:.|
+000002d0  60 96 24 c8 af de 2c db  5a 29 1c 62 67 28 e9 d7  |`.$...,.Z).bg(..|
+000002e0  57 5f 54 18 cc bf ee d1  d9 02 42 01 04 cf 67 0b  |W_T.......B...g.|
+000002f0  62 2c c2 17 a3 f4 f1 32  0f c5 b9 ae 3b 52 36 2b  |b,.....2....;R6+|
+00000300  f0 c0 60 49 08 e0 bf f5  7c 09 13 e4 b8 ba 08 c7  |..`I....|.......|
+00000310  ea 74 a0 f5 88 45 e4 35  f1 c5 4e df fe 45 bc ca  |.t...E.5..N..E..|
+00000320  9c 5f c8 84 66 13 8f b3  c9 7e b2 ba d6 16 03 03  |._..f....~......|
 00000330  00 3a 0d 00 00 36 03 01  02 40 00 2e 04 03 05 03  |.:...6...@......|
 00000340  06 03 08 07 08 08 08 09  08 0a 08 0b 08 04 08 05  |................|
 00000350  08 06 04 01 05 01 06 01  03 03 02 03 03 01 02 01  |................|
 00000200  e4 fa cc b1 8a ce e2 23  a0 87 f0 e1 67 51 eb 16  |.......#....gQ..|
 00000210  03 03 00 25 10 00 00 21  20 2f e5 7d a3 47 cd 62  |...%...! /.}.G.b|
 00000220  43 15 28 da ac 5f bb 29  07 30 ff f6 84 af c4 cf  |C.(.._.).0......|
-00000230  c2 ed 90 99 5f 58 cb 3b  74 16 03 03 00 93 0f 00  |...._X.;t.......|
-00000240  00 8f 04 03 00 8b 30 81  88 02 42 01 e6 0a ff de  |......0...B.....|
-00000250  af a6 d2 7a 5f 4e f8 eb  c8 19 74 53 5c e8 bc 2d  |...z_N....tS\..-|
-00000260  72 24 11 d2 11 ec ec cd  a1 9c 3d 10 a2 de f8 8b  |r$........=.....|
-00000270  22 98 d3 33 c2 13 3b 93  89 ae ca a6 a8 94 70 fe  |"..3..;.......p.|
-00000280  76 2f 04 bc ac fb 66 79  3b 76 7f 6d 96 02 42 01  |v/....fy;v.m..B.|
-00000290  df f6 30 14 7c 7e a1 0b  f6 b8 8b d7 75 b8 bd 0e  |..0.|~......u...|
-000002a0  63 8a bd 8b ec 75 70 db  d9 37 d7 53 f3 8b a2 ae  |c....up..7.S....|
-000002b0  60 96 69 74 eb bb 3d a6  9a 7d 46 51 73 ff 78 cf  |`.it..=..}FQs.x.|
-000002c0  7f 49 d9 27 5e 9f f9 d2  11 cc 0e e4 dc 04 fe d5  |.I.'^...........|
-000002d0  d2 14 03 03 00 01 01 16  03 03 00 40 00 00 00 00  |...........@....|
-000002e0  00 00 00 00 00 00 00 00  00 00 00 00 7a db 34 e9  |............z.4.|
-000002f0  98 f8 c1 f0 38 c3 33 22  5c c3 45 b0 a3 10 3c 77  |....8.3"\.E...<w|
-00000300  7f d2 06 c5 f8 13 b6 f4  ee 7e 53 0b 07 0b c3 c9  |.........~S.....|
-00000310  89 9a a9 bb 3b af 79 09  59 ce 10 41              |....;.y.Y..A|
+00000230  c2 ed 90 99 5f 58 cb 3b  74 16 03 03 00 92 0f 00  |...._X.;t.......|
+00000240  00 8e 04 03 00 8a 30 81  87 02 42 01 8f ff aa 8c  |......0...B.....|
+00000250  bd 0c 94 39 34 e5 39 7b  d2 12 26 8e 94 4a fd 68  |...94.9{..&..J.h|
+00000260  f2 f5 5b 30 69 e1 42 3a  74 cd 9a 37 75 5c d2 a6  |..[0i.B:t..7u\..|
+00000270  c9 7b b1 83 c1 d9 c5 55  1a af 3d 19 64 02 43 c0  |.{.....U..=.d.C.|
+00000280  0a 1c 0e ff f4 42 85 fb  d1 aa a2 52 1a 02 41 2f  |.....B.....R..A/|
+00000290  c6 23 d7 37 f1 36 75 0c  0f b4 49 14 c4 b4 d9 28  |.#.7.6u...I....(|
+000002a0  c1 00 2d e4 d6 93 fd a0  f5 59 4e 45 0c a4 28 d4  |..-......YNE..(.|
+000002b0  dc aa 7b 0b 28 29 12 94  f6 db 8c 23 af 81 7e ab  |..{.().....#..~.|
+000002c0  fd 12 ba 11 27 b2 10 87  89 61 9f 5d 6d 18 79 c5  |....'....a.]m.y.|
+000002d0  14 03 03 00 01 01 16 03  03 00 40 00 00 00 00 00  |..........@.....|
+000002e0  00 00 00 00 00 00 00 00  00 00 00 2d 3e 6e 02 fb  |...........->n..|
+000002f0  50 cc 37 62 77 17 08 ef  71 e6 06 23 82 ba 97 b7  |P.7bw...q..#....|
+00000300  0f 38 f9 5e 05 63 4c c9  04 6e bd e4 78 76 32 3b  |.8.^.cL..n..xv2;|
+00000310  3a a7 9b de 30 ca ed fb  17 dc 40                 |:...0.....@|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 40 18 c0 f3 96 7b  |..........@....{|
-00000010  45 91 6d 5b 1c 67 4f 37  74 b7 db 72 45 57 09 25  |E.m[.gO7t..rEW.%|
-00000020  4a 14 68 4d 78 6c c7 15  6a b1 57 e6 ff 53 c4 58  |J.hMxl..j.W..S.X|
-00000030  41 c5 6b 08 3c 5a 8c b9  04 d0 27 62 ee a6 e3 36  |A.k.<Z....'b...6|
-00000040  96 87 db 09 e3 88 d9 a2  0f 7d 9a                 |.........}.|
+00000000  14 03 03 00 01 01 16 03  03 00 40 19 62 a8 82 26  |..........@.b..&|
+00000010  0f 0c 84 b4 31 6a 5d 12  65 dc b9 bc de 5c cb 77  |....1j].e....\.w|
+00000020  5d 04 7e a8 10 1a a5 05  e5 ca 04 68 a2 81 ef f5  |].~........h....|
+00000030  ae 4e bd f1 f3 ba 3f 6a  81 ae 71 9a 2f 31 e2 79  |.N....?j..q./1.y|
+00000040  f1 4d 6c 0e a4 be 4b f7  80 6f 97                 |.Ml...K..o.|
 >>> Flow 5 (client to server)
 00000000  17 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
-00000010  00 00 00 00 00 a6 c2 ef  07 bb 38 4a e4 8f 0c 12  |..........8J....|
-00000020  19 1a 96 62 22 57 57 a2  b5 b3 06 70 95 28 a7 f7  |...b"WW....p.(..|
-00000030  0d 42 69 37 7f 15 03 03  00 30 00 00 00 00 00 00  |.Bi7.....0......|
-00000040  00 00 00 00 00 00 00 00  00 00 04 ed 3e 68 40 eb  |............>h@.|
-00000050  a0 7e 57 da 27 e7 f5 e8  6c e5 6d 58 c8 a5 18 47  |.~W.'...l.mX...G|
-00000060  92 5a 43 90 de 07 9e 9a  3b cc                    |.ZC.....;.|
+00000010  00 00 00 00 00 e9 f4 51  fe c1 02 35 de 6e 72 c3  |.......Q...5.nr.|
+00000020  58 f3 01 4a f0 9d f2 34  df fc 0e 93 ef 46 2e 45  |X..J...4.....F.E|
+00000030  5e 60 43 52 33 15 03 03  00 30 00 00 00 00 00 00  |^`CR3....0......|
+00000040  00 00 00 00 00 00 00 00  00 00 ac 82 d6 47 42 40  |.............GB@|
+00000050  d6 6c 6d e3 b6 c6 4a b7  83 ce 6f 3f 33 ad e7 eb  |.lm...J...o?3...|
+00000060  bf 59 82 50 8a 18 e3 13  46 6c                    |.Y.P....Fl|
index f5fae453a86e3cbfef3c7ddf05a4895efe47926f..7ae186dd8405df2a46b070ad82dbb5556f5b07b0 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 be ba ac 2a 81  |....Y...U.....*.|
-00000010  33 b1 6e 4d 8b 9b 29 f9  16 86 bc cd b2 03 50 72  |3.nM..).......Pr|
-00000020  91 9a 93 f9 e1 d6 27 55  8b b8 6c 20 84 c2 21 9e  |......'U..l ..!.|
-00000030  60 aa b3 f0 ec 2f 66 0d  59 31 02 08 9e 68 68 c0  |`..../f.Y1...hh.|
-00000040  58 9a 8e 6c 25 ce 4d e3  3f 9d dc 91 c0 2f 00 00  |X..l%.M.?..../..|
+00000000  16 03 03 00 59 02 00 00  55 03 03 2a 52 95 57 8c  |....Y...U..*R.W.|
+00000010  55 3f d7 82 f0 3f af 57  a1 82 86 00 3a 6b c0 07  |U?...?.W....:k..|
+00000020  4d c3 0e 80 cc 37 2d 51  f4 d3 e2 20 4a f6 c9 8a  |M....7-Q... J...|
+00000030  d2 98 4a ff 22 66 11 da  6f 9a a0 17 b9 96 b0 86  |..J."f..o.......|
+00000040  29 e0 39 86 0a 00 42 78  30 60 61 99 c0 2f 00 00  |).9...Bx0`a../..|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 59 0b 00 02 55 00  02 52 00 02 4f 30 82 02  |..Y...U..R..O0..|
 00000070  4b 30 82 01 b4 a0 03 02  01 02 02 09 00 e8 f0 9d  |K0..............|
 00000290  77 8d 0c 1c f1 0f a1 d8  40 83 61 c9 4c 72 2b 9d  |w.......@.a.Lr+.|
 000002a0  ae db 46 06 06 4d f4 c1  b3 3e c0 d1 bd 42 d4 db  |..F..M...>...B..|
 000002b0  fe 3d 13 60 84 5c 21 d3  3b e9 fa e7 16 03 03 00  |.=.`.\!.;.......|
-000002c0  ac 0c 00 00 a8 03 00 1d  20 82 89 54 65 64 97 8d  |........ ..Ted..|
-000002d0  e8 63 a2 5b 4f 16 56 7c  cf 8b 0a 75 46 52 7e b6  |.c.[O.V|...uFR~.|
-000002e0  99 2a e9 52 1f 11 46 85  36 08 04 00 80 cd a5 84  |.*.R..F.6.......|
-000002f0  ff 9a 79 b5 04 85 88 fb  1e 1c d6 6b 78 e8 4d a5  |..y........kx.M.|
-00000300  10 38 25 8e 8d de 71 51  b5 fd a6 2a f8 8b 5c 6d  |.8%...qQ...*..\m|
-00000310  1e 88 f7 d8 12 24 ff f7  7e dd 05 1c bf 71 7d 4f  |.....$..~....q}O|
-00000320  26 2f 2e 27 d8 e1 a8 8b  d2 42 2b a6 d9 4e e6 60  |&/.'.....B+..N.`|
-00000330  48 57 38 5d 3b f3 94 74  2c 8f ba e0 84 54 1c c0  |HW8];..t,....T..|
-00000340  10 51 a0 31 1a d0 ec 72  01 f1 d3 65 73 c7 40 25  |.Q.1...r...es.@%|
-00000350  af cd 10 18 29 2c 1a 52  e0 c9 a6 de 85 8c 96 e6  |....),.R........|
-00000360  7d 85 0a 64 86 59 39 25  8f 8c 36 4c 37 16 03 03  |}..d.Y9%..6L7...|
+000002c0  ac 0c 00 00 a8 03 00 1d  20 fa 3a 8f b7 50 10 38  |........ .:..P.8|
+000002d0  04 9d fb c4 e4 76 6d 93  86 b2 8a d7 5b 8f 8d 45  |.....vm.....[..E|
+000002e0  41 b7 ba 54 bc cc 7b 07  3c 08 04 00 80 a1 14 65  |A..T..{.<......e|
+000002f0  f6 48 29 ba 08 86 52 65  dd 08 ef b8 b8 77 ef fd  |.H)...Re.....w..|
+00000300  8a ca dc 37 f8 69 fa 04  69 73 84 07 b2 45 f0 a2  |...7.i..is...E..|
+00000310  8c 69 f7 7c 4c 5c 95 c5  66 80 ad 93 04 67 4b 3d  |.i.|L\..f....gK=|
+00000320  f8 53 a9 33 b3 c0 40 17  62 34 f0 f3 1e d2 23 93  |.S.3..@.b4....#.|
+00000330  29 52 bc f4 f0 72 58 b9  76 9c 7b 54 b0 d5 d1 ab  |)R...rX.v.{T....|
+00000340  b3 1b ae f7 f3 46 6a 07  7f f4 91 ee 46 d6 85 43  |.....Fj.....F..C|
+00000350  ea c6 f9 f5 47 89 85 39  72 35 af b4 03 e9 a2 ea  |....G..9r5......|
+00000360  a8 19 09 ea b3 d2 c2 38  59 65 d1 2c 18 16 03 03  |.......8Ye.,....|
 00000370  00 3a 0d 00 00 36 03 01  02 40 00 2e 04 03 05 03  |.:...6...@......|
 00000380  06 03 08 07 08 08 08 09  08 0a 08 0b 08 04 08 05  |................|
 00000390  08 06 04 01 05 01 06 01  03 03 02 03 03 01 02 01  |................|
 00000200  e4 fa cc b1 8a ce e2 23  a0 87 f0 e1 67 51 eb 16  |.......#....gQ..|
 00000210  03 03 00 25 10 00 00 21  20 2f e5 7d a3 47 cd 62  |...%...! /.}.G.b|
 00000220  43 15 28 da ac 5f bb 29  07 30 ff f6 84 af c4 cf  |C.(.._.).0......|
-00000230  c2 ed 90 99 5f 58 cb 3b  74 16 03 03 00 92 0f 00  |...._X.;t.......|
-00000240  00 8e 04 03 00 8a 30 81  87 02 41 72 16 75 7d 08  |......0...Ar.u}.|
-00000250  42 7b 33 e7 59 51 ef 3c  54 e7 81 e4 10 31 ab 5d  |B{3.YQ.<T....1.]|
-00000260  df 17 52 e0 a9 9f b5 43  e0 33 0e 52 b2 19 a2 a8  |..R....C.3.R....|
-00000270  0b b9 8b e3 0b 51 1d 65  c9 7b 7c 67 66 d4 98 77  |.....Q.e.{|gf..w|
-00000280  34 06 07 fc 8f 84 85 36  c3 fd f9 12 02 42 01 ad  |4......6.....B..|
-00000290  a7 25 ed c2 e8 2d c0 a3  12 0b 79 b2 32 e2 c3 70  |.%...-....y.2..p|
-000002a0  2b 5d 99 1b 24 45 60 68  8b b3 28 5c 96 1a 26 89  |+]..$E`h..(\..&.|
-000002b0  24 53 20 f5 fc 6f 98 b1  64 0b ba f5 ad ea 1e 33  |$S ..o..d......3|
-000002c0  4f 64 fd 43 37 80 24 f0  7d e3 7d 63 76 7e 60 e3  |Od.C7.$.}.}cv~`.|
-000002d0  14 03 03 00 01 01 16 03  03 00 28 00 00 00 00 00  |..........(.....|
-000002e0  00 00 00 27 0b ff 3a 92  88 b6 86 86 0e c2 f5 94  |...'..:.........|
-000002f0  d5 29 a4 6d 95 12 e1 d8  ec d9 a4 3c 1c db 52 76  |.).m.......<..Rv|
-00000300  2a 72 29                                          |*r)|
+00000230  c2 ed 90 99 5f 58 cb 3b  74 16 03 03 00 91 0f 00  |...._X.;t.......|
+00000240  00 8d 04 03 00 89 30 81  86 02 41 63 34 72 b4 70  |......0...Ac4r.p|
+00000250  45 46 9c 3c 06 2c f5 ab  d4 dd a7 91 69 9c 65 0f  |EF.<.,......i.e.|
+00000260  4b d9 2d 90 3d d1 f2 4d  2a 6a 43 4f a7 fd b5 22  |K.-.=..M*jCO..."|
+00000270  83 61 e2 14 33 8c bc 8a  81 52 a1 f4 69 a7 12 c9  |.a..3....R..i...|
+00000280  c3 28 69 85 6d c1 b0 5d  d3 5e ac 4e 02 41 35 cd  |.(i.m..].^.N.A5.|
+00000290  3b c3 f6 ea 9e df 2a a1  ea 80 55 40 d2 13 d3 ff  |;.....*...U@....|
+000002a0  b2 59 bb a0 c7 10 67 6e  9b dc 6c 3c 97 08 07 e0  |.Y....gn..l<....|
+000002b0  db da 79 6b 0e 6c a0 23  13 b1 02 32 ab ee 62 69  |..yk.l.#...2..bi|
+000002c0  f9 d5 7f 24 2e 26 94 36  a4 36 53 63 dd 90 20 14  |...$.&.6.6Sc.. .|
+000002d0  03 03 00 01 01 16 03 03  00 28 00 00 00 00 00 00  |.........(......|
+000002e0  00 00 a7 30 0e b0 f7 ba  51 35 c9 4c c2 24 90 5e  |...0....Q5.L.$.^|
+000002f0  b2 59 57 5d 96 9d ad d1  1e 7d b0 35 09 9c c5 49  |.YW].....}.5...I|
+00000300  bd 82                                             |..|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 28 b8 e9 dd 30 75  |..........(...0u|
-00000010  40 7d 71 76 db 9a 95 92  81 02 3a 9e 36 d5 15 ca  |@}qv......:.6...|
-00000020  5d 63 a1 0f 8c 53 c9 1c  37 56 b2 0d 54 15 a2 dc  |]c...S..7V..T...|
-00000030  03 d6 2e                                          |...|
+00000000  14 03 03 00 01 01 16 03  03 00 28 09 ff 53 e8 0f  |..........(..S..|
+00000010  ad 86 30 ca 96 54 da 72  45 13 7a cd 51 f6 b3 a5  |..0..T.rE.z.Q...|
+00000020  27 4c 7c 26 81 6d 76 6f  19 8e f3 13 77 49 59 73  |'L|&.mvo....wIYs|
+00000030  4e 98 3e                                          |N.>|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 01 85 96  |................|
-00000010  67 b2 4b d3 e3 27 80 9f  2d a8 f4 bf 47 91 58 6e  |g.K..'..-...G.Xn|
-00000020  47 d8 98 15 03 03 00 1a  00 00 00 00 00 00 00 02  |G...............|
-00000030  36 54 82 d1 a2 0f 2a c3  53 f6 09 d0 5c 78 46 97  |6T....*.S...\xF.|
-00000040  20 41                                             | A|
+00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 99 7b 4c  |..............{L|
+00000010  1d 0a b1 89 0d ac fa a7  39 eb 9a ff 8f 06 60 d1  |........9.....`.|
+00000020  88 e8 ef 15 03 03 00 1a  00 00 00 00 00 00 00 02  |................|
+00000030  99 42 7f c8 35 79 f3 a0  10 5c 05 25 c1 ac ab aa  |.B..5y...\.%....|
+00000040  d5 9e                                             |..|
index e415b126e564b5ab1e7e8871cc4f5ebcdda5f913..9ecd8e3ac3b685e844c6f307eb0f271d9190e67e 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 1c 50 4e 50 35  |....Y...U...PNP5|
-00000010  51 02 a9 62 ba 82 a5 d3  fa 40 4e f3 28 9b 50 a6  |Q..b.....@N.(.P.|
-00000020  f0 75 30 e9 fe be a3 42  1d 1c f5 20 9e 88 46 57  |.u0....B... ..FW|
-00000030  c5 b4 a3 a3 fc 88 bb e0  1c 5e ea 77 a0 75 93 5a  |.........^.w.u.Z|
-00000040  6d 4c c7 57 6f 3a 05 af  3f 3f ac 75 cc a8 00 00  |mL.Wo:..??.u....|
+00000000  16 03 03 00 59 02 00 00  55 03 03 5c 37 b1 d2 6c  |....Y...U..\7..l|
+00000010  bc dd 26 8c 4e f7 04 80  09 3c fd 76 23 d4 52 16  |..&.N....<.v#.R.|
+00000020  df 0e 79 ab f4 cf 8c f3  61 31 c6 20 7d 7a 1d 8f  |..y.....a1. }z..|
+00000030  09 3e 2b 25 04 7f 0f 0a  a7 0c 03 fd 9c 09 f3 5d  |.>+%...........]|
+00000040  96 75 f8 da 5b 6b 1b fb  ca d7 ec 7a cc a8 00 00  |.u..[k.....z....|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 59 0b 00 02 55 00  02 52 00 02 4f 30 82 02  |..Y...U..R..O0..|
 00000070  4b 30 82 01 b4 a0 03 02  01 02 02 09 00 e8 f0 9d  |K0..............|
 00000290  77 8d 0c 1c f1 0f a1 d8  40 83 61 c9 4c 72 2b 9d  |w.......@.a.Lr+.|
 000002a0  ae db 46 06 06 4d f4 c1  b3 3e c0 d1 bd 42 d4 db  |..F..M...>...B..|
 000002b0  fe 3d 13 60 84 5c 21 d3  3b e9 fa e7 16 03 03 00  |.=.`.\!.;.......|
-000002c0  ac 0c 00 00 a8 03 00 1d  20 82 c1 f5 7b 68 eb 7a  |........ ...{h.z|
-000002d0  cf 02 c9 95 28 4b 31 76  a9 84 93 a9 1f 5b f4 2a  |....(K1v.....[.*|
-000002e0  5c a5 31 94 5f f0 e0 ed  2e 08 04 00 80 7a 99 38  |\.1._........z.8|
-000002f0  7f d0 25 4b bf a9 e0 2b  db ce 17 9d 30 4b 82 9e  |..%K...+....0K..|
-00000300  b1 50 84 fc dd b0 a8 5c  39 20 00 40 5b 92 dc 7c  |.P.....\9 .@[..||
-00000310  25 3b 53 7d 5a 4b ad 05  6f 3a 4f e5 84 b6 3a e2  |%;S}ZK..o:O...:.|
-00000320  fb bf cb c8 94 39 a5 28  ad c8 5f 94 53 90 0e 61  |.....9.(.._.S..a|
-00000330  af f2 92 2c 3b ec 3c bf  1d d3 8b a5 65 58 5b bf  |...,;.<.....eX[.|
-00000340  5a 21 3d cd 40 7c 9e 1d  e9 62 3c 67 71 7c ec b4  |Z!=.@|...b<gq|..|
-00000350  25 d0 4a 6a 85 1d c4 e8  44 d6 25 1a 2c 29 ae d7  |%.Jj....D.%.,)..|
-00000360  d7 24 fb 5a 62 f7 50 52  12 1b c7 3e b0 16 03 03  |.$.Zb.PR...>....|
+000002c0  ac 0c 00 00 a8 03 00 1d  20 aa c7 43 e7 1e 3b 2b  |........ ..C..;+|
+000002d0  28 c2 68 aa 83 cc 85 63  68 c4 b8 4d fb 18 fa b9  |(.h....ch..M....|
+000002e0  3e 9a f2 7c 04 33 7f 48  6b 08 04 00 80 28 28 c7  |>..|.3.Hk....((.|
+000002f0  84 79 65 11 07 43 7a ce  f1 d6 cb 0e fe 6a 24 2c  |.ye..Cz......j$,|
+00000300  f3 f0 e5 9c 80 a6 c7 41  c7 51 f2 84 be 6e 58 df  |.......A.Q...nX.|
+00000310  f2 d2 d4 d9 62 08 c8 35  75 b9 8e 49 c2 98 b0 9d  |....b..5u..I....|
+00000320  32 aa db bf 03 c1 61 83  f7 20 d7 ec 07 27 5e 45  |2.....a.. ...'^E|
+00000330  dc d6 92 4c a1 4f 4e 7c  53 c5 ca 42 48 40 0f 83  |...L.ON|S..BH@..|
+00000340  fc 9d 60 a1 7c 43 d1 f5  f8 3f fe 50 3f d0 03 bc  |..`.|C...?.P?...|
+00000350  3e 8b ac 69 8f ae b6 9a  c8 d4 98 84 30 f1 79 9b  |>..i........0.y.|
+00000360  af 5d 4e 41 2a 7c 46 22  df 46 42 74 f6 16 03 03  |.]NA*|F".FBt....|
 00000370  00 3a 0d 00 00 36 03 01  02 40 00 2e 04 03 05 03  |.:...6...@......|
 00000380  06 03 08 07 08 08 08 09  08 0a 08 0b 08 04 08 05  |................|
 00000390  08 06 04 01 05 01 06 01  03 03 02 03 03 01 02 01  |................|
 00000140  08 16 03 03 00 25 10 00  00 21 20 2f e5 7d a3 47  |.....%...! /.}.G|
 00000150  cd 62 43 15 28 da ac 5f  bb 29 07 30 ff f6 84 af  |.bC.(.._.).0....|
 00000160  c4 cf c2 ed 90 99 5f 58  cb 3b 74 16 03 03 00 48  |......_X.;t....H|
-00000170  0f 00 00 44 08 07 00 40  af a6 03 14 53 7a 4f 75  |...D...@....SzOu|
-00000180  9d cc 2f e3 e7 2a 51 16  16 b0 1d 28 e0 2a 59 f0  |../..*Q....(.*Y.|
-00000190  3c df cc 18 dd b8 ef d1  9f 9d 03 8e 59 00 27 d1  |<...........Y.'.|
-000001a0  39 2f 3b 33 53 1f b2 f0  22 1d 06 f6 50 0b a7 98  |9/;3S..."...P...|
-000001b0  cc fa 78 53 bf 8e ff 0b  14 03 03 00 01 01 16 03  |..xS............|
-000001c0  03 00 20 e5 81 3e a3 34  29 52 14 19 49 cf 04 82  |.. ..>.4)R..I...|
-000001d0  8b e7 83 aa 6c db 96 ec  97 29 b4 a3 db 87 21 2e  |....l....)....!.|
-000001e0  a5 c0 66                                          |..f|
+00000170  0f 00 00 44 08 07 00 40  07 e0 a5 14 ca cf 31 d7  |...D...@......1.|
+00000180  99 96 c7 c7 d8 d8 a7 f7  82 e7 c6 c0 12 5d 91 5a  |.............].Z|
+00000190  bc eb 4a c0 59 c6 5b 7b  03 df 2a ff 48 ca 55 d8  |..J.Y.[{..*.H.U.|
+000001a0  3e 10 c1 94 2c 03 b2 e7  16 83 4d e5 5a 3d 8a 48  |>...,.....M.Z=.H|
+000001b0  2f e5 c4 59 de 6f 47 05  14 03 03 00 01 01 16 03  |/..Y.oG.........|
+000001c0  03 00 20 ae 35 81 df 88  0e a3 2e 67 3f 33 02 3d  |.. .5......g?3.=|
+000001d0  b8 7e 47 db cb be 05 c7  ba 43 dc 5b 52 3b 4b ca  |.~G......C.[R;K.|
+000001e0  c0 dc 78                                          |..x|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 20 84 67 d4 ce cf  |.......... .g...|
-00000010  fb 54 2c dc f7 53 31 8a  aa 03 60 37 3d 33 f2 79  |.T,..S1...`7=3.y|
-00000020  d0 65 2e 3f 0e f9 1a d3  6e 6d 8e                 |.e.?....nm.|
+00000000  14 03 03 00 01 01 16 03  03 00 20 63 23 49 7c 83  |.......... c#I|.|
+00000010  1a 8b cd 48 02 e7 86 4d  ab 8b 3c 4f 40 27 a6 48  |...H...M..<O@'.H|
+00000020  95 d5 80 8a 7a e0 56 0b  e6 34 70                 |....z.V..4p|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 16 e5 b7 4c  92 05 fc 81 cf 11 ef cd  |.......L........|
-00000010  0f 4b df ef a1 54 ae 26  4e ec aa 15 03 03 00 12  |.K...T.&N.......|
-00000020  0a f3 5b 06 63 84 a6 eb  d4 73 94 db fe d8 e0 ae  |..[.c....s......|
-00000030  d6 fc                                             |..|
+00000000  17 03 03 00 16 aa b4 5b  75 04 96 c5 4a e3 2a fb  |.......[u...J.*.|
+00000010  be 29 32 9e c5 e4 15 bd  38 df 69 15 03 03 00 12  |.)2.....8.i.....|
+00000020  50 4d b6 c0 95 e6 5a db  f2 b7 ea 02 cb 3e 01 ea  |PM....Z......>..|
+00000030  35 0d                                             |5.|
index 3975b072c9503fe263707675a03c38d3b2a222fd..35ec3471e6efb8596795d9479d9ee8b5a0ec0917 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 d4 20 b3 4c 6a  |....Y...U... .Lj|
-00000010  69 44 3f f7 ab 15 35 85  ca 71 02 b0 70 18 8e d6  |iD?...5..q..p...|
-00000020  61 d5 34 08 42 de cf a1  57 32 96 20 8c b4 72 dd  |a.4.B...W2. ..r.|
-00000030  63 93 e6 13 9d 4a ec 75  d9 a1 a6 9e 5e 02 f5 63  |c....J.u....^..c|
-00000040  29 1a 78 9f 94 9f 6c 58  b5 91 ae 63 c0 30 00 00  |).x...lX...c.0..|
+00000000  16 03 03 00 59 02 00 00  55 03 03 16 f7 21 0a 97  |....Y...U....!..|
+00000010  89 11 ec c3 c4 05 41 79  72 60 40 6d ec 78 90 26  |......Ayr`@m.x.&|
+00000020  0c a4 f8 5d d5 27 e9 70  bb 40 21 20 b0 bb 98 5d  |...].'.p.@! ...]|
+00000030  a2 27 08 1e 4a fe f9 e1  cf a5 79 d3 eb c6 40 f7  |.'..J.....y...@.|
+00000040  ee 4f 0b fa a1 bb 09 62  07 24 30 b7 c0 30 00 00  |.O.....b.$0..0..|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 59 0b 00 02 55 00  02 52 00 02 4f 30 82 02  |..Y...U..R..O0..|
 00000070  4b 30 82 01 b4 a0 03 02  01 02 02 09 00 e8 f0 9d  |K0..............|
 00000290  77 8d 0c 1c f1 0f a1 d8  40 83 61 c9 4c 72 2b 9d  |w.......@.a.Lr+.|
 000002a0  ae db 46 06 06 4d f4 c1  b3 3e c0 d1 bd 42 d4 db  |..F..M...>...B..|
 000002b0  fe 3d 13 60 84 5c 21 d3  3b e9 fa e7 16 03 03 00  |.=.`.\!.;.......|
-000002c0  ac 0c 00 00 a8 03 00 1d  20 a2 bd 95 3e 0c 9f ad  |........ ...>...|
-000002d0  11 59 e0 6a c1 21 0c 6c  86 cc f1 ce bd a0 30 5d  |.Y.j.!.l......0]|
-000002e0  53 1e 75 f9 55 af 49 7b  31 08 04 00 80 d4 8b 11  |S.u.U.I{1.......|
-000002f0  ca 22 14 79 a3 e8 b6 c7  d0 d6 1b 17 42 93 47 30  |.".y........B.G0|
-00000300  ab 50 0e c9 0c 92 88 96  b4 63 4e 4e ac 7f dd c8  |.P.......cNN....|
-00000310  8f 85 07 5b 95 c5 0a c0  4e 6d 4f 51 ba d8 d7 db  |...[....NmOQ....|
-00000320  14 70 80 4f 68 d9 b4 39  e7 48 27 21 76 4c 79 a4  |.p.Oh..9.H'!vLy.|
-00000330  60 91 d7 2f 75 69 04 1a  da 71 ff b8 4d 78 d8 e7  |`../ui...q..Mx..|
-00000340  ca f2 f2 1e 71 21 b3 a0  44 a7 6c 99 16 a1 c9 f8  |....q!..D.l.....|
-00000350  f0 de e8 99 12 7b 3d a2  e3 15 fa 63 62 e9 1b 72  |.....{=....cb..r|
-00000360  c8 bb 27 38 4a 48 66 1d  dd fb ef 6f d1 16 03 03  |..'8JHf....o....|
+000002c0  ac 0c 00 00 a8 03 00 1d  20 39 1f 7e 66 c8 20 24  |........ 9.~f. $|
+000002d0  cf 8e 51 f6 bf 2a 01 a9  3b 51 19 f1 9d 32 b6 fa  |..Q..*..;Q...2..|
+000002e0  05 3b 90 c9 a3 8b 49 92  2a 08 04 00 80 da 65 ad  |.;....I.*.....e.|
+000002f0  fa f9 d5 f6 d7 13 34 d2  ab ac ea 57 37 69 c6 b1  |......4....W7i..|
+00000300  91 ee 89 b7 04 6b 17 fb  80 23 df df ef a1 62 9b  |.....k...#....b.|
+00000310  e4 0a 4e ca b0 35 b2 d3  2a cf 4f c1 e3 d9 37 78  |..N..5..*.O...7x|
+00000320  aa c8 59 f8 25 c7 43 51  19 6c c7 50 90 a4 2c 92  |..Y.%.CQ.l.P..,.|
+00000330  01 0e 8d ff f0 88 4b af  1d 03 ee 51 8b 18 e4 ee  |......K....Q....|
+00000340  35 48 16 e7 4c 26 1d d8  af 91 b1 75 38 b5 65 42  |5H..L&.....u8.eB|
+00000350  8e 60 c7 f9 25 a7 85 35  72 41 6f f6 c4 61 1d c0  |.`..%..5rAo..a..|
+00000360  c8 cf da ae 31 5e 2e d6  9c ca f1 d6 31 16 03 03  |....1^......1...|
 00000370  00 3a 0d 00 00 36 03 01  02 40 00 2e 04 03 05 03  |.:...6...@......|
 00000380  06 03 08 07 08 08 08 09  08 0a 08 0b 08 04 08 05  |................|
 00000390  08 06 04 01 05 01 06 01  03 03 02 03 03 01 02 01  |................|
 00000200  e5 35 16 03 03 00 25 10  00 00 21 20 2f e5 7d a3  |.5....%...! /.}.|
 00000210  47 cd 62 43 15 28 da ac  5f bb 29 07 30 ff f6 84  |G.bC.(.._.).0...|
 00000220  af c4 cf c2 ed 90 99 5f  58 cb 3b 74 16 03 03 00  |......._X.;t....|
-00000230  88 0f 00 00 84 08 04 00  80 2e bf 05 22 82 a7 d6  |............"...|
-00000240  e9 08 ff 9b 10 d3 4a 6c  c4 73 5c 78 88 05 0c 15  |......Jl.s\x....|
-00000250  b7 8c 78 49 64 2d 58 67  ef 8f db c0 67 fa 32 6e  |..xId-Xg....g.2n|
-00000260  65 45 90 a0 69 5c fb ba  e0 16 1c d4 81 1d 24 89  |eE..i\........$.|
-00000270  35 27 14 15 19 0b 86 ee  6a f2 b4 a5 27 61 5f 1f  |5'......j...'a_.|
-00000280  cc 47 7c 01 ed a9 ff ed  61 45 3f 53 1c 82 c8 cd  |.G|.....aE?S....|
-00000290  48 e4 89 82 12 d7 d2 ff  fa 32 b3 e6 9d ce 75 75  |H........2....uu|
-000002a0  d1 cd b2 a8 56 a6 a6 63  da 8d ed 27 13 01 9a 56  |....V..c...'...V|
-000002b0  a2 26 b4 6c af 27 f6 4f  1b 14 03 03 00 01 01 16  |.&.l.'.O........|
-000002c0  03 03 00 28 00 00 00 00  00 00 00 00 f0 e8 32 33  |...(..........23|
-000002d0  50 df 73 17 3c 58 f2 c9  30 2e 5d e9 00 4f 4b 33  |P.s.<X..0.]..OK3|
-000002e0  22 12 f7 f0 62 d0 62 3e  ed 36 b8 58              |"...b.b>.6.X|
+00000230  88 0f 00 00 84 08 04 00  80 56 1c 58 51 d8 51 bc  |.........V.XQ.Q.|
+00000240  8e 4b b8 24 64 85 81 d2  26 9b 38 bf 13 19 e7 0a  |.K.$d...&.8.....|
+00000250  f7 94 e8 b5 94 bf 6f ae  f2 07 1a 46 24 38 7b 8b  |......o....F$8{.|
+00000260  2f a6 da 91 1a 5f 7d 3f  cf c4 1b 14 9c 44 8e 6a  |/...._}?.....D.j|
+00000270  6b c8 c4 60 c6 15 e6 f2  c0 45 e7 46 c4 32 06 b1  |k..`.....E.F.2..|
+00000280  46 5e 25 1d ba f7 d8 81  b0 6b 50 40 81 b1 93 89  |F^%......kP@....|
+00000290  cb 90 ae 10 b1 db 08 99  e6 0e 8f 17 0f 4d a7 a7  |.............M..|
+000002a0  f5 42 8a be ca d6 75 c4  32 44 22 ab df cf 22 f7  |.B....u.2D"...".|
+000002b0  58 d9 9f 52 c2 04 c0 81  59 14 03 03 00 01 01 16  |X..R....Y.......|
+000002c0  03 03 00 28 00 00 00 00  00 00 00 00 eb 5a 97 41  |...(.........Z.A|
+000002d0  1d da 2b 81 da 7a b7 9a  f8 5e fe 50 75 e5 a4 6a  |..+..z...^.Pu..j|
+000002e0  21 90 b7 3d 4e bc 44 cf  86 8f cd c3              |!..=N.D.....|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 28 14 ce b1 86 0e  |..........(.....|
-00000010  9f ce 73 25 44 b7 3e a9  25 db a8 93 d9 39 33 75  |..s%D.>.%....93u|
-00000020  2f a9 7f 97 6a 76 28 fe  e2 84 5f 1e 84 66 b4 c8  |/...jv(..._..f..|
-00000030  45 e7 64                                          |E.d|
+00000000  14 03 03 00 01 01 16 03  03 00 28 93 a5 d4 a8 16  |..........(.....|
+00000010  4e a2 b2 c3 b9 ce dd 0e  57 49 7c eb 92 e4 e7 e3  |N.......WI|.....|
+00000020  a8 55 3a 56 54 53 92 b8  ce 15 e3 c3 c2 da 52 01  |.U:VTS........R.|
+00000030  6f 35 fd                                          |o5.|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 3b 17 73  |.............;.s|
-00000010  78 d6 3a b4 6d 3a 61 52  f6 a5 8c dd 18 3e ff 04  |x.:.m:aR.....>..|
-00000020  d9 3f 22 15 03 03 00 1a  00 00 00 00 00 00 00 02  |.?".............|
-00000030  32 8d 5d 07 14 a9 d2 1c  dd 1e 2f 3d 89 a9 8f 1d  |2.]......./=....|
-00000040  08 0f                                             |..|
+00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 5b 20 4f  |.............[ O|
+00000010  e9 3f 09 28 6e 88 5d 1d  57 90 2c 35 74 37 d1 df  |.?.(n.].W.,5t7..|
+00000020  aa 39 9b 15 03 03 00 1a  00 00 00 00 00 00 00 02  |.9..............|
+00000030  bb e3 77 62 e5 c9 78 f4  a5 09 93 b0 20 9a 1b a4  |..wb..x..... ...|
+00000040  48 44                                             |HD|
index 2d608a782455643d55d8d230ed0506076eb25c50..110f689f8e40aca6725269ff424cea2bc04d8719 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 3c ba b1 d8 8d  |....Y...U..<....|
-00000010  f5 52 f4 a4 70 fc 12 54  20 85 eb 23 bc b8 0b e0  |.R..p..T ..#....|
-00000020  80 b6 ab 9b c5 34 84 57  bc ae 95 20 e3 51 8d 40  |.....4.W... .Q.@|
-00000030  93 cc 9f e4 fd 77 82 c8  12 54 6a 23 08 db ff e5  |.....w...Tj#....|
-00000040  87 8d 72 41 60 51 6a 11  5f 0a 9a d2 c0 09 00 00  |..rA`Qj._.......|
+00000000  16 03 03 00 59 02 00 00  55 03 03 68 dc 2e 5e 8e  |....Y...U..h..^.|
+00000010  80 38 0e 65 a3 b0 f6 a0  c0 8f 1e 62 ef 1d 5a 54  |.8.e.......b..ZT|
+00000020  82 dc 9c 68 77 88 57 dd  f3 9d c2 20 4e 56 dd 44  |...hw.W.... NV.D|
+00000030  a0 46 67 4c 09 2b d5 e6  fe 15 fb b3 8e 19 ef a3  |.FgL.+..........|
+00000040  8e 5c a9 70 00 cf 96 d7  3b 8b c9 64 c0 09 00 00  |.\.p....;..d....|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
 00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
 00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
 00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
 00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
-00000270  2a 16 03 03 00 b7 0c 00  00 b3 03 00 1d 20 86 f3  |*............ ..|
-00000280  1e c5 fb 1f 91 44 0e e5  e4 3e 0a cd 75 a2 fb 4c  |.....D...>..u..L|
-00000290  a2 b9 07 f7 33 ce cc cd  61 a5 8c ba 6a 35 04 03  |....3...a...j5..|
-000002a0  00 8b 30 81 88 02 42 01  f4 8d 4f 3e c8 73 b5 b4  |..0...B...O>.s..|
-000002b0  b5 2b ac 2a 27 68 56 a1  45 ce b6 1d c6 37 ce de  |.+.*'hV.E....7..|
-000002c0  bd 96 90 5e e2 1c c8 84  b2 84 57 25 81 d4 c3 7a  |...^......W%...z|
-000002d0  db b2 3d 24 2b 17 3a 4a  7e 92 1a bb 0c fb b6 05  |..=$+.:J~.......|
-000002e0  cd 0e 85 4c 3d 4b 24 2a  2a 02 42 00 f6 91 d6 82  |...L=K$**.B.....|
-000002f0  9e 81 98 5f 64 59 ce 16  85 fc 65 19 0c 50 ca ea  |..._dY....e..P..|
-00000300  8a ba 1e 61 a8 71 cf 2c  eb 94 24 ac 34 75 6e 5c  |...a.q.,..$.4un\|
-00000310  dc 92 ba b8 bd 42 75 ef  6d 67 5f 06 5c e3 6c c2  |.....Bu.mg_.\.l.|
-00000320  aa 5e 29 25 66 00 68 c8  5d 9c 6f bb e0 16 03 03  |.^)%f.h.].o.....|
-00000330  00 3a 0d 00 00 36 03 01  02 40 00 2e 04 03 05 03  |.:...6...@......|
-00000340  06 03 08 07 08 08 08 09  08 0a 08 0b 08 04 08 05  |................|
-00000350  08 06 04 01 05 01 06 01  03 03 02 03 03 01 02 01  |................|
-00000360  03 02 02 02 04 02 05 02  06 02 00 00 16 03 03 00  |................|
-00000370  04 0e 00 00 00                                    |.....|
+00000270  2a 16 03 03 00 b6 0c 00  00 b2 03 00 1d 20 24 d0  |*............ $.|
+00000280  e5 11 4c 95 2c 96 58 62  01 df 20 c8 24 ce 29 a2  |..L.,.Xb.. .$.).|
+00000290  1a 3e 97 e2 df 29 49 e6  3a e8 c2 d3 72 49 04 03  |.>...)I.:...rI..|
+000002a0  00 8a 30 81 87 02 41 71  15 8d 50 f6 69 40 d7 cd  |..0...Aq..P.i@..|
+000002b0  da c9 c3 ee 37 c2 5f c3  89 62 23 e0 ef 37 f9 9e  |....7._..b#..7..|
+000002c0  2a 26 85 10 56 28 08 de  49 3b fa 03 f3 14 4b 3a  |*&..V(..I;....K:|
+000002d0  b2 3d de 84 d2 08 8d 4e  59 3e 80 8f 6a 44 af 6f  |.=.....NY>..jD.o|
+000002e0  be ee 08 ae 35 40 42 bc  02 42 00 f3 e9 89 a5 7f  |....5@B..B......|
+000002f0  9c 50 7c 07 34 e4 cf f0  2b 0f cf f7 68 57 fa fd  |.P|.4...+...hW..|
+00000300  2f 52 04 f8 90 7b 97 eb  c3 e0 cc 68 f7 bf 22 21  |/R...{.....h.."!|
+00000310  62 b3 51 c8 a4 30 38 c5  88 46 df 55 21 21 d0 4f  |b.Q..08..F.U!!.O|
+00000320  6f 95 7b 5f 5a c6 98 dd  2d d1 0a 95 16 03 03 00  |o.{_Z...-.......|
+00000330  3a 0d 00 00 36 03 01 02  40 00 2e 04 03 05 03 06  |:...6...@.......|
+00000340  03 08 07 08 08 08 09 08  0a 08 0b 08 04 08 05 08  |................|
+00000350  06 04 01 05 01 06 01 03  03 02 03 03 01 02 01 03  |................|
+00000360  02 02 02 04 02 05 02 06  02 00 00 16 03 03 00 04  |................|
+00000370  0e 00 00 00                                       |....|
 >>> Flow 3 (client to server)
 00000000  16 03 03 01 fd 0b 00 01  f9 00 01 f6 00 01 f3 30  |...............0|
 00000010  82 01 ef 30 82 01 58 a0  03 02 01 02 02 10 5c 19  |...0..X.......\.|
 00000200  e5 35 16 03 03 00 25 10  00 00 21 20 2f e5 7d a3  |.5....%...! /.}.|
 00000210  47 cd 62 43 15 28 da ac  5f bb 29 07 30 ff f6 84  |G.bC.(.._.).0...|
 00000220  af c4 cf c2 ed 90 99 5f  58 cb 3b 74 16 03 03 00  |......._X.;t....|
-00000230  88 0f 00 00 84 08 04 00  80 53 85 ea dc a6 86 2d  |.........S.....-|
-00000240  e7 8c 0b 68 f9 57 7f f5  77 d8 fe 35 28 91 e7 2f  |...h.W..w..5(../|
-00000250  8a 2c 36 cf d7 8c 9f 3d  f2 e2 99 41 11 b2 3c a2  |.,6....=...A..<.|
-00000260  5e f3 68 1f b5 d4 f8 90  8a e2 5e 02 48 00 2b eb  |^.h.......^.H.+.|
-00000270  f0 e6 8c 28 af 11 80 82  ea 35 06 fd 0a 5f d7 1a  |...(.....5..._..|
-00000280  e9 63 29 08 8c aa 18 1e  7c 08 81 21 c8 aa 86 b1  |.c).....|..!....|
-00000290  cf 94 db f6 8d 15 dc cc  ae cf 41 2c 32 b1 3f 0c  |..........A,2.?.|
-000002a0  96 0e 5c ed 82 74 cc fc  35 f4 38 80 29 00 c1 3a  |..\..t..5.8.)..:|
-000002b0  70 d4 07 07 9c 49 9e 7b  91 14 03 03 00 01 01 16  |p....I.{........|
+00000230  88 0f 00 00 84 08 04 00  80 84 38 78 4d dd 9f 84  |..........8xM...|
+00000240  ae cb b8 2f e9 f3 76 66  41 56 f6 ed a5 fb 8b f2  |.../..vfAV......|
+00000250  43 0f 27 56 9e 7d a8 06  3e 8f ad b0 17 d5 d6 52  |C.'V.}..>......R|
+00000260  f4 88 e5 af 55 5b 55 fc  26 c1 a9 d5 a9 34 2b 50  |....U[U.&....4+P|
+00000270  96 09 db 59 cc f4 e8 cf  84 6f 9d b1 fd 3b a4 66  |...Y.....o...;.f|
+00000280  66 43 74 6d 4f e5 52 2c  22 2d c9 4c 67 3d ff 3d  |fCtmO.R,"-.Lg=.=|
+00000290  c2 79 b3 b1 85 56 08 cc  02 7c 53 a7 be 39 04 21  |.y...V...|S..9.!|
+000002a0  fb db fe ff 1b a6 c7 7a  e9 4c 11 c3 34 a6 7c 4f  |.......z.L..4.|O|
+000002b0  23 61 d9 47 b0 6c ae cb  72 14 03 03 00 01 01 16  |#a.G.l..r.......|
 000002c0  03 03 00 40 00 00 00 00  00 00 00 00 00 00 00 00  |...@............|
-000002d0  00 00 00 00 f3 da dc d7  12 d6 f6 19 75 a8 02 68  |............u..h|
-000002e0  57 0e e1 90 75 d1 fc b8  32 a3 34 16 d6 8d 2a f5  |W...u...2.4...*.|
-000002f0  65 f2 a7 67 2c 2c a4 73  6a b6 f2 ad 2d 7f 8a ce  |e..g,,.sj...-...|
-00000300  a7 12 16 97                                       |....|
+000002d0  00 00 00 00 d3 95 4a 65  d9 8e 3d 9c 2b 18 67 aa  |......Je..=.+.g.|
+000002e0  e0 d7 a6 dd fb af 42 06  0d 56 cc 3d 12 3e 7e 95  |......B..V.=.>~.|
+000002f0  18 6e 97 d6 cc 84 eb 90  a1 c3 b6 6e 3c 42 d1 2e  |.n.........n<B..|
+00000300  7a dc 41 81                                       |z.A.|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 40 dc 11 a1 a2 fb  |..........@.....|
-00000010  55 0c 9e e0 e2 55 1a ca  cd 5b df 1f 39 9e 08 51  |U....U...[..9..Q|
-00000020  bd 6b 72 40 93 f8 23 7a  32 9d 85 18 20 b7 39 b0  |.kr@..#z2... .9.|
-00000030  03 d3 10 6a 8e 66 6d e6  d5 38 03 c6 e5 b8 dc d7  |...j.fm..8......|
-00000040  3c 27 1d d2 a9 59 f9 18  7d 15 90                 |<'...Y..}..|
+00000000  14 03 03 00 01 01 16 03  03 00 40 71 ee 1d 4f 55  |..........@q..OU|
+00000010  b4 47 3d 26 52 5a 00 a5  ce 0e 31 6c 2d 09 95 df  |.G=&RZ....1l-...|
+00000020  fb 74 30 89 32 3d 47 29  58 ee 61 70 74 18 8c 01  |.t0.2=G)X.apt...|
+00000030  e3 16 d7 6e 3d a1 30 75  61 b8 99 e4 c5 82 82 d5  |...n=.0ua.......|
+00000040  75 f6 e1 b4 f8 97 77 92  00 64 06                 |u.....w..d.|
 >>> Flow 5 (client to server)
 00000000  17 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
-00000010  00 00 00 00 00 c2 92 ee  96 31 60 90 d5 ee a6 1c  |.........1`.....|
-00000020  ed 3c 03 40 8c e7 0c db  7f b0 11 dc 7e 58 e1 aa  |.<.@........~X..|
-00000030  4c d7 68 2a 91 15 03 03  00 30 00 00 00 00 00 00  |L.h*.....0......|
-00000040  00 00 00 00 00 00 00 00  00 00 b6 61 51 ac 66 a5  |...........aQ.f.|
-00000050  d1 ef d3 ee c8 d3 48 72  d5 e0 ef 7d ca 6a ec b2  |......Hr...}.j..|
-00000060  77 ff 2d a8 32 6d be 6e  a7 42                    |w.-.2m.n.B|
+00000010  00 00 00 00 00 e2 68 77  75 6a f8 3c 3d 2c 96 52  |......hwuj.<=,.R|
+00000020  2d fc d5 3b d3 17 c0 29  df 99 f1 09 23 13 9f 89  |-..;...)....#...|
+00000030  dd 21 15 23 36 15 03 03  00 30 00 00 00 00 00 00  |.!.#6....0......|
+00000040  00 00 00 00 00 00 00 00  00 00 37 4e ac 91 80 02  |..........7N....|
+00000050  4f 4a 9f b4 3c 0e 24 87  c8 d0 41 24 ce 01 e2 bb  |OJ..<.$...A$....|
+00000060  18 af bc ce 09 4b 41 f6  db 08                    |.....KA...|
index cdc71041fbb27ec71d14e20905e7e124d94c747b..cbc4bcc31137aa468eda4f4f3ee9e8f5fe125d24 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 f3 28 ca c9 ac  |....Y...U...(...|
-00000010  29 bb 15 80 56 d2 37 09  fa 7d 23 04 d4 79 e7 1d  |)...V.7..}#..y..|
-00000020  bb 4e c5 60 c8 44 39 02  6a e9 e0 20 b5 ae 39 87  |.N.`.D9.j.. ..9.|
-00000030  4e 24 2f 33 02 fe 72 d6  2a 4d 0c 8c da 36 7b 28  |N$/3..r.*M...6{(|
-00000040  3c 06 aa b2 60 68 91 7a  ae d8 7b e2 c0 2f 00 00  |<...`h.z..{../..|
+00000000  16 03 03 00 59 02 00 00  55 03 03 b6 96 f2 bc ed  |....Y...U.......|
+00000010  1b 14 73 de 12 10 cc e9  4d f2 c7 8b 46 d8 63 55  |..s.....M...F.cU|
+00000020  8f 04 33 ec 89 b5 70 93  01 1c f2 20 72 82 e1 16  |..3...p.... r...|
+00000030  9c 0e 70 25 84 2c 09 a6  4f 19 c0 ed 44 d6 98 13  |..p%.,..O...D...|
+00000040  97 f6 19 08 d4 b6 d3 ad  82 96 ef db c0 2f 00 00  |............./..|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 59 0b 00 02 55 00  02 52 00 02 4f 30 82 02  |..Y...U..R..O0..|
 00000070  4b 30 82 01 b4 a0 03 02  01 02 02 09 00 e8 f0 9d  |K0..............|
 00000290  77 8d 0c 1c f1 0f a1 d8  40 83 61 c9 4c 72 2b 9d  |w.......@.a.Lr+.|
 000002a0  ae db 46 06 06 4d f4 c1  b3 3e c0 d1 bd 42 d4 db  |..F..M...>...B..|
 000002b0  fe 3d 13 60 84 5c 21 d3  3b e9 fa e7 16 03 03 00  |.=.`.\!.;.......|
-000002c0  ac 0c 00 00 a8 03 00 1d  20 d4 df 5d 10 ee ba a6  |........ ..]....|
-000002d0  51 d7 1b fb bf ed bc d6  b9 34 44 e7 af 23 0e 9b  |Q........4D..#..|
-000002e0  45 af ba 7a 89 63 03 a9  4c 08 04 00 80 30 2c 0f  |E..z.c..L....0,.|
-000002f0  2e d9 e4 1d c2 90 01 1c  cc cf d4 fe 06 6d c3 aa  |.............m..|
-00000300  59 d9 d9 bc 16 2f 2c b1  be 90 a3 93 a7 be bc 4d  |Y..../,........M|
-00000310  d8 f4 ac 21 36 59 a8 21  94 ef d3 c4 53 14 34 18  |...!6Y.!....S.4.|
-00000320  c9 10 d5 77 fd 1e ad 15  0f 23 d7 73 90 7a c0 7b  |...w.....#.s.z.{|
-00000330  b3 b2 e2 df 15 42 35 ce  38 05 52 02 77 b7 b2 2b  |.....B5.8.R.w..+|
-00000340  6b 88 6a ce d4 20 99 9d  e4 fe e8 38 1e 01 b7 78  |k.j.. .....8...x|
-00000350  3c ea ac 8e ef 2f 7e e8  22 08 78 42 b7 db 84 80  |<..../~.".xB....|
-00000360  8c 61 8a c5 cc d7 1f 6a  8d 5c 1d 2d 0d 16 03 03  |.a.....j.\.-....|
+000002c0  ac 0c 00 00 a8 03 00 1d  20 21 1b d1 91 16 9c c1  |........ !......|
+000002d0  51 52 39 07 6b 6d ab 07  28 f7 d0 ae 02 13 5e 73  |QR9.km..(.....^s|
+000002e0  5b 51 30 96 27 57 56 e5  37 08 04 00 80 6a 13 82  |[Q0.'WV.7....j..|
+000002f0  97 81 ea 32 51 cb cb 8e  3b ee e5 dd 4f 80 20 50  |...2Q...;...O. P|
+00000300  c9 f0 19 9b d5 1b ae 21  f7 e6 24 4e a3 22 ec b9  |.......!..$N."..|
+00000310  25 6e 77 19 12 08 16 8a  c7 c1 db 29 e9 be 05 55  |%nw........)...U|
+00000320  09 c1 6e 44 c3 d7 bd 18  80 c8 1f 42 53 3b e6 09  |..nD.......BS;..|
+00000330  00 29 20 c4 94 04 97 6f  f7 e6 f4 3b 66 77 2f e5  |.) ....o...;fw/.|
+00000340  de 96 6f c3 67 c5 ce 4b  5e 4b 0e 90 02 fc 32 7f  |..o.g..K^K....2.|
+00000350  71 f4 63 76 37 57 75 30  fb 1b f5 99 98 5f c3 b1  |q.cv7Wu0....._..|
+00000360  fb e3 76 ad 8e 2f 7a 72  86 ed 34 18 98 16 03 03  |..v../zr..4.....|
 00000370  00 3a 0d 00 00 36 03 01  02 40 00 2e 04 03 05 03  |.:...6...@......|
 00000380  06 03 08 07 08 08 08 09  08 0a 08 0b 08 04 08 05  |................|
 00000390  08 06 04 01 05 01 06 01  03 03 02 03 03 01 02 01  |................|
 00000200  e5 35 16 03 03 00 25 10  00 00 21 20 2f e5 7d a3  |.5....%...! /.}.|
 00000210  47 cd 62 43 15 28 da ac  5f bb 29 07 30 ff f6 84  |G.bC.(.._.).0...|
 00000220  af c4 cf c2 ed 90 99 5f  58 cb 3b 74 16 03 03 00  |......._X.;t....|
-00000230  88 0f 00 00 84 08 04 00  80 b8 96 b3 c8 66 a9 fb  |.............f..|
-00000240  da 1b 82 65 9d 57 e5 e5  e5 60 c9 43 df 6e 99 53  |...e.W...`.C.n.S|
-00000250  45 95 b8 58 d1 19 05 50  e1 a7 3c e8 07 ad 57 09  |E..X...P..<...W.|
-00000260  9c 95 13 ea 80 24 53 56  b1 13 2d 59 9d e9 60 0f  |.....$SV..-Y..`.|
-00000270  75 97 d3 4f 82 3a b5 41  3e 90 75 ea 28 97 00 e7  |u..O.:.A>.u.(...|
-00000280  74 c9 04 1d d0 16 ba 40  75 9c ae a0 bd 00 b1 a9  |t......@u.......|
-00000290  86 d5 1a f2 30 45 72 99  ea b2 eb 61 b1 63 72 c5  |....0Er....a.cr.|
-000002a0  ad b1 60 a8 fa bd 95 95  17 03 4c 8e 87 4b 44 e5  |..`.......L..KD.|
-000002b0  ec f3 e0 48 33 b8 a9 74  78 14 03 03 00 01 01 16  |...H3..tx.......|
-000002c0  03 03 00 28 00 00 00 00  00 00 00 00 e6 a6 db ee  |...(............|
-000002d0  7d fb 48 9f 81 a6 78 6a  db a1 9a bb c8 da 7b b2  |}.H...xj......{.|
-000002e0  6a 01 66 fb 85 a7 2f 35  40 77 b6 b2              |j.f.../5@w..|
+00000230  88 0f 00 00 84 08 04 00  80 90 53 1e fc 7c 63 b0  |..........S..|c.|
+00000240  98 c5 19 40 fb 4f cf c3  53 51 81 68 54 c7 49 38  |...@.O..SQ.hT.I8|
+00000250  0c 41 f0 12 7d a6 e4 8a  4e 77 97 49 5a 07 7d 30  |.A..}...Nw.IZ.}0|
+00000260  fa df 77 2f 51 cf 37 65  07 0b 2c 91 15 43 1d c9  |..w/Q.7e..,..C..|
+00000270  69 46 e2 26 66 72 98 ec  62 1a 22 ae e8 3e 3a 28  |iF.&fr..b."..>:(|
+00000280  17 83 b9 74 57 59 a2 ec  31 95 17 1f c3 ec 9a 01  |...tWY..1.......|
+00000290  f2 d4 07 d5 ee d5 0e f2  f4 75 3b d6 b8 df aa ad  |.........u;.....|
+000002a0  0b 87 37 30 43 7e c1 b1  e1 0d 7e 90 3d 87 9d 93  |..70C~....~.=...|
+000002b0  d7 06 57 18 5c 12 c2 32  0d 14 03 03 00 01 01 16  |..W.\..2........|
+000002c0  03 03 00 28 00 00 00 00  00 00 00 00 ff 2a ae f8  |...(.........*..|
+000002d0  c9 1c bd 3f 62 0e 68 42  e7 96 ec ee c0 fa 71 34  |...?b.hB......q4|
+000002e0  f1 e2 67 76 82 cf c3 2a  fb b2 5a c1              |..gv...*..Z.|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 28 b3 9c 30 b6 a2  |..........(..0..|
-00000010  cb cf 75 38 10 e7 80 39  0e 87 39 9c d9 da 2c 53  |..u8...9..9...,S|
-00000020  1a 64 2d 33 ff 21 25 e9  3c f2 ec 6d a4 59 f4 30  |.d-3.!%.<..m.Y.0|
-00000030  ea 41 24                                          |.A$|
+00000000  14 03 03 00 01 01 16 03  03 00 28 da 70 e7 aa 1b  |..........(.p...|
+00000010  6c 66 cb 9b 07 d9 4e 87  6f 87 60 fb 46 f5 e9 33  |lf....N.o.`.F..3|
+00000020  48 59 ff 3e b5 bf 0b 0c  b2 39 79 64 f6 3c 2e 95  |HY.>.....9yd.<..|
+00000030  04 51 87                                          |.Q.|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 65 72 8f  |.............er.|
-00000010  4a 5f 08 c1 f9 37 5d 30  bc c6 e6 5f a8 23 35 69  |J_...7]0..._.#5i|
-00000020  d3 3c 7a 15 03 03 00 1a  00 00 00 00 00 00 00 02  |.<z.............|
-00000030  b0 48 2e 2e ed 4d 9c db  3a fc ff e6 57 83 fc 90  |.H...M..:...W...|
-00000040  aa 78                                             |.x|
+00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 21 29 d2  |.............!).|
+00000010  27 05 2d b4 a2 bf ea f2  96 8a 61 c9 91 75 9f 0f  |'.-.......a..u..|
+00000020  50 4a 76 15 03 03 00 1a  00 00 00 00 00 00 00 02  |PJv.............|
+00000030  a9 40 eb 86 b2 f0 85 a2  75 bc 4e 09 8c c9 ca 31  |.@......u.N....1|
+00000040  e5 49                                             |.I|
index 26308fc9dfdd5aa57681309d35d1a46e4637b00d..b8ecfffb91bfc784e264b3d7c3327a903a03da55 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 97 f2 cb de f1  |....Y...U.......|
-00000010  bb cf 9a 6c 6d 7e e2 94  af 9d 0b ed 02 cf fc b2  |...lm~..........|
-00000020  80 b2 7b 41 2c a6 83 e7  52 62 93 20 63 23 7f 48  |..{A,...Rb. c#.H|
-00000030  be c1 7f d3 75 34 fe 3a  ad 27 f5 99 b0 73 91 df  |....u4.:.'...s..|
-00000040  b3 e9 82 95 cd 1b f9 08  b6 3d 4f 9b c0 2f 00 00  |.........=O../..|
+00000000  16 03 03 00 59 02 00 00  55 03 03 ad e1 a7 5e 0b  |....Y...U.....^.|
+00000010  b8 bd 9d 05 c2 8e 6c f2  ea 7d a1 c8 32 cc d1 74  |......l..}..2..t|
+00000020  ba 86 75 98 33 27 39 c3  0a 6f 49 20 2b 37 9a 0f  |..u.3'9..oI +7..|
+00000030  9b de 1f 1d 5f 2b 45 29  6c 9b 33 c6 bc c1 15 a4  |...._+E)l.3.....|
+00000040  19 9b 70 6c 15 eb 4a 92  92 5f b7 6b c0 2f 00 00  |..pl..J.._.k./..|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 59 0b 00 02 55 00  02 52 00 02 4f 30 82 02  |..Y...U..R..O0..|
 00000070  4b 30 82 01 b4 a0 03 02  01 02 02 09 00 e8 f0 9d  |K0..............|
 00000290  77 8d 0c 1c f1 0f a1 d8  40 83 61 c9 4c 72 2b 9d  |w.......@.a.Lr+.|
 000002a0  ae db 46 06 06 4d f4 c1  b3 3e c0 d1 bd 42 d4 db  |..F..M...>...B..|
 000002b0  fe 3d 13 60 84 5c 21 d3  3b e9 fa e7 16 03 03 00  |.=.`.\!.;.......|
-000002c0  ac 0c 00 00 a8 03 00 1d  20 f8 3a 6c 5b 6f 88 48  |........ .:l[o.H|
-000002d0  19 c5 a2 e7 4a d9 6d 21  56 23 63 1b 1f 95 aa bc  |....J.m!V#c.....|
-000002e0  33 ac aa 3b bb f8 35 ba  1a 04 01 00 80 98 6d 7b  |3..;..5.......m{|
-000002f0  7d 40 13 81 6b 70 ec ac  60 ee 1d 3e 37 36 bc f4  |}@..kp..`..>76..|
-00000300  c1 9f 3c 13 b7 06 3d 38  be 4f 8c 3e e2 2e f2 b5  |..<...=8.O.>....|
-00000310  de 16 ec a0 5b 64 00 5c  c3 50 cc 79 a2 f7 e0 8d  |....[d.\.P.y....|
-00000320  68 e6 6b 1b b8 57 a4 15  d0 2c d7 4a be 97 26 26  |h.k..W...,.J..&&|
-00000330  8c 5c 4e 26 36 96 48 b5  0f 88 7b 37 43 e4 d1 24  |.\N&6.H...{7C..$|
-00000340  01 3c 70 38 99 c6 e2 2f  66 e7 db 57 30 f2 72 d0  |.<p8.../f..W0.r.|
-00000350  17 fd ad 09 a7 bd ee de  ca fd 57 15 de 25 b6 1f  |..........W..%..|
-00000360  ed 45 86 22 83 4e 64 54  56 17 1f 81 4f 16 03 03  |.E.".NdTV...O...|
+000002c0  ac 0c 00 00 a8 03 00 1d  20 ba ad fb 1e 28 95 96  |........ ....(..|
+000002d0  f3 62 9d 97 87 0f fd fc  a9 91 a2 4b 8d 69 ec 8f  |.b.........K.i..|
+000002e0  7d 49 08 6e fe 7d b3 5b  03 04 01 00 80 86 57 23  |}I.n.}.[......W#|
+000002f0  58 bb 9a 50 d8 bb 99 d9  f5 cc 66 43 38 f0 14 8a  |X..P......fC8...|
+00000300  cb 6d 8b c0 83 52 f8 53  75 94 07 e3 12 2c 10 bb  |.m...R.Su....,..|
+00000310  f3 9b 74 84 1f 11 f3 06  c3 f4 df db f0 1e 0a cd  |..t.............|
+00000320  1b 45 18 44 88 67 79 ca  3e 6e 2b 73 c2 10 84 d8  |.E.D.gy.>n+s....|
+00000330  7b c5 2e 81 7d 53 19 46  09 35 35 8b 66 8a a8 cc  |{...}S.F.55.f...|
+00000340  20 ba 20 15 9f d1 27 9c  6b 3c bb 48 79 4a 7e 11  | . ...'.k<.HyJ~.|
+00000350  da e3 26 5b 3a 95 da 4d  bd 86 3e 8c 97 55 7c 22  |..&[:..M..>..U|"|
+00000360  a1 d3 88 61 ae e1 3b 51  25 c6 01 7e 10 16 03 03  |...a..;Q%..~....|
 00000370  00 0c 0d 00 00 08 01 01  00 02 04 01 00 00 16 03  |................|
 00000380  03 00 04 0e 00 00 00                              |.......|
 >>> Flow 3 (client to server)
 00000200  e5 35 16 03 03 00 25 10  00 00 21 20 2f e5 7d a3  |.5....%...! /.}.|
 00000210  47 cd 62 43 15 28 da ac  5f bb 29 07 30 ff f6 84  |G.bC.(.._.).0...|
 00000220  af c4 cf c2 ed 90 99 5f  58 cb 3b 74 16 03 03 00  |......._X.;t....|
-00000230  88 0f 00 00 84 04 01 00  80 a8 12 9d 84 c2 17 0a  |................|
-00000240  03 ae bd 87 9a b6 6f 65  2f 7a 04 1f 69 2a 41 f4  |......oe/z..i*A.|
-00000250  d0 9a 4d a4 5b 6e d2 d3  42 c3 77 4f 04 28 ce e6  |..M.[n..B.wO.(..|
-00000260  d4 25 c5 81 1b 78 91 e9  1e 93 90 57 b2 58 6f 26  |.%...x.....W.Xo&|
-00000270  ed 20 15 62 ff e9 c6 c1  52 4a 9a 05 a6 cd 17 22  |. .b....RJ....."|
-00000280  75 c8 81 da a4 96 af c6  83 b5 5c 81 93 59 44 26  |u.........\..YD&|
-00000290  5b 03 59 9d ab 93 ee c7  37 61 74 e7 4a 22 1c ec  |[.Y.....7at.J"..|
-000002a0  96 fb a2 c9 ea 2d 4b 8d  d3 a7 e4 60 57 10 be b7  |.....-K....`W...|
-000002b0  60 80 4f ee 8e 21 6b a2  13 14 03 03 00 01 01 16  |`.O..!k.........|
-000002c0  03 03 00 28 00 00 00 00  00 00 00 00 16 82 4a c0  |...(..........J.|
-000002d0  98 7b 62 3e 9b da a9 ac  31 f2 32 a9 23 13 2f e3  |.{b>....1.2.#./.|
-000002e0  77 c9 1e ca 39 9f 4c 8a  10 58 33 67              |w...9.L..X3g|
+00000230  88 0f 00 00 84 04 01 00  80 12 a4 42 13 85 6f 92  |...........B..o.|
+00000240  6d 26 5d 05 3c b7 80 ab  a9 e0 74 3d 89 67 79 a0  |m&].<.....t=.gy.|
+00000250  9f e1 a9 20 d8 82 e2 22  99 38 03 fe 32 d9 1f c7  |... ...".8..2...|
+00000260  39 1e 27 31 59 05 eb aa  bc 2c 10 eb f0 82 65 65  |9.'1Y....,....ee|
+00000270  ce b2 e9 83 67 21 43 03  19 2d 14 9f c3 db bc dc  |....g!C..-......|
+00000280  59 66 95 d7 4e 09 3c f0  f2 4a 39 f7 db c4 0c 4e  |Yf..N.<..J9....N|
+00000290  73 e2 d6 59 f1 bc 06 d8  75 df 32 b7 f1 b4 01 98  |s..Y....u.2.....|
+000002a0  4f 93 43 a3 a6 09 da cd  1c ee 26 65 ab d1 2a 56  |O.C.......&e..*V|
+000002b0  74 32 24 46 27 f3 d9 6a  df 14 03 03 00 01 01 16  |t2$F'..j........|
+000002c0  03 03 00 28 00 00 00 00  00 00 00 00 68 27 5e 44  |...(........h'^D|
+000002d0  d7 73 26 f6 51 86 01 f5  f3 5d 61 a0 05 cd c3 00  |.s&.Q....]a.....|
+000002e0  85 6f ea 56 85 1e 7a c3  4c d3 6d 64              |.o.V..z.L.md|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 28 8e 56 d0 9c 38  |..........(.V..8|
-00000010  4f d9 df 12 9b dd 96 05  94 77 2f 6d 24 a8 cb 56  |O........w/m$..V|
-00000020  91 f9 bc ec 00 b5 cc 71  c4 f4 36 42 be 68 37 78  |.......q..6B.h7x|
-00000030  8f 6e 8c                                          |.n.|
+00000000  14 03 03 00 01 01 16 03  03 00 28 81 f3 33 d8 2a  |..........(..3.*|
+00000010  57 45 53 2c ee 68 8b 79  ed 07 dc 90 c3 a7 84 38  |WES,.h.y.......8|
+00000020  8c 33 03 e9 c6 51 04 b2  73 8a 8b 81 12 eb 6c 5f  |.3...Q..s.....l_|
+00000030  a3 8f 5e                                          |..^|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 1c 19 9e  |................|
-00000010  a5 40 f6 d7 8b 80 23 8a  0b fa 14 65 08 6a 3c 66  |.@....#....e.j<f|
-00000020  07 c4 d2 15 03 03 00 1a  00 00 00 00 00 00 00 02  |................|
-00000030  16 7c e2 68 a5 d4 df 64  f4 1c 7d 17 b6 14 0a 4c  |.|.h...d..}....L|
-00000040  40 8e                                             |@.|
+00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 e5 c6 d7  |................|
+00000010  4d e0 d1 0c ff a0 66 c4  71 53 af 7e 16 01 3d 2e  |M.....f.qS.~..=.|
+00000020  6c ab 90 15 03 03 00 1a  00 00 00 00 00 00 00 02  |l...............|
+00000030  92 12 87 24 c8 7e 74 23  df f7 23 49 01 9a dd 3b  |...$.~t#..#I...;|
+00000040  2c 68                                             |,h|
index 3f740807f6a01f6dc93c5fdb402b47de38120565..de05fec53ecee08a79f0e503aa989e134a1d2740 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 29 bc e2 fe ae  |....Y...U..)....|
-00000010  0a db 37 e6 39 d5 48 24  3d 0f e5 d7 6b a3 69 dd  |..7.9.H$=...k.i.|
-00000020  ce 09 fd 28 03 c2 7e 38  db c9 ec 20 d2 5e 3f 94  |...(..~8... .^?.|
-00000030  b0 2c 5e 4c 77 c2 94 c3  f2 a9 d0 91 4f 96 45 0e  |.,^Lw.......O.E.|
-00000040  d3 34 fc 9f e0 a5 e6 fc  1e 8a c1 00 c0 2f 00 00  |.4.........../..|
+00000000  16 03 03 00 59 02 00 00  55 03 03 61 fe 1e 35 33  |....Y...U..a..53|
+00000010  4b b4 dd 9b 0f 55 58 f4  0c c5 b2 73 51 7b 84 e7  |K....UX....sQ{..|
+00000020  25 f7 8f 12 5a 12 11 e1  7b e6 52 20 ad 86 a9 f9  |%...Z...{.R ....|
+00000030  7f 6a 30 da 79 23 c3 c4  dc 88 f6 19 1d cc 16 8b  |.j0.y#..........|
+00000040  96 74 84 ce 53 56 65 e2  cb 94 61 0c c0 2f 00 00  |.t..SVe...a../..|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 66 0b 00 02 62 00  02 5f 00 02 5c 30 82 02  |..f...b.._..\0..|
 00000070  58 30 82 01 8d a0 03 02  01 02 02 11 00 f2 99 26  |X0.............&|
 000002a0  11 89 66 79 d1 8e 88 0e  0b a0 9e 30 2a c0 67 ef  |..fy.......0*.g.|
 000002b0  ca 46 02 88 e9 53 81 22  69 22 97 ad 80 93 d4 f7  |.F...S."i"......|
 000002c0  dd 70 14 24 d7 70 0a 46  a1 16 03 03 00 ac 0c 00  |.p.$.p.F........|
-000002d0  00 a8 03 00 1d 20 9e e4  39 3a b3 d5 f9 51 16 d4  |..... ..9:...Q..|
-000002e0  a8 e1 0a 6d ad 3c ca 01  97 d6 a1 ce 03 2a 67 4a  |...m.<.......*gJ|
-000002f0  49 06 eb ed c6 24 08 04  00 80 b3 b7 9e fd 97 9b  |I....$..........|
-00000300  b0 d6 35 89 21 53 ff a8  4b 59 59 26 37 ac 2f 36  |..5.!S..KYY&7./6|
-00000310  27 3d 5a 04 3f 50 ed 36  e0 5f 1a d7 1b 36 47 94  |'=Z.?P.6._...6G.|
-00000320  45 ec 8c 0b 8f 0f fc df  ec 3c 56 f0 d0 28 45 94  |E........<V..(E.|
-00000330  96 c7 35 bb 42 31 a6 6e  eb 27 cf cf 7e 21 cf 2f  |..5.B1.n.'..~!./|
-00000340  a1 90 5d 2b 32 23 b3 de  40 a7 b6 56 c1 73 29 56  |..]+2#..@..V.s)V|
-00000350  3d 73 fe 34 b2 0b 58 97  16 e6 a1 1c 47 0e 24 a7  |=s.4..X.....G.$.|
-00000360  0d c9 a0 51 70 82 b1 d1  a6 a1 bc b4 49 77 c4 c4  |...Qp.......Iw..|
-00000370  87 ae c8 49 e6 80 ae d0  dd ca 16 03 03 00 0c 0d  |...I............|
+000002d0  00 a8 03 00 1d 20 e0 90  02 58 37 69 79 d6 78 e5  |..... ...X7iy.x.|
+000002e0  1d c6 7e a0 c6 38 1b ff  47 72 d6 c2 52 cb 6c 52  |..~..8..Gr..R.lR|
+000002f0  36 7e 03 c3 35 1d 08 04  00 80 79 5f 23 fd b1 ee  |6~..5.....y_#...|
+00000300  ac 62 c8 72 09 52 1f 9a  0f ac 95 3e 4e e4 97 d2  |.b.r.R.....>N...|
+00000310  a3 04 ae 19 3f 25 ad 3e  b7 78 1f d9 79 5f c8 26  |....?%.>.x..y_.&|
+00000320  f0 26 e5 ee 54 46 4a 05  84 15 01 4f 7a 7e 60 bd  |.&..TFJ....Oz~`.|
+00000330  86 74 78 d7 7c 86 91 2b  4f 76 b6 aa 78 27 c8 21  |.tx.|..+Ov..x'.!|
+00000340  7e df 88 2f 26 f0 9d 3c  a2 e8 95 f6 9f 5a a4 5e  |~../&..<.....Z.^|
+00000350  18 dc cd 0d 70 e8 85 b7  e5 57 f6 c2 f4 33 28 1c  |....p....W...3(.|
+00000360  58 7b 94 b0 9e ee d8 b3  42 b5 f3 63 78 a1 30 f3  |X{......B..cx.0.|
+00000370  f7 e4 5e 72 64 6f 80 32  70 4e 16 03 03 00 0c 0d  |..^rdo.2pN......|
 00000380  00 00 08 01 01 00 02 08  04 00 00 16 03 03 00 04  |................|
 00000390  0e 00 00 00                                       |....|
 >>> Flow 3 (client to server)
 00000270  10 00 00 21 20 2f e5 7d  a3 47 cd 62 43 15 28 da  |...! /.}.G.bC.(.|
 00000280  ac 5f bb 29 07 30 ff f6  84 af c4 cf c2 ed 90 99  |._.).0..........|
 00000290  5f 58 cb 3b 74 16 03 03  00 88 0f 00 00 84 08 04  |_X.;t...........|
-000002a0  00 80 a6 6b 99 15 5e 97  33 4f a8 0e 59 af 15 22  |...k..^.3O..Y.."|
-000002b0  f3 6e be 02 6e e4 20 d5  81 c0 b4 74 5a e2 20 32  |.n..n. ....tZ. 2|
-000002c0  2b 7f 9c e6 94 32 4d 30  bf 93 86 9b 75 4d f1 9f  |+....2M0....uM..|
-000002d0  e4 48 28 00 27 fa 7c 45  2e fe d7 0b dc 03 c4 6b  |.H(.'.|E.......k|
-000002e0  42 ad a2 32 d7 9d ea d6  52 05 3f ed 87 fd b9 9d  |B..2....R.?.....|
-000002f0  58 fd d6 9f 28 6d 45 07  de 5b 4a 8e f4 4d 19 0b  |X...(mE..[J..M..|
-00000300  cf 4e 64 75 73 ae cd e9  ae f9 af 27 d0 b9 eb 4c  |.Ndus......'...L|
-00000310  98 ad 66 6d 4e bf 2c 39  87 f3 72 3e 4e bc a1 8f  |..fmN.,9..r>N...|
-00000320  a8 1e 14 03 03 00 01 01  16 03 03 00 28 00 00 00  |............(...|
-00000330  00 00 00 00 00 04 3c cc  ae cd 19 52 6b 1e 0e cc  |......<....Rk...|
-00000340  dd a9 ac 2f 2a c6 94 4c  09 f3 ee 2f b5 5a 13 1e  |.../*..L.../.Z..|
-00000350  4f 54 a0 ae c2                                    |OT...|
+000002a0  00 80 b2 c4 60 82 75 ca  be 40 dc 28 ec 6d 14 6f  |....`.u..@.(.m.o|
+000002b0  6c 88 ca 9a d7 ae ce 94  26 a7 10 ad d8 c3 b9 a6  |l.......&.......|
+000002c0  48 4e 01 7d ee 6e f8 e0  15 d9 72 c4 79 8d ac 25  |HN.}.n....r.y..%|
+000002d0  37 29 83 fc e6 f1 2e 4f  76 49 6a 36 b9 1e b4 58  |7).....OvIj6...X|
+000002e0  a2 3e f7 ff 96 5e d9 17  f2 40 05 1f ec bb 5b f5  |.>...^...@....[.|
+000002f0  28 86 d2 fc 0e 7e 70 3a  3d 90 4c 46 a5 3e bc 57  |(....~p:=.LF.>.W|
+00000300  24 4c ee 35 23 99 6f 21  12 db ba d8 3a 5f 37 1f  |$L.5#.o!....:_7.|
+00000310  da 3d c2 c9 bf b6 11 8b  b9 b9 43 0b 52 ff 6d 2a  |.=........C.R.m*|
+00000320  74 a7 14 03 03 00 01 01  16 03 03 00 28 00 00 00  |t...........(...|
+00000330  00 00 00 00 00 34 bd 90  a0 3f 1c 0c 11 5c 8a e4  |.....4...?...\..|
+00000340  28 82 c4 57 59 73 fd a4  dc a9 91 4b df 2a c6 b5  |(..WYs.....K.*..|
+00000350  f0 6e cf 41 70                                    |.n.Ap|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 28 6d 44 cb 35 8b  |..........(mD.5.|
-00000010  15 5c f9 f8 1e ae 4f 8c  8c d9 90 9e 6c cf 13 f6  |.\....O.....l...|
-00000020  12 29 f5 f7 d6 ff da e2  48 7d 68 ec ad 1a 6c 39  |.)......H}h...l9|
-00000030  c5 77 6c                                          |.wl|
+00000000  14 03 03 00 01 01 16 03  03 00 28 e2 44 81 59 e4  |..........(.D.Y.|
+00000010  6c cf e2 e7 04 78 61 02  36 29 2c 5c c4 6f 13 0b  |l....xa.6),\.o..|
+00000020  29 ba 74 b0 13 e8 8f 67  39 b5 ea d1 9d 99 d2 f6  |).t....g9.......|
+00000030  f7 32 be                                          |.2.|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 2a ce da  |.............*..|
-00000010  11 1c 7d 49 0d aa 44 d4  d6 d4 7f 64 2b 49 47 20  |..}I..D....d+IG |
-00000020  5a 21 bb 15 03 03 00 1a  00 00 00 00 00 00 00 02  |Z!..............|
-00000030  fc 10 75 a7 22 f9 74 1c  3a d2 b2 a8 04 2d 37 5f  |..u.".t.:....-7_|
-00000040  c2 76                                             |.v|
+00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 5c 7b 38  |.............\{8|
+00000010  46 af 57 57 05 5a c5 cb  83 f3 fd 17 d4 c3 2e 93  |F.WW.Z..........|
+00000020  d7 70 52 15 03 03 00 1a  00 00 00 00 00 00 00 02  |.pR.............|
+00000030  df 2b d8 62 ec 97 c6 ab  be d4 7f c9 91 f4 fe 55  |.+.b...........U|
+00000040  ac bd                                             |..|
index 95781c6853b84226b923268fcd8909506e382991..d21e9b3704926ae1f8ed6ed3a62d3680e8efe9c2 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 eb a2 77 eb b6  |....Y...U....w..|
-00000010  1e e4 5c 2c ed 5a dc 93  1b 7e 8a 75 a1 8c ac a6  |..\,.Z...~.u....|
-00000020  69 13 f6 f6 a4 69 07 93  99 cf 12 20 37 d7 f8 26  |i....i..... 7..&|
-00000030  46 ea 3a 21 03 d0 25 0f  22 84 8d 24 2f 98 3d 42  |F.:!..%."..$/.=B|
-00000040  eb 47 1d de 0c 12 ab 95  7a 55 46 f7 c0 09 00 00  |.G......zUF.....|
+00000000  16 03 03 00 59 02 00 00  55 03 03 ec 4a 6a f8 c5  |....Y...U...Jj..|
+00000010  42 65 f9 d3 4f 65 6f 14  6b bd ae a9 82 5d 06 9b  |Be..Oeo.k....]..|
+00000020  9d 03 bb 67 eb ba 52 70  74 c3 01 20 f2 ef 69 54  |...g..Rpt.. ..iT|
+00000030  1f 4b 79 f7 5b d5 08 b4  18 4c af 8e 55 58 45 22  |.Ky.[....L..UXE"|
+00000040  c1 c9 6f cf 36 67 45 20  c7 c5 3a af c0 09 00 00  |..o.6gE ..:.....|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
 00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
 00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
 00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
 00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
-00000270  2a 16 03 03 00 b7 0c 00  00 b3 03 00 1d 20 90 68  |*............ .h|
-00000280  81 8b 1d 7f d5 69 36 d3  4e 63 40 fa 3a 21 ee a4  |.....i6.Nc@.:!..|
-00000290  c7 b4 09 bc 34 51 89 df  d5 d2 79 51 34 32 04 03  |....4Q....yQ42..|
-000002a0  00 8b 30 81 88 02 42 01  b4 69 6b 1c e6 35 99 81  |..0...B..ik..5..|
-000002b0  fb aa cb b4 2d e9 e0 48  6a 6c 5e 14 54 77 b7 9d  |....-..Hjl^.Tw..|
-000002c0  df a3 c2 1b 53 8c d2 46  6d 2e ae 83 3a db 7c 86  |....S..Fm...:.|.|
-000002d0  4a 45 c7 51 cd 30 d6 8c  f5 4f ea 37 cb 1e 27 18  |JE.Q.0...O.7..'.|
-000002e0  ba df d5 5f 11 ae 0e af  75 02 42 01 2b 37 2e 6d  |..._....u.B.+7.m|
-000002f0  7c 11 57 b7 b7 8b 90 73  cd e0 c9 38 3c ee aa d5  ||.W....s...8<...|
-00000300  f2 cd ff b9 66 6a be 62  70 74 ee a4 f4 e3 fb 4f  |....fj.bpt.....O|
-00000310  ed 2e d5 a7 b5 a4 53 c8  1b 17 9e e9 48 e1 dd a6  |......S.....H...|
-00000320  e8 6a 05 cf 73 b2 85 11  13 37 be e0 26 16 03 03  |.j..s....7..&...|
+00000270  2a 16 03 03 00 b7 0c 00  00 b3 03 00 1d 20 7f e5  |*............ ..|
+00000280  3b 03 9e 6a 77 11 1b 0f  bc 4a db 44 7c 3b 81 1c  |;..jw....J.D|;..|
+00000290  03 8b 15 a6 f3 16 a0 58  5b 13 c5 1e d2 2c 04 03  |.......X[....,..|
+000002a0  00 8b 30 81 88 02 42 00  cc 7c 76 94 81 89 8f 25  |..0...B..|v....%|
+000002b0  16 e2 a0 0d 80 4f 7a 8f  8c 83 23 53 23 45 9c c1  |.....Oz...#S#E..|
+000002c0  39 e3 0c c2 1b 4d f3 78  cd ea b9 c8 d4 b6 30 bb  |9....M.x......0.|
+000002d0  ff d7 ad 6c b2 fd 62 4d  8a 05 19 cf 58 ec 81 17  |...l..bM....X...|
+000002e0  21 7c 71 a1 d7 ad 87 11  8d 02 42 01 a2 9e c8 e4  |!|q.......B.....|
+000002f0  04 7c 75 22 df 14 97 94  8a 1b a1 34 95 95 dd 4c  |.|u".......4...L|
+00000300  9f 1a c7 c7 96 db ef 87  82 27 9a 27 3a 3d 75 26  |.........'.':=u&|
+00000310  04 47 66 eb 55 60 9f 93  4e b2 09 14 fa 71 5b 3f  |.Gf.U`..N....q[?|
+00000320  33 37 3f 0c f2 5c 4f 1e  cc fa b1 6f 70 16 03 03  |37?..\O....op...|
 00000330  00 04 0e 00 00 00                                 |......|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 25 10 00 00  21 20 2f e5 7d a3 47 cd  |....%...! /.}.G.|
 00000010  62 43 15 28 da ac 5f bb  29 07 30 ff f6 84 af c4  |bC.(.._.).0.....|
 00000020  cf c2 ed 90 99 5f 58 cb  3b 74 14 03 03 00 01 01  |....._X.;t......|
 00000030  16 03 03 00 40 00 00 00  00 00 00 00 00 00 00 00  |....@...........|
-00000040  00 00 00 00 00 7f 83 b7  cd 14 66 fb c3 2a f9 9f  |..........f..*..|
-00000050  79 ec 40 e5 dd 15 46 f3  25 8d dd b2 8e d5 78 97  |y.@...F.%.....x.|
-00000060  e5 d6 4e 1a 2e 35 21 b2  aa ac 28 6f 2c 36 a6 6e  |..N..5!...(o,6.n|
-00000070  44 92 84 1b b9                                    |D....|
+00000040  00 00 00 00 00 d6 67 cb  d5 7c 95 9b 16 e2 3b 86  |......g..|....;.|
+00000050  22 bd 8c c7 40 36 9b b6  7e 0a 77 78 38 14 37 3c  |"...@6..~.wx8.7<|
+00000060  48 42 37 a7 07 31 bb 57  c4 e9 f5 e5 a7 58 71 f8  |HB7..1.W.....Xq.|
+00000070  82 f7 12 97 72                                    |....r|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 40 db ee f8 c1 0e  |..........@.....|
-00000010  7f 23 b4 cb e6 db 03 2a  fb 68 40 78 85 03 9e dc  |.#.....*.h@x....|
-00000020  ac f8 f0 b5 65 8d 7c 01  4a ce 86 29 a9 c5 c3 b2  |....e.|.J..)....|
-00000030  12 8d d1 58 af e7 21 75  e4 be f3 c0 03 55 f8 bb  |...X..!u.....U..|
-00000040  71 bd 85 ee 46 87 a0 32  75 ee 4c                 |q...F..2u.L|
+00000000  14 03 03 00 01 01 16 03  03 00 40 56 45 5c a3 b3  |..........@VE\..|
+00000010  64 43 54 7f b5 90 1a 34  ab 2b 68 25 49 41 bf 78  |dCT....4.+h%IA.x|
+00000020  50 b0 66 35 20 76 e1 d0  5c 8a 82 2e 03 83 cf c6  |P.f5 v..\.......|
+00000030  b7 48 3d 2c c4 cf f5 31  c1 ab 9a 3b 09 3a 75 e3  |.H=,...1...;.:u.|
+00000040  b2 05 fa d9 79 cc 1b 0e  30 44 e1                 |....y...0D.|
 >>> Flow 5 (client to server)
 00000000  17 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
-00000010  00 00 00 00 00 48 95 f8  a1 0e a7 d0 50 dd cf 8f  |.....H......P...|
-00000020  c4 af ec 49 89 bf 5d 8b  a0 d0 60 7b 38 5a 83 e4  |...I..]...`{8Z..|
-00000030  72 47 7f 81 bd 15 03 03  00 30 00 00 00 00 00 00  |rG.......0......|
-00000040  00 00 00 00 00 00 00 00  00 00 48 06 f1 30 61 dd  |..........H..0a.|
-00000050  e2 97 aa 9c 5f a7 07 bb  44 a4 fb d6 6a 7c aa f5  |...._...D...j|..|
-00000060  16 ae 38 1a 98 e5 f5 28  c2 57                    |..8....(.W|
+00000010  00 00 00 00 00 76 5f 1f  ec 55 ec f4 87 06 91 b4  |.....v_..U......|
+00000020  ba 71 4f 7f 9c ce e1 c7  e6 3d 75 05 fd ba 98 c4  |.qO......=u.....|
+00000030  d0 39 24 b8 d4 15 03 03  00 30 00 00 00 00 00 00  |.9$......0......|
+00000040  00 00 00 00 00 00 00 00  00 00 e8 4e 09 a1 5f db  |...........N.._.|
+00000050  91 d5 5b e8 6a 86 7a 6c  7d 4a e1 94 8a 7d 99 52  |..[.j.zl}J...}.R|
+00000060  e6 5d d8 35 7c a0 68 8f  09 f9                    |.].5|.h...|
index 7214747d15eac01d1397570e60a283ec8f8e1d96..02bad39f16b440400a1b177303c9e63cf1b261bd 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 c9 a1 8b 70 59  |....Y...U.....pY|
-00000010  8b 88 41 56 b7 bc 9a 1f  50 57 46 7d 79 d8 ef b2  |..AV....PWF}y...|
-00000020  15 3f ad ad bb 48 09 ce  e1 c2 2c 20 84 43 65 e7  |.?...H...., .Ce.|
-00000030  3f 2f d8 13 9a 79 ac 54  ee b9 13 a1 7c a7 05 f7  |?/...y.T....|...|
-00000040  c8 b4 fc bd 20 40 17 ca  15 cd 91 1e c0 2b 00 00  |.... @.......+..|
+00000000  16 03 03 00 59 02 00 00  55 03 03 d4 97 12 a8 e7  |....Y...U.......|
+00000010  be a9 2d 80 f0 db 01 49  07 04 f4 d1 02 db 3d 4a  |..-....I......=J|
+00000020  f0 af 31 38 39 d7 4c 1a  d3 74 71 20 0f a3 76 14  |..189.L..tq ..v.|
+00000030  73 ff 25 1b ef 29 b3 5e  0b 8f fe ee a6 19 d3 31  |s.%..).^.......1|
+00000040  5d 2e 71 ab 74 58 e9 d6  c5 9b f4 93 c0 2b 00 00  |].q.tX.......+..|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
 00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
 00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
 00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
 00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
-00000270  2a 16 03 03 00 b7 0c 00  00 b3 03 00 1d 20 58 f9  |*............ X.|
-00000280  2e 03 90 fa 3d 33 0d 3e  e1 3a b1 5a 45 ec 5c ee  |....=3.>.:.ZE.\.|
-00000290  9f 47 51 4b 93 89 33 11  e0 63 86 fd b2 3b 04 03  |.GQK..3..c...;..|
-000002a0  00 8b 30 81 88 02 42 01  c2 fa 7b f8 ed 6b a5 0f  |..0...B...{..k..|
-000002b0  33 87 02 35 5b 8e 5d 31  5e 92 df c2 90 ae 58 24  |3..5[.]1^.....X$|
-000002c0  43 0f ba e3 b8 77 12 7a  97 c3 77 15 62 d3 f2 cc  |C....w.z..w.b...|
-000002d0  10 cd a9 be b6 b2 37 93  b1 ce 8b b2 6c fa 93 74  |......7.....l..t|
-000002e0  5e 14 8e ba 9e d7 66 48  b8 02 42 01 8e 9a 10 1d  |^.....fH..B.....|
-000002f0  7d e0 d3 cf 0d d0 3c bc  34 1c 16 20 85 50 03 3f  |}.....<.4.. .P.?|
-00000300  e1 6d a3 a0 d4 6e d8 fd  7e df b4 c1 84 29 c3 68  |.m...n..~....).h|
-00000310  c2 01 dd 77 fc 2c a5 8f  3b 74 c6 e4 32 20 b7 a0  |...w.,..;t..2 ..|
-00000320  8c 1b 2d 93 6a 9c 8a ed  21 b5 9a e0 cb 16 03 03  |..-.j...!.......|
+00000270  2a 16 03 03 00 b7 0c 00  00 b3 03 00 1d 20 a8 15  |*............ ..|
+00000280  13 40 df f8 dc 39 f0 af  90 53 a8 34 a9 61 68 c8  |.@...9...S.4.ah.|
+00000290  ad be 4f 02 0e d2 83 fd  2e 35 bf 8c 8e 13 04 03  |..O......5......|
+000002a0  00 8b 30 81 88 02 42 00  bc 69 df 5b ec 9f 17 ff  |..0...B..i.[....|
+000002b0  e6 e5 24 71 f6 2b a5 88  40 78 12 ef f3 dc 25 a9  |..$q.+..@x....%.|
+000002c0  7c 89 24 0d c7 46 b2 db  ae 72 b4 2a 87 87 fe 7e  ||.$..F...r.*...~|
+000002d0  22 8f e6 d4 c4 7b 61 14  c3 04 39 98 87 6f 1f 54  |"....{a...9..o.T|
+000002e0  e0 50 16 0b 52 8e d6 1e  0a 02 42 00 b7 40 26 a8  |.P..R.....B..@&.|
+000002f0  11 09 77 ec 36 e5 88 26  6d 83 6f e7 c3 b1 98 c3  |..w.6..&m.o.....|
+00000300  4b 83 92 48 65 31 87 68  ee 49 25 ec 95 59 82 b5  |K..He1.h.I%..Y..|
+00000310  93 92 c8 17 d6 d9 1c 99  60 48 1b 18 50 b4 e7 df  |........`H..P...|
+00000320  ed 75 1a f2 08 e8 3d 93  99 27 ef 4d e3 16 03 03  |.u....=..'.M....|
 00000330  00 04 0e 00 00 00                                 |......|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 25 10 00 00  21 20 2f e5 7d a3 47 cd  |....%...! /.}.G.|
 00000010  62 43 15 28 da ac 5f bb  29 07 30 ff f6 84 af c4  |bC.(.._.).0.....|
 00000020  cf c2 ed 90 99 5f 58 cb  3b 74 14 03 03 00 01 01  |....._X.;t......|
-00000030  16 03 03 00 28 00 00 00  00 00 00 00 00 c2 14 2d  |....(..........-|
-00000040  fc d7 a2 cb 18 b9 2a ae  38 70 b7 78 7c 88 97 d3  |......*.8p.x|...|
-00000050  ff 7f df 12 23 96 ab 4d  6c 5c 67 72 c4           |....#..Ml\gr.|
+00000030  16 03 03 00 28 00 00 00  00 00 00 00 00 30 f1 a9  |....(........0..|
+00000040  4a 7e 86 a1 5d b7 db 2f  c6 e2 ec 36 41 83 66 75  |J~..]../...6A.fu|
+00000050  a3 6c 7d e7 61 36 ac f7  76 f8 8e d8 81           |.l}.a6..v....|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 28 2a dd b3 5b c6  |..........(*..[.|
-00000010  76 e7 c0 ac 8c 70 77 d6  d8 4e 79 4a 04 3d 91 a9  |v....pw..NyJ.=..|
-00000020  ad 79 ef c9 22 78 17 9e  ef b0 03 c8 e6 85 b7 8c  |.y.."x..........|
-00000030  e5 74 95                                          |.t.|
+00000000  14 03 03 00 01 01 16 03  03 00 28 2c 78 86 13 dc  |..........(,x...|
+00000010  a4 b9 bf ad 50 45 a3 d9  b3 df 33 a2 79 b1 1b 25  |....PE....3.y..%|
+00000020  12 94 97 99 07 6b 52 c4  52 64 ab 89 40 8c 93 4a  |.....kR.Rd..@..J|
+00000030  e3 cc d9                                          |...|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 84 b5 0f  |................|
-00000010  1f ed f9 4c 0d a1 f3 7b  8e 23 87 65 b1 39 98 50  |...L...{.#.e.9.P|
-00000020  3d ff 1b 15 03 03 00 1a  00 00 00 00 00 00 00 02  |=...............|
-00000030  aa 34 cc f1 4a d3 de 4c  42 bc 2c 0f 3e 71 af 6b  |.4..J..LB.,.>q.k|
-00000040  3c fc                                             |<.|
+00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 fa 9e 8b  |................|
+00000010  92 8c f5 32 e6 d4 11 46  b4 73 62 56 f6 83 15 6f  |...2...F.sbV...o|
+00000020  ce de 2d 15 03 03 00 1a  00 00 00 00 00 00 00 02  |..-.............|
+00000030  93 24 68 83 67 b6 f9 27  b5 26 52 78 5d f3 c9 d2  |.$h.g..'.&Rx]...|
+00000040  26 a0                                             |&.|
index 96f6218a35d35a64777360ca6732100afafba30f..4946fe4ec5e2a86f5f3b5f105e90e8e0b39c714c 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 87 87 6f ce 44  |....Y...U....o.D|
-00000010  94 5f 2f cc 94 03 50 68  a7 4f 37 70 8a d4 cf e3  |._/...Ph.O7p....|
-00000020  23 7f 11 f5 93 c7 3f 96  87 49 45 20 9c d4 96 b2  |#.....?..IE ....|
-00000030  dc 8c 16 c5 fb cc 2f 8e  0e a5 ef a3 ea cf 57 d0  |....../.......W.|
-00000040  09 70 bd 16 c4 d9 e4 1b  a0 40 f7 f3 c0 23 00 00  |.p.......@...#..|
+00000000  16 03 03 00 59 02 00 00  55 03 03 d1 af 88 61 b7  |....Y...U.....a.|
+00000010  b3 01 16 1a 44 26 1c a1  4f 2d 8a f6 9c f2 7e 1a  |....D&..O-....~.|
+00000020  1f ce cb dd 5b f0 c6 2f  16 5e 4a 20 b3 c7 ae 3f  |....[../.^J ...?|
+00000030  de d0 d8 9e 48 3e 87 23  f0 9d 43 10 50 3c 66 8b  |....H>.#..C.P<f.|
+00000040  7f d2 9b 4f f5 e4 b3 53  db d6 65 d0 c0 23 00 00  |...O...S..e..#..|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
 00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
 00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
 00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
 00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
-00000270  2a 16 03 03 00 b6 0c 00  00 b2 03 00 1d 20 3f a6  |*............ ?.|
-00000280  d1 0d ae 8d c0 06 14 ca  da 2c 69 1c f1 84 c4 dd  |.........,i.....|
-00000290  14 f4 0e a6 ce b5 d6 37  9d 9f a5 ba 7b 74 04 03  |.......7....{t..|
-000002a0  00 8a 30 81 87 02 42 00  b5 2b 9a 32 9d af b9 cc  |..0...B..+.2....|
-000002b0  0d b6 f1 9b 87 35 af d7  dc 04 0f 1b 04 d7 fa 62  |.....5.........b|
-000002c0  20 bd 2c 31 41 17 e7 c0  ea 22 78 e4 de 37 14 a8  | .,1A...."x..7..|
-000002d0  f9 f3 f1 3e 0c 55 59 b3  e3 0e 31 26 ce d0 c1 19  |...>.UY...1&....|
-000002e0  b8 17 07 2a 23 98 7b 17  0f 02 41 41 d5 51 80 4d  |...*#.{...AA.Q.M|
-000002f0  8a 14 56 b1 39 7b 8b 37  24 ef e0 ec 43 44 5a cc  |..V.9{.7$...CDZ.|
-00000300  9b ab dc 63 e7 cc 7b 29  c0 66 ae 9c 23 c5 1b 98  |...c..{).f..#...|
-00000310  6e 35 64 97 12 43 16 73  a6 6b c8 09 2c 26 7c f5  |n5d..C.s.k..,&|.|
-00000320  b1 1f 9f 55 04 9e 53 33  c1 89 7a d0 16 03 03 00  |...U..S3..z.....|
+00000270  2a 16 03 03 00 b6 0c 00  00 b2 03 00 1d 20 dc 43  |*............ .C|
+00000280  15 b7 95 81 41 bf e2 bd  56 82 23 46 05 29 05 95  |....A...V.#F.)..|
+00000290  ae 67 08 38 9f 10 70 25  21 92 b4 a0 82 4e 04 03  |.g.8..p%!....N..|
+000002a0  00 8a 30 81 87 02 41 5d  ca d6 a2 fd e3 e2 be 2f  |..0...A]......./|
+000002b0  69 b5 7d 5c a3 2b 36 4c  8b 81 05 89 12 e1 30 26  |i.}\.+6L......0&|
+000002c0  fa ae 82 b9 4f 8e ba ac  ee 7b 62 d5 60 f8 df a4  |....O....{b.`...|
+000002d0  c1 a1 15 73 f8 fb 0b 47  64 b3 34 4a 44 02 a6 32  |...s...Gd.4JD..2|
+000002e0  bc 0d 7b a5 c1 84 cf 77  02 42 01 f3 e5 7f d1 47  |..{....w.B.....G|
+000002f0  bc be 0a ec cd d6 4f 2c  26 5a 95 d3 0f 9b c3 c6  |......O,&Z......|
+00000300  05 b5 5e d7 f6 ca 64 17  94 aa a5 e6 b1 88 57 21  |..^...d.......W!|
+00000310  f8 da 02 de 32 8c ea 5b  7c 36 c9 93 e1 96 38 93  |....2..[|6....8.|
+00000320  9b f9 e5 44 47 a6 74 fa  0e 5f 8f 22 16 03 03 00  |...DG.t.._."....|
 00000330  04 0e 00 00 00                                    |.....|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 25 10 00 00  21 20 2f e5 7d a3 47 cd  |....%...! /.}.G.|
 00000010  62 43 15 28 da ac 5f bb  29 07 30 ff f6 84 af c4  |bC.(.._.).0.....|
 00000020  cf c2 ed 90 99 5f 58 cb  3b 74 14 03 03 00 01 01  |....._X.;t......|
 00000030  16 03 03 00 50 00 00 00  00 00 00 00 00 00 00 00  |....P...........|
-00000040  00 00 00 00 00 d3 72 3f  9d 37 ba 97 55 83 b4 f0  |......r?.7..U...|
-00000050  ad 0b f0 48 98 16 05 f1  b5 6e da a4 79 e4 d9 8e  |...H.....n..y...|
-00000060  62 af b9 a1 d1 a4 5c 04  d2 b1 86 32 af 64 ac 89  |b.....\....2.d..|
-00000070  d3 47 5f 61 ae f4 21 5b  8d 4b ff 74 c1 b8 9c de  |.G_a..![.K.t....|
-00000080  fd 74 a0 99 c1                                    |.t...|
+00000040  00 00 00 00 00 85 db ae  c1 37 85 25 3d ee 5f f5  |.........7.%=._.|
+00000050  12 95 df ee 29 4a f7 3a  80 ca bd c2 b3 d8 f3 8c  |....)J.:........|
+00000060  56 62 d2 68 13 1d 73 51  09 93 a3 b9 43 4a 2c 0f  |Vb.h..sQ....CJ,.|
+00000070  bf 3c 96 76 08 a9 17 68  e2 9a 3f 39 e7 04 76 f8  |.<.v...h..?9..v.|
+00000080  8f fe e8 f5 ce                                    |.....|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 50 09 3b 3e 7e 2e  |..........P.;>~.|
-00000010  d8 46 04 ac b0 3d c9 7e  ec 28 8c bd 6c 0f a8 b5  |.F...=.~.(..l...|
-00000020  af 8c 86 ed 64 81 6c d4  98 9e 56 2a 48 0d 03 40  |....d.l...V*H..@|
-00000030  64 3e 25 58 6f 03 6a 4e  be a2 11 6f 6f e7 2f c2  |d>%Xo.jN...oo./.|
-00000040  8f 78 c4 11 a1 07 21 91  9d 34 01 08 39 0d 07 d2  |.x....!..4..9...|
-00000050  d4 a2 cc 2f 25 ea ee 8d  8b 91 f9                 |.../%......|
+00000000  14 03 03 00 01 01 16 03  03 00 50 fa 85 cc bc dd  |..........P.....|
+00000010  0e 16 86 b1 5c 51 8a b9  cc 78 cd cd 64 5d 23 ca  |....\Q...x..d]#.|
+00000020  59 84 b3 42 dd ae a7 98  43 05 21 4f 35 43 75 5c  |Y..B....C.!O5Cu\|
+00000030  13 c8 e0 b6 66 0f 55 32  69 7a 8b 8f cd c2 37 38  |....f.U2iz....78|
+00000040  f6 fa 0b 66 cf 46 91 3e  9f f5 43 44 f5 c7 2b e1  |...f.F.>..CD..+.|
+00000050  39 3a f7 3c f2 03 c4 85  dc 58 66                 |9:.<.....Xf|
 >>> Flow 5 (client to server)
 00000000  17 03 03 00 40 00 00 00  00 00 00 00 00 00 00 00  |....@...........|
-00000010  00 00 00 00 00 1d 76 4c  fb 46 f8 02 9a bc 07 8d  |......vL.F......|
-00000020  b0 52 40 44 58 da ad be  3c a6 d7 44 0f 59 98 f3  |.R@DX...<..D.Y..|
-00000030  ae 5c d2 04 bb 07 ee f6  99 9d 2c 14 44 3b 90 bc  |.\........,.D;..|
-00000040  2b e9 bc 37 59 15 03 03  00 40 00 00 00 00 00 00  |+..7Y....@......|
-00000050  00 00 00 00 00 00 00 00  00 00 c4 ef 97 87 35 a2  |..............5.|
-00000060  2f cc c2 6f 3d d5 f5 6f  fd 74 56 50 37 f8 10 e8  |/..o=..o.tVP7...|
-00000070  36 f5 fb 6f 7b 5d 20 07  0d 2f 72 46 a7 3a e0 de  |6..o{] ../rF.:..|
-00000080  39 b3 76 0e 4f c0 e7 85  4b bb                    |9.v.O...K.|
+00000010  00 00 00 00 00 44 e6 99  40 ae 12 bc d9 92 c5 ae  |.....D..@.......|
+00000020  fb 4d 5f 64 7a 77 0f 80  8e a4 be d0 ba ba 41 b1  |.M_dzw........A.|
+00000030  0d 40 e9 0e 50 32 dc 35  2d 5e 5c 8a ef 20 75 80  |.@..P2.5-^\.. u.|
+00000040  a0 e5 9c 61 49 15 03 03  00 40 00 00 00 00 00 00  |...aI....@......|
+00000050  00 00 00 00 00 00 00 00  00 00 57 91 40 2a a5 f7  |..........W.@*..|
+00000060  9f 29 0f 02 8e 50 ac 4b  2e 55 9a 78 72 f0 d7 c5  |.)...P.K.U.xr...|
+00000070  3b f2 cd 28 4d 8b 49 d8  50 a6 22 96 de df 16 d6  |;..(M.I.P.".....|
+00000080  61 4b 23 5c 5d de a1 0a  5b 16                    |aK#\]...[.|
index 90a1639e9901dab5afb17de7a254b0fbd9c9138c..14af5ae75f417e758f465a68963a414bba14abd9 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 b8 16 bd ae 15  |....Y...U.......|
-00000010  a3 33 52 cc 60 dc 6c fe  7c f3 82 b9 1e 13 ab 87  |.3R.`.l.|.......|
-00000020  22 d8 c3 38 dc 8a 76 bb  a0 a3 fd 20 8a d1 92 d1  |"..8..v.... ....|
-00000030  d6 f3 76 e0 e2 76 32 95  32 a0 eb 5b dc e4 42 81  |..v..v2.2..[..B.|
-00000040  14 bb 58 ab b8 e8 9d ee  fa 32 58 05 c0 2c 00 00  |..X......2X..,..|
+00000000  16 03 03 00 59 02 00 00  55 03 03 bb 8a 66 ee 44  |....Y...U....f.D|
+00000010  42 dc 59 c7 a7 7b a8 57  8e 63 21 f0 4e 31 f4 5c  |B.Y..{.W.c!.N1.\|
+00000020  1d d3 42 e5 de eb 8c 78  3a 01 01 20 9b 89 05 d6  |..B....x:.. ....|
+00000030  d2 07 38 8b 4c 5f 6d 62  9f 43 a0 cd d3 40 0f 77  |..8.L_mb.C...@.w|
+00000040  17 ff 43 4a 5c b3 8c 83  b7 4b c7 e7 c0 2c 00 00  |..CJ\....K...,..|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
 00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
 00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
 00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
 00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
-00000270  2a 16 03 03 00 b6 0c 00  00 b2 03 00 1d 20 5c 9b  |*............ \.|
-00000280  9b 29 5c 83 36 b8 20 47  2b 04 0d 1b ab f5 f7 81  |.)\.6. G+.......|
-00000290  aa 89 b4 93 37 aa 28 4e  44 e1 22 26 b6 46 04 03  |....7.(ND."&.F..|
-000002a0  00 8a 30 81 87 02 42 01  2c 87 df 1f 07 86 36 c8  |..0...B.,.....6.|
-000002b0  f6 aa 41 c1 8e 99 6e 12  08 5f e2 62 4b 3a 9b ad  |..A...n.._.bK:..|
-000002c0  e8 26 1c 95 f9 62 c6 f6  c7 e4 f7 db 3b 23 e5 4f  |.&...b......;#.O|
-000002d0  03 a1 c6 89 74 cb bd 2a  4e 47 3f 0f bf 28 bb 6d  |....t..*NG?..(.m|
-000002e0  c0 c6 53 4c 02 0b 9a 30  2d 02 41 0c 6f 26 a5 4c  |..SL...0-.A.o&.L|
-000002f0  b6 6c 8c ab 82 32 19 a0  f0 1b 41 2d 9d 1d 12 1b  |.l...2....A-....|
-00000300  91 62 6a 3d 17 92 79 f6  59 45 21 2f 6b d0 cb 7b  |.bj=..y.YE!/k..{|
-00000310  22 b3 79 80 90 90 81 97  06 c8 59 fd 8b 40 f9 ec  |".y.......Y..@..|
-00000320  80 58 db fc 5e a2 67 9a  96 01 53 d4 16 03 03 00  |.X..^.g...S.....|
-00000330  04 0e 00 00 00                                    |.....|
+00000270  2a 16 03 03 00 b7 0c 00  00 b3 03 00 1d 20 fd 71  |*............ .q|
+00000280  c1 3a 6a a3 69 6a 34 f3  02 c5 1d e5 db 63 f4 eb  |.:j.ij4......c..|
+00000290  97 4c 70 bc b3 4e 9d 2c  2f b2 b9 9d ac 3f 04 03  |.Lp..N.,/....?..|
+000002a0  00 8b 30 81 88 02 42 01  bd 9d ad 24 37 b9 60 55  |..0...B....$7.`U|
+000002b0  e4 cc bc 49 c3 88 3b ed  ac e4 42 8e fa 81 01 d9  |...I..;...B.....|
+000002c0  39 4c f0 1c 7d 39 a2 81  8a e1 17 0e 8d 37 76 96  |9L..}9.......7v.|
+000002d0  37 13 3a 1e 2e fd 0d 0a  3c 90 9d 43 3d 06 c0 b1  |7.:.....<..C=...|
+000002e0  4e 07 3e c3 9f f2 43 40  0b 02 42 01 d6 d0 20 ad  |N.>...C@..B... .|
+000002f0  48 09 c0 9b 5d c8 84 46  3b 98 37 9b 5a 91 4a 07  |H...]..F;.7.Z.J.|
+00000300  79 68 71 92 76 dc 70 0f  5c 44 7e 81 c3 c6 3f 19  |yhq.v.p.\D~...?.|
+00000310  f4 0f 6a 0b aa cc bb 65  e7 34 b5 e9 67 2d 32 98  |..j....e.4..g-2.|
+00000320  1c f6 76 4c 96 73 df 21  d6 e1 ea 34 86 16 03 03  |..vL.s.!...4....|
+00000330  00 04 0e 00 00 00                                 |......|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 25 10 00 00  21 20 2f e5 7d a3 47 cd  |....%...! /.}.G.|
 00000010  62 43 15 28 da ac 5f bb  29 07 30 ff f6 84 af c4  |bC.(.._.).0.....|
 00000020  cf c2 ed 90 99 5f 58 cb  3b 74 14 03 03 00 01 01  |....._X.;t......|
-00000030  16 03 03 00 28 00 00 00  00 00 00 00 00 17 be e6  |....(...........|
-00000040  ba 39 2d 82 38 6e 09 2c  1c ef d5 1f ad 8e e0 47  |.9-.8n.,.......G|
-00000050  2d bc 74 f8 3b ed 86 89  9e e9 a5 01 40           |-.t.;.......@|
+00000030  16 03 03 00 28 00 00 00  00 00 00 00 00 27 fd 98  |....(........'..|
+00000040  47 79 56 f9 e8 0e fd 18  c2 8f 2d 32 51 f7 19 b5  |GyV.......-2Q...|
+00000050  ab 2f 81 ed b6 cf 6f b5  65 81 81 f1 44           |./....o.e...D|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 28 42 3b b0 5e 66  |..........(B;.^f|
-00000010  3e ef a5 3d 49 64 42 34  b1 21 d6 43 d3 f6 f5 84  |>..=IdB4.!.C....|
-00000020  21 96 b4 7b ed 73 b5 23  b6 40 cf 86 ab 71 59 58  |!..{.s.#.@...qYX|
-00000030  3a bf 79                                          |:.y|
+00000000  14 03 03 00 01 01 16 03  03 00 28 a9 b7 63 61 57  |..........(..caW|
+00000010  54 57 f0 b2 60 58 e3 dc  6e e1 40 3e 67 b4 99 8f  |TW..`X..n.@>g...|
+00000020  e9 6b 11 f1 1a 54 bd c1  d3 b9 5b 01 12 27 a4 0b  |.k...T....[..'..|
+00000030  e9 ec 01                                          |...|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 8d 3c f7  |..............<.|
-00000010  9e da 91 15 35 10 5f a4  29 32 3f 6a 8c 1d bc 13  |....5._.)2?j....|
-00000020  8a 35 2b 15 03 03 00 1a  00 00 00 00 00 00 00 02  |.5+.............|
-00000030  1f b3 e3 e3 24 ac 7a a6  ee 81 e7 cc 9e 70 34 2c  |....$.z......p4,|
-00000040  d2 28                                             |.(|
+00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 e0 8a 6e  |...............n|
+00000010  62 5d e3 db 99 10 d2 53  b6 21 2e 79 31 cf 71 1d  |b].....S.!.y1.q.|
+00000020  34 71 2a 15 03 03 00 1a  00 00 00 00 00 00 00 02  |4q*.............|
+00000030  e7 4a 8d b9 2f 1b b1 70  72 da 7f d8 fa 4f 9f d6  |.J../..pr....O..|
+00000040  ca f3                                             |..|
index 1b3c37be2418adcc2f130b5c21f171d82cdc5fd2..3113b3c6e5c296b37efcec6dc546e600147d3b20 100644 (file)
@@ -4,7 +4,7 @@
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 08 cc a9  |................|
-00000050  13 01 13 03 13 02 01 00  00 7b 00 05 00 05 01 00  |.........{......|
+00000050  13 03 13 01 13 02 01 00  00 7b 00 05 00 05 01 00  |.........{......|
 00000060  00 00 00 00 0a 00 0a 00  08 00 1d 00 17 00 18 00  |................|
 00000070  19 00 0b 00 02 01 00 00  0d 00 1a 00 18 08 04 04  |................|
 00000080  03 08 07 08 05 08 06 04  01 05 01 06 01 05 03 06  |................|
 000000c0  ac 5f bb 29 07 30 ff f6  84 af c4 cf c2 ed 90 99  |._.).0..........|
 000000d0  5f 58 cb 3b 74                                    |_X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 ea 73 50 31 e4  |....Y...U...sP1.|
-00000010  7a c7 e2 05 23 a0 22 e3  1a cd 6d b5 0f e7 f2 5e  |z...#."...m....^|
-00000020  d6 cb 6c 70 05 04 a9 63  4a a3 fc 20 a2 c5 68 f2  |..lp...cJ.. ..h.|
-00000030  9b 56 6e 83 66 c1 7f 85  02 b6 6d 37 12 0f 12 5a  |.Vn.f.....m7...Z|
-00000040  41 7e c3 c9 44 85 3c 00  50 6f c7 f9 cc a9 00 00  |A~..D.<.Po......|
+00000000  16 03 03 00 59 02 00 00  55 03 03 e1 cc 3c 49 04  |....Y...U....<I.|
+00000010  bb 5b 18 c7 44 8f 52 62  d9 74 84 94 fa 61 3f 12  |.[..D.Rb.t...a?.|
+00000020  c8 23 50 0b 8a 5c 81 23  c2 9d 3d 20 1f b2 67 b0  |.#P..\.#..= ..g.|
+00000030  e9 2d a9 ed 35 4e ab b9  73 59 32 2f 49 ed 1e 60  |.-..5N..sY2/I..`|
+00000040  4c 31 11 6e 27 79 e0 62  e0 e4 ca 16 cc a9 00 00  |L1.n'y.b........|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
 00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
 00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
 00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
 00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
-00000270  2a 16 03 03 00 b7 0c 00  00 b3 03 00 1d 20 a4 6a  |*............ .j|
-00000280  0d ab f2 7c 1a 31 2a 7d  51 b7 fe 69 cd 59 f5 c1  |...|.1*}Q..i.Y..|
-00000290  10 94 a0 b2 6f 6f c4 48  48 9b 20 1e 46 2a 04 03  |....oo.HH. .F*..|
-000002a0  00 8b 30 81 88 02 42 00  84 2a 96 88 a4 7a 86 7f  |..0...B..*...z..|
-000002b0  cf 86 20 37 17 de 54 0c  c2 89 5e 27 f4 3b a4 ec  |.. 7..T...^'.;..|
-000002c0  ce 25 34 4e c7 a8 7d f5  56 6d 96 2c d0 53 ae 42  |.%4N..}.Vm.,.S.B|
-000002d0  b5 87 a9 20 9c 4f c9 67  7e ca f6 fc 2f 61 72 35  |... .O.g~.../ar5|
-000002e0  78 fe 54 32 1e a1 90 88  c2 02 42 01 a6 7b 98 de  |x.T2......B..{..|
-000002f0  fd 01 4b 4a 8f 1a e8 18  dd 07 bb 0b 38 41 7f 22  |..KJ........8A."|
-00000300  62 3b 7e 37 67 b7 18 46  a7 32 43 1b c9 a9 8a a6  |b;~7g..F.2C.....|
-00000310  d7 8a 2f 7b c5 14 f3 33  96 fe 0a fc 22 d0 a5 02  |../{...3...."...|
-00000320  37 a5 31 5f b9 6b d2 3b  f6 d0 d1 7b a1 16 03 03  |7.1_.k.;...{....|
-00000330  00 04 0e 00 00 00                                 |......|
+00000270  2a 16 03 03 00 b6 0c 00  00 b2 03 00 1d 20 cc a1  |*............ ..|
+00000280  4d a4 b1 22 86 e5 91 9b  e2 1a 28 c6 66 06 1a 89  |M.."......(.f...|
+00000290  a9 62 23 93 09 54 ae 67  a8 ab 18 ac 67 37 04 03  |.b#..T.g....g7..|
+000002a0  00 8a 30 81 87 02 42 01  f0 46 f3 3f 13 a7 1d 84  |..0...B..F.?....|
+000002b0  73 65 9e 91 16 6c 3d 8f  21 ab 17 db 24 34 21 8c  |se...l=.!...$4!.|
+000002c0  a9 e1 9b a6 17 c8 0d 7a  b4 8e f0 46 cd c5 b9 b2  |.......z...F....|
+000002d0  5e 64 7f 9f 9d 03 14 7a  23 5d 55 70 ae d1 ff 08  |^d.....z#]Up....|
+000002e0  e8 70 f5 5d 55 90 74 04  0d 02 41 09 ca 7d 60 ea  |.p.]U.t...A..}`.|
+000002f0  13 17 42 e8 53 e7 c5 31  15 4a 58 14 d6 54 f5 40  |..B.S..1.JX..T.@|
+00000300  a1 aa fe 4b 13 f5 29 04  05 cc 12 26 e2 b7 e5 a6  |...K..)....&....|
+00000310  90 7c 5e 66 2f ed 41 7c  97 a1 72 87 5e 46 5a 5b  |.|^f/.A|..r.^FZ[|
+00000320  1b d1 7b 3c 34 ba 3f 47  7d a9 84 33 16 03 03 00  |..{<4.?G}..3....|
+00000330  04 0e 00 00 00                                    |.....|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 25 10 00 00  21 20 2f e5 7d a3 47 cd  |....%...! /.}.G.|
 00000010  62 43 15 28 da ac 5f bb  29 07 30 ff f6 84 af c4  |bC.(.._.).0.....|
 00000020  cf c2 ed 90 99 5f 58 cb  3b 74 14 03 03 00 01 01  |....._X.;t......|
-00000030  16 03 03 00 20 f5 a0 28  0a 7e d4 8b a2 b6 e1 af  |.... ..(.~......|
-00000040  83 e2 50 e8 fc 7e f0 59  21 ed 3d 0d a8 ef a9 b1  |..P..~.Y!.=.....|
-00000050  5a 13 2a 1b 2c                                    |Z.*.,|
+00000030  16 03 03 00 20 7f ab 78  f0 a6 b6 57 bd c3 b9 32  |.... ..x...W...2|
+00000040  96 3f 7c 9d a0 4d dc 74  c9 e8 1a 88 c4 b2 10 27  |.?|..M.t.......'|
+00000050  e3 9c 1e 9b e1                                    |.....|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 20 44 15 68 4d e0  |.......... D.hM.|
-00000010  3b 34 c5 77 b2 25 f2 e9  35 75 08 f5 a9 53 c9 65  |;4.w.%..5u...S.e|
-00000020  19 36 49 fe 43 e4 f5 48  ac 7c d7                 |.6I.C..H.|.|
+00000000  14 03 03 00 01 01 16 03  03 00 20 0c b7 0c 47 8e  |.......... ...G.|
+00000010  40 6b 9f 9c d2 cd 24 25  db 12 e8 0c 50 be f3 98  |@k....$%....P...|
+00000020  4a 6f f9 42 58 07 b9 64  d0 00 91                 |Jo.BX..d...|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 16 f7 fd 2a  83 90 01 f3 d2 82 dc bd  |.......*........|
-00000010  6c 33 31 a3 92 0f a4 f5  9c fa f4 15 03 03 00 12  |l31.............|
-00000020  9e 60 18 02 f1 0d 2f f5  5f 68 69 ae 62 93 04 6a  |.`..../._hi.b..j|
-00000030  41 f0                                             |A.|
+00000000  17 03 03 00 16 1d 32 1c  ef 0b 1f a4 ba 39 a3 63  |......2......9.c|
+00000010  04 29 e5 67 1e bb 5a 6e  c7 3c c1 15 03 03 00 12  |.).g..Zn.<......|
+00000020  0e 0b 0f 49 30 fe d4 c3  35 85 e3 db 6e 65 e3 2d  |...I0...5...ne.-|
+00000030  d1 1d                                             |..|
index eff5b979f97ce2ea29cdde2b19b9c0cdd10160e6..ea6c7872ec7d81485a793e05f87cdcbf79ef513f 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 f1 07 97 47 f7  |....Y...U.....G.|
-00000010  b8 42 f5 ce 2b b5 ec 5a  d3 74 f1 fa 1f ea ec 6d  |.B..+..Z.t.....m|
-00000020  49 4e cf 2e 47 8b 2e 80  9b 8a ed 20 89 ca 35 4a  |IN..G...... ..5J|
-00000030  f4 35 5e b7 ed b2 96 ad  e1 66 1d 43 9d 07 ba ed  |.5^......f.C....|
-00000040  ff 9d 47 65 c8 7d 91 32  4b 88 4d 83 c0 13 00 00  |..Ge.}.2K.M.....|
+00000000  16 03 03 00 59 02 00 00  55 03 03 1e 2f 6f fa 02  |....Y...U.../o..|
+00000010  44 3e 0d d0 3e b5 e6 0c  a2 d6 aa 04 5b ba 93 39  |D>..>.......[..9|
+00000020  29 dd e7 7e b8 11 f9 85  97 a5 e4 20 9c 64 e9 47  |)..~....... .d.G|
+00000030  cb 7c 0c 77 9d 83 5a c4  e8 05 62 40 95 8e 8e aa  |.|.w..Z...b@....|
+00000040  39 bb 24 8f b7 29 75 77  18 66 60 29 c0 13 00 00  |9.$..)uw.f`)....|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 59 0b 00 02 55 00  02 52 00 02 4f 30 82 02  |..Y...U..R..O0..|
 00000070  4b 30 82 01 b4 a0 03 02  01 02 02 09 00 e8 f0 9d  |K0..............|
 00000290  77 8d 0c 1c f1 0f a1 d8  40 83 61 c9 4c 72 2b 9d  |w.......@.a.Lr+.|
 000002a0  ae db 46 06 06 4d f4 c1  b3 3e c0 d1 bd 42 d4 db  |..F..M...>...B..|
 000002b0  fe 3d 13 60 84 5c 21 d3  3b e9 fa e7 16 03 03 00  |.=.`.\!.;.......|
-000002c0  ac 0c 00 00 a8 03 00 1d  20 78 22 92 20 a9 be 78  |........ x". ..x|
-000002d0  12 0f e6 83 13 3d 13 91  16 11 ca 26 9f b7 37 d5  |.....=.....&..7.|
-000002e0  f0 97 f9 f2 01 fd 08 4f  42 08 04 00 80 2c f1 4e  |.......OB....,.N|
-000002f0  79 63 f2 d9 54 1c 0c 56  fd 56 4d e0 37 ee 5d bb  |yc..T..V.VM.7.].|
-00000300  22 90 fd ee d9 0f e6 d9  85 41 b9 8d d6 76 5f 05  |"........A...v_.|
-00000310  1b 8c d7 4e c5 e8 4e 69  b9 5d de 73 c0 ed 4f 3e  |...N..Ni.].s..O>|
-00000320  09 9d b0 10 d6 61 87 d8  f9 c2 5b 48 f9 ef dd 65  |.....a....[H...e|
-00000330  e6 f8 b0 d2 71 f6 e9 ae  b1 c0 ea 90 dc 33 c6 72  |....q........3.r|
-00000340  3e 9f 31 d4 ae 78 23 54  7a 4f 02 69 72 c1 06 2f  |>.1..x#TzO.ir../|
-00000350  3f 3c 7b f2 d8 17 40 a6  95 6d 46 62 6b 54 f1 cf  |?<{...@..mFbkT..|
-00000360  60 08 63 89 f7 a5 2a 52  3b 0e 0c d6 34 16 03 03  |`.c...*R;...4...|
+000002c0  ac 0c 00 00 a8 03 00 1d  20 92 ed 81 60 d9 51 c2  |........ ...`.Q.|
+000002d0  00 3d 99 84 82 c5 83 67  60 b3 11 59 0c c5 5d ff  |.=.....g`..Y..].|
+000002e0  d6 28 79 68 2d 73 7f 84  40 08 04 00 80 b6 a0 4b  |.(yh-s..@......K|
+000002f0  3d fb e1 e6 76 cc ae e3  59 d0 1c 50 5c 09 5d 80  |=...v...Y..P\.].|
+00000300  c2 58 0d 36 d7 1a 78 e3  c2 66 73 3a 14 06 37 6f  |.X.6..x..fs:..7o|
+00000310  3a 95 2e 2a eb cc e5 e3  f7 30 eb 0d 33 04 51 6e  |:..*.....0..3.Qn|
+00000320  06 86 8f 53 6d fd 97 75  b3 13 2e 4e ee 8f 03 68  |...Sm..u...N...h|
+00000330  23 32 83 96 af 01 ed b0  21 a7 13 06 47 f4 08 b9  |#2......!...G...|
+00000340  8a 47 cc 12 99 20 c6 31  77 28 2c 2e d6 a0 20 8c  |.G... .1w(,... .|
+00000350  e6 67 c7 70 23 ed 98 9c  c9 47 1c e0 37 95 42 aa  |.g.p#....G..7.B.|
+00000360  c2 19 1b 55 09 5c 58 fb  ef 67 a9 b5 65 16 03 03  |...U.\X..g..e...|
 00000370  00 04 0e 00 00 00                                 |......|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 25 10 00 00  21 20 2f e5 7d a3 47 cd  |....%...! /.}.G.|
 00000010  62 43 15 28 da ac 5f bb  29 07 30 ff f6 84 af c4  |bC.(.._.).0.....|
 00000020  cf c2 ed 90 99 5f 58 cb  3b 74 14 03 03 00 01 01  |....._X.;t......|
 00000030  16 03 03 00 40 00 00 00  00 00 00 00 00 00 00 00  |....@...........|
-00000040  00 00 00 00 00 96 55 d3  bd a1 b6 de 93 68 19 ed  |......U......h..|
-00000050  4a 3a cc 42 7c c4 41 1e  b5 37 65 d5 84 10 60 3d  |J:.B|.A..7e...`=|
-00000060  e9 57 29 28 79 54 da 6c  1b 36 6b b1 75 f4 bb 32  |.W)(yT.l.6k.u..2|
-00000070  47 8d de c8 7d                                    |G...}|
+00000040  00 00 00 00 00 dd 81 23  e0 a3 01 33 bb 87 0d 93  |.......#...3....|
+00000050  b2 61 16 01 e3 87 e0 05  cc b0 ec 15 56 df ff 9c  |.a..........V...|
+00000060  e6 9c 6a 57 79 8a 0b 86  f9 fb 60 3f ca 0d ef f2  |..jWy.....`?....|
+00000070  81 c0 5e 22 bf                                    |..^".|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 40 db ed ec 54 4a  |..........@...TJ|
-00000010  20 d8 a7 ee 12 04 e2 e4  95 b4 a4 a7 e1 80 c8 40  | ..............@|
-00000020  81 00 6d 3e 58 26 7c d4  26 84 86 ee b4 fc c5 50  |..m>X&|.&......P|
-00000030  46 31 e7 4c 1e fd ed 10  7e 72 45 18 43 db 4c 0d  |F1.L....~rE.C.L.|
-00000040  b5 49 6c 31 04 f0 85 a7  f8 02 e1                 |.Il1.......|
+00000000  14 03 03 00 01 01 16 03  03 00 40 d4 d3 ba 7f 4c  |..........@....L|
+00000010  1a ee d9 ca 66 a0 5b d7  08 78 5d 5c fd 17 32 71  |....f.[..x]\..2q|
+00000020  7f 8c 2e eb 80 bc 82 0f  0c ed 71 ac 34 59 71 d1  |..........q.4Yq.|
+00000030  aa d3 fd 0c 50 7d 4b 1b  01 5d 4c 03 9f 6c 16 8f  |....P}K..]L..l..|
+00000040  5d f7 8d c0 4b 3f 01 96  23 40 22                 |]...K?..#@"|
 >>> Flow 5 (client to server)
 00000000  17 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
-00000010  00 00 00 00 00 90 f7 06  a7 05 8d de 51 21 88 95  |............Q!..|
-00000020  47 61 fb 8d a9 c9 6d 59  ca 92 8d 07 8b 9d 82 4e  |Ga....mY.......N|
-00000030  fd e9 ae 3d b0 15 03 03  00 30 00 00 00 00 00 00  |...=.....0......|
-00000040  00 00 00 00 00 00 00 00  00 00 12 77 0c 5f 12 4b  |...........w._.K|
-00000050  96 ab 64 58 6e f5 82 09  6c 18 ae 1f a2 fb 0a 3b  |..dXn...l......;|
-00000060  71 17 25 8b c8 72 d0 13  fb e8                    |q.%..r....|
+00000010  00 00 00 00 00 36 49 0e  f6 26 13 f7 69 15 54 27  |.....6I..&..i.T'|
+00000020  5a e6 f2 fb 7d ad e0 30  d3 cd ed 08 24 74 5f 77  |Z...}..0....$t_w|
+00000030  f7 8b 3f bf 94 15 03 03  00 30 00 00 00 00 00 00  |..?......0......|
+00000040  00 00 00 00 00 00 00 00  00 00 28 09 ed 2f d8 6f  |..........(../.o|
+00000050  95 fc db 9e ec d8 81 7e  a4 d4 8e c5 ec d3 24 bc  |.......~......$.|
+00000060  ab 52 e6 01 75 98 b9 e5  9f d9                    |.R..u.....|
index 4f8f49eb6a001bad29666178063fc3f6074bcf24..88d0d01483bd7a2a2930beee108c530169879491 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 9e d4 c1 3e c6  |....Y...U.....>.|
-00000010  3d 44 eb a7 b8 c5 c8 e0  ab 16 06 83 67 5e b2 d6  |=D..........g^..|
-00000020  67 50 4b f3 24 17 97 19  76 7e 71 20 5a 2b dc 15  |gPK.$...v~q Z+..|
-00000030  87 37 be bb c7 9c 38 cd  3e 55 4e 33 32 a0 01 1b  |.7....8.>UN32...|
-00000040  79 13 87 6a 19 09 42 4c  fb 59 97 a8 c0 27 00 00  |y..j..BL.Y...'..|
+00000000  16 03 03 00 59 02 00 00  55 03 03 e6 04 5e a9 bb  |....Y...U....^..|
+00000010  23 56 bd cc e7 72 9f 10  b1 fc 23 48 22 19 cb 27  |#V...r....#H"..'|
+00000020  3e c4 22 ec b9 7a 9c 81  60 c5 55 20 b9 7f 8a 0e  |>."..z..`.U ....|
+00000030  6b d6 cf cb 35 85 52 f3  9f 28 00 87 22 88 6d 7c  |k...5.R..(..".m||
+00000040  35 0e f6 af 7c 28 b4 71  cc 46 c1 b5 c0 27 00 00  |5...|(.q.F...'..|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 59 0b 00 02 55 00  02 52 00 02 4f 30 82 02  |..Y...U..R..O0..|
 00000070  4b 30 82 01 b4 a0 03 02  01 02 02 09 00 e8 f0 9d  |K0..............|
 00000290  77 8d 0c 1c f1 0f a1 d8  40 83 61 c9 4c 72 2b 9d  |w.......@.a.Lr+.|
 000002a0  ae db 46 06 06 4d f4 c1  b3 3e c0 d1 bd 42 d4 db  |..F..M...>...B..|
 000002b0  fe 3d 13 60 84 5c 21 d3  3b e9 fa e7 16 03 03 00  |.=.`.\!.;.......|
-000002c0  ac 0c 00 00 a8 03 00 1d  20 57 62 97 e9 c8 c6 17  |........ Wb.....|
-000002d0  73 d2 9e 31 a6 f8 be 03  65 86 af 6b e2 64 bf 7c  |s..1....e..k.d.||
-000002e0  4a f1 b9 fb 84 21 10 76  66 08 04 00 80 2d 08 24  |J....!.vf....-.$|
-000002f0  06 2a a3 c5 28 c4 22 5b  fe 79 4f 91 56 9e 40 6f  |.*..(."[.yO.V.@o|
-00000300  e6 0c e8 70 e0 35 9e 55  91 51 86 ec ad ff 6b 3f  |...p.5.U.Q....k?|
-00000310  a7 19 fa 6f 74 47 8a 86  04 b5 8a f0 0a d5 e5 5f  |...otG........._|
-00000320  ea 30 cc 79 77 3d ac 99  da 41 7f 25 3b da cd da  |.0.yw=...A.%;...|
-00000330  aa 4e 2a 54 b5 d3 13 4f  e4 e9 cb 76 86 fb 0b b5  |.N*T...O...v....|
-00000340  0d a3 be ab d2 e6 6e f6  77 7c 60 a7 50 56 43 60  |......n.w|`.PVC`|
-00000350  95 ba 95 c4 b5 1a 8d 6a  f7 a5 9f 03 27 93 9f 23  |.......j....'..#|
-00000360  44 27 88 f0 d5 51 0f ba  43 84 5c 02 14 16 03 03  |D'...Q..C.\.....|
+000002c0  ac 0c 00 00 a8 03 00 1d  20 55 af 53 a0 54 77 df  |........ U.S.Tw.|
+000002d0  ca 8f 49 1a 4d d0 9b 24  a6 a9 2b b2 2a 33 46 b8  |..I.M..$..+.*3F.|
+000002e0  01 d6 4e fd fb c1 e4 e6  64 08 04 00 80 5c da 2f  |..N.....d....\./|
+000002f0  01 2b 10 b9 e9 35 f2 b1  2a 28 4f 78 58 7b 3d 9a  |.+...5..*(OxX{=.|
+00000300  13 e4 7c 77 41 95 fa 7a  90 1f eb f5 20 55 7c 76  |..|wA..z.... U|v|
+00000310  dd c5 66 08 88 eb ba 17  f0 de f3 0c a5 a6 3c 21  |..f...........<!|
+00000320  52 89 25 b1 4d 86 e3 0b  8a 14 dc 8b a6 76 41 25  |R.%.M........vA%|
+00000330  9e d3 20 b6 61 8a 26 8b  0d b7 cb 98 ac 45 e0 3b  |.. .a.&......E.;|
+00000340  6f d6 b2 52 8b a2 31 63  c8 44 1d 2a 3a c1 35 87  |o..R..1c.D.*:.5.|
+00000350  7a 7b 2a fa dd ab d3 48  9b e2 fa e1 93 7c 09 f7  |z{*....H.....|..|
+00000360  e1 72 83 f8 23 07 30 3a  4a 4f 56 97 1b 16 03 03  |.r..#.0:JOV.....|
 00000370  00 04 0e 00 00 00                                 |......|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 25 10 00 00  21 20 2f e5 7d a3 47 cd  |....%...! /.}.G.|
 00000010  62 43 15 28 da ac 5f bb  29 07 30 ff f6 84 af c4  |bC.(.._.).0.....|
 00000020  cf c2 ed 90 99 5f 58 cb  3b 74 14 03 03 00 01 01  |....._X.;t......|
 00000030  16 03 03 00 50 00 00 00  00 00 00 00 00 00 00 00  |....P...........|
-00000040  00 00 00 00 00 02 19 fd  3e 06 0d 12 0d 03 42 da  |........>.....B.|
-00000050  76 6f e2 e3 96 eb 42 d9  96 b7 0b ae d6 a0 06 fa  |vo....B.........|
-00000060  57 4e ff 62 85 dd 3f ab  63 f9 73 87 8d 71 6a c6  |WN.b..?.c.s..qj.|
-00000070  f4 ef ce f5 55 5b d2 1f  b5 33 fd 12 32 bd 5e 1e  |....U[...3..2.^.|
-00000080  d5 32 91 9a ae                                    |.2...|
+00000040  00 00 00 00 00 91 c1 82  23 f0 03 79 83 38 ef d0  |........#..y.8..|
+00000050  73 71 9b 7d 55 5e 53 3b  d3 cf 86 48 60 2f 42 97  |sq.}U^S;...H`/B.|
+00000060  63 e8 4b 20 4c 92 3e 2f  aa b3 32 46 8a 96 69 42  |c.K L.>/..2F..iB|
+00000070  96 9a 4b bd 04 f2 3d b6  5f f9 37 4f a4 3d f1 cb  |..K...=._.7O.=..|
+00000080  d5 57 fc 5e 8e                                    |.W.^.|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 50 77 80 95 42 a3  |..........Pw..B.|
-00000010  2b 1c 16 0f 3b f4 78 2a  bd ab 6e d1 33 1e 0e a5  |+...;.x*..n.3...|
-00000020  c7 f4 e9 92 82 00 da 44  0f b6 4e f9 1f ef 67 3b  |.......D..N...g;|
-00000030  de 5c dc 93 07 68 99 1a  70 7f 92 a7 d7 da f3 60  |.\...h..p......`|
-00000040  cf d5 f1 f0 5e 75 68 a1  0b 32 eb d2 96 de e6 34  |....^uh..2.....4|
-00000050  c3 e3 26 43 1f a2 8d e7  1b fc 76                 |..&C......v|
+00000000  14 03 03 00 01 01 16 03  03 00 50 e1 91 69 dc 7b  |..........P..i.{|
+00000010  5f a4 c7 7a 8f ba bb 8d  98 c3 0e 3f 10 f1 3e 3f  |_..z.......?..>?|
+00000020  37 6f 11 81 3f c5 7c 22  6f 22 a3 94 ae 3a 77 17  |7o..?.|"o"...:w.|
+00000030  a2 7b cc 8e 5e 6e 9b 4b  98 fd 16 f8 46 9e 78 19  |.{..^n.K....F.x.|
+00000040  43 e6 da e3 05 9a 0a 49  b0 09 c7 e5 4b 41 dc b4  |C......I....KA..|
+00000050  c0 81 9b 46 7e dd c3 64  2e f8 6e                 |...F~..d..n|
 >>> Flow 5 (client to server)
 00000000  17 03 03 00 40 00 00 00  00 00 00 00 00 00 00 00  |....@...........|
-00000010  00 00 00 00 00 f8 35 11  b8 23 cf d9 ec a7 d3 b9  |......5..#......|
-00000020  60 1e 34 01 20 49 73 ec  72 78 58 24 3b fc a8 42  |`.4. Is.rxX$;..B|
-00000030  b2 a9 69 69 40 65 5a c2  8b 9f 0b 0e 70 ab ac 22  |..ii@eZ.....p.."|
-00000040  1a ac d6 04 06 15 03 03  00 40 00 00 00 00 00 00  |.........@......|
-00000050  00 00 00 00 00 00 00 00  00 00 fe ed 19 a0 84 06  |................|
-00000060  8b f0 e8 4e 30 7a 3c 89  a0 a8 59 74 a5 92 73 f3  |...N0z<...Yt..s.|
-00000070  df 1b f0 c6 5a 95 d5 1c  b6 57 4a 1b 8f 24 59 87  |....Z....WJ..$Y.|
-00000080  b4 2b 7f 6f 89 03 e8 6d  e5 d9                    |.+.o...m..|
+00000010  00 00 00 00 00 65 4c 71  31 d4 47 4d 0b 81 1f 75  |.....eLq1.GM...u|
+00000020  b6 71 64 4a e6 a8 80 a1  f1 e2 0a 14 77 af a4 c6  |.qdJ........w...|
+00000030  1d 6a 7d 79 6a 15 a1 0e  86 6c 8e e1 32 64 0b 5d  |.j}yj....l..2d.]|
+00000040  af e0 f5 05 91 15 03 03  00 40 00 00 00 00 00 00  |.........@......|
+00000050  00 00 00 00 00 00 00 00  00 00 ca 46 1b 95 2a 41  |...........F..*A|
+00000060  ce dc 30 d6 e0 cf 2f 2b  1f 61 81 33 a4 58 e7 af  |..0.../+.a.3.X..|
+00000070  90 9c 15 42 9b ab 26 64  d1 39 46 45 6b 74 b9 c4  |...B..&d.9FEkt..|
+00000080  21 d9 ef 2d 69 51 dc e7  8a 6b                    |!..-iQ...k|
index 38fb4a0be7cb5427d47f011c9b5c50222047f0f6..2c2cb455d1551796f0dc54ba1028d3bae6e14d2e 100644 (file)
@@ -4,7 +4,7 @@
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 08 cc a8  |................|
-00000050  13 01 13 03 13 02 01 00  00 7b 00 05 00 05 01 00  |.........{......|
+00000050  13 03 13 01 13 02 01 00  00 7b 00 05 00 05 01 00  |.........{......|
 00000060  00 00 00 00 0a 00 0a 00  08 00 1d 00 17 00 18 00  |................|
 00000070  19 00 0b 00 02 01 00 00  0d 00 1a 00 18 08 04 04  |................|
 00000080  03 08 07 08 05 08 06 04  01 05 01 06 01 05 03 06  |................|
 000000c0  ac 5f bb 29 07 30 ff f6  84 af c4 cf c2 ed 90 99  |._.).0..........|
 000000d0  5f 58 cb 3b 74                                    |_X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 4e fb dc 04 6f  |....Y...U..N...o|
-00000010  5a 52 37 a3 55 58 26 e5  cd a0 67 4c 0f 87 1a 3a  |ZR7.UX&...gL...:|
-00000020  f6 84 33 2f 2e 52 d0 48  7c 5b 64 20 6e d0 bc ca  |..3/.R.H|[d n...|
-00000030  c9 a5 87 8d 99 c5 ec 85  84 89 f0 22 ab 63 55 f4  |...........".cU.|
-00000040  70 d7 02 93 b5 fe d7 38  fb c1 b2 da cc a8 00 00  |p......8........|
+00000000  16 03 03 00 59 02 00 00  55 03 03 2a 76 db 4b d5  |....Y...U..*v.K.|
+00000010  10 f3 21 f2 4b 29 a2 2e  7a 7d 0b 86 c4 af 60 95  |..!.K)..z}....`.|
+00000020  5b 11 84 27 8a 59 7f af  a0 27 de 20 02 f7 dc 9b  |[..'.Y...'. ....|
+00000030  63 8e 2e da 48 b5 73 81  8e 76 13 da dd 2e 17 2b  |c...H.s..v.....+|
+00000040  ff 18 ad d7 9d f3 44 ed  b6 60 0e 42 cc a8 00 00  |......D..`.B....|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 59 0b 00 02 55 00  02 52 00 02 4f 30 82 02  |..Y...U..R..O0..|
 00000070  4b 30 82 01 b4 a0 03 02  01 02 02 09 00 e8 f0 9d  |K0..............|
 00000290  77 8d 0c 1c f1 0f a1 d8  40 83 61 c9 4c 72 2b 9d  |w.......@.a.Lr+.|
 000002a0  ae db 46 06 06 4d f4 c1  b3 3e c0 d1 bd 42 d4 db  |..F..M...>...B..|
 000002b0  fe 3d 13 60 84 5c 21 d3  3b e9 fa e7 16 03 03 00  |.=.`.\!.;.......|
-000002c0  ac 0c 00 00 a8 03 00 1d  20 fc 4b 92 ab d2 cb 4f  |........ .K....O|
-000002d0  61 aa 86 12 1a 1d 75 be  31 dd b8 ee 6c a6 db bd  |a.....u.1...l...|
-000002e0  0b ea b2 d5 27 49 42 eb  5a 08 04 00 80 02 ad 71  |....'IB.Z......q|
-000002f0  e2 e8 f6 44 3c a6 18 6f  76 ee 9a eb 0e d9 ff cb  |...D<..ov.......|
-00000300  6d 1e 64 dd 29 1d 8c c8  f6 14 40 c0 12 46 74 4c  |m.d.).....@..FtL|
-00000310  41 2d 71 5f 9c b7 86 0b  fc 66 1e 14 cb 26 d0 d7  |A-q_.....f...&..|
-00000320  21 b4 bd c2 04 38 77 90  6a f0 01 18 bd 1c 17 45  |!....8w.j......E|
-00000330  7e 38 46 4c 2e 97 ba 11  01 1f 20 cc df f2 6b 5b  |~8FL...... ...k[|
-00000340  a7 29 c0 52 52 9c 2f 23  bd 1c 72 c2 f2 99 d1 dc  |.).RR./#..r.....|
-00000350  6a 6c ac 8e 87 8a 00 74  47 2e 99 8d 3f 79 04 60  |jl.....tG...?y.`|
-00000360  5e dc ba 86 1c f4 f9 03  22 38 96 a7 b3 16 03 03  |^......."8......|
+000002c0  ac 0c 00 00 a8 03 00 1d  20 0d c3 c2 b5 73 da 39  |........ ....s.9|
+000002d0  82 e5 8c 18 0d 8d 16 c2  a5 e7 3e 39 fd 25 00 18  |..........>9.%..|
+000002e0  25 16 c0 a7 6e c6 dd bb  01 08 04 00 80 b3 bd 01  |%...n...........|
+000002f0  ae dd b1 c8 2a 5d 0e 66  6d 1e b3 92 f4 01 63 59  |....*].fm.....cY|
+00000300  0c c1 62 df 75 8f 4f 19  5a cf 2f 63 79 d0 06 31  |..b.u.O.Z./cy..1|
+00000310  c0 60 6a 4f db 70 18 bd  80 8b 30 94 40 dd 13 39  |.`jO.p....0.@..9|
+00000320  4f db 2b 54 a4 97 f7 ef  a5 a3 ff f5 14 3d e2 2d  |O.+T.........=.-|
+00000330  0c 0e 71 4a bd a8 59 48  ab 06 55 53 45 2a ee 3e  |..qJ..YH..USE*.>|
+00000340  65 1f 47 ee 8d e3 f6 4e  2e b1 4c d0 af 50 15 02  |e.G....N..L..P..|
+00000350  5e 84 fe 76 d5 f3 c5 fb  2a 91 44 f0 92 32 ee ea  |^..v....*.D..2..|
+00000360  a0 26 77 5c 94 88 24 e3  2f 75 e3 fd b7 16 03 03  |.&w\..$./u......|
 00000370  00 04 0e 00 00 00                                 |......|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 25 10 00 00  21 20 2f e5 7d a3 47 cd  |....%...! /.}.G.|
 00000010  62 43 15 28 da ac 5f bb  29 07 30 ff f6 84 af c4  |bC.(.._.).0.....|
 00000020  cf c2 ed 90 99 5f 58 cb  3b 74 14 03 03 00 01 01  |....._X.;t......|
-00000030  16 03 03 00 20 0a 17 ee  70 8c 50 24 7c 00 b9 6f  |.... ...p.P$|..o|
-00000040  82 71 ed 2b 8c 0b 4b ff  bb 38 bc 12 7e 0c a5 3e  |.q.+..K..8..~..>|
-00000050  71 a2 ad f8 52                                    |q...R|
+00000030  16 03 03 00 20 0b 58 fe  b5 63 ac 28 f8 34 d6 72  |.... .X..c.(.4.r|
+00000040  1a a3 ec 26 91 70 07 8d  6a 3a 3b 3a 94 5e a3 fa  |...&.p..j:;:.^..|
+00000050  6e 92 3a 15 65                                    |n.:.e|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 20 e9 87 55 12 a8  |.......... ..U..|
-00000010  ad 68 42 0c 60 12 be 2f  2c e5 00 2d 01 cf 86 a2  |.hB.`../,..-....|
-00000020  1b 06 b3 86 bf 88 48 73  7a d3 cc                 |......Hsz..|
+00000000  14 03 03 00 01 01 16 03  03 00 20 01 fa e1 2f 29  |.......... .../)|
+00000010  ee f6 d4 e8 22 b6 e0 8f  82 37 81 83 1b 03 4d 5f  |...."....7....M_|
+00000020  00 80 cb eb 9a 3a 01 c7  aa e9 9a                 |.....:.....|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 16 96 75 4c  c6 ba b1 ad ae 2f 44 9d  |......uL...../D.|
-00000010  10 c3 ef e5 dc fb 0a 3e  af 6b 6a 15 03 03 00 12  |.......>.kj.....|
-00000020  30 13 8f e5 a1 0f 38 67  b9 53 4e 6a 66 ec ee 45  |0.....8g.SNjf..E|
-00000030  c2 b2                                             |..|
+00000000  17 03 03 00 16 43 6a e8  f2 ca f9 4f 3c 6d ff 5e  |.....Cj....O<m.^|
+00000010  f3 19 eb ee 96 1c d8 68  c5 53 86 15 03 03 00 12  |.......h.S......|
+00000020  c2 72 4e 3c 33 93 fa f3  21 32 bb fd e3 c4 ef 1a  |.rN<3...!2......|
+00000030  46 df                                             |F.|
index 35513adb84222b62bf810e0d1d4bc4191fb442c4..72d564f44adf602ee1cc6f338f2e1d2a4ff7007d 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 66 49 2a a6 a4  |....Y...U..fI*..|
-00000010  75 60 58 bb 5f 5e 82 cd  e5 c0 9f 6d a4 fd 39 3b  |u`X._^.....m..9;|
-00000020  d9 17 80 14 89 ea 51 c1  b0 43 d6 20 b2 6b 72 81  |......Q..C. .kr.|
-00000030  f6 63 20 22 e2 b6 d2 61  aa 87 b6 67 ae 56 78 44  |.c "...a...g.VxD|
-00000040  5d 10 8c cf ea 32 cf 9e  92 e5 59 70 cc a9 00 00  |]....2....Yp....|
+00000000  16 03 03 00 59 02 00 00  55 03 03 6c 5f 04 9e a6  |....Y...U..l_...|
+00000010  c6 41 0c ee a2 2c af 45  f0 bc de 67 2d 20 1c 9c  |.A...,.E...g- ..|
+00000020  82 33 fd 86 86 b3 50 04  77 ec da 20 f3 09 fb 8c  |.3....P.w.. ....|
+00000030  79 83 f9 82 58 b9 76 bb  d3 58 44 3d 52 0c 37 ae  |y...X.v..XD=R.7.|
+00000040  18 98 84 9a 56 af 5d 2b  68 68 c7 30 cc a9 00 00  |....V.]+hh.0....|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 01 3c 0b 00 01 38 00  01 35 00 01 32 30 82 01  |..<...8..5..20..|
 00000070  2e 30 81 e1 a0 03 02 01  02 02 10 0f 43 1c 42 57  |.0..........C.BW|
 00000170  90 95 39 e5 0d c1 55 ff  2c 16 b7 1d fc ab 7d 4d  |..9...U.,.....}M|
 00000180  d4 e0 93 13 d0 a9 42 e0  b6 6b fe 5d 67 48 d7 9f  |......B..k.]gH..|
 00000190  50 bc 6c cd 4b 03 83 7c  f2 08 58 cd ac cf 0c 16  |P.l.K..|..X.....|
-000001a0  03 03 00 6c 0c 00 00 68  03 00 1d 20 c4 8c b8 a2  |...l...h... ....|
-000001b0  32 92 b8 22 1f 4c f1 96  00 64 35 47 4e f8 3d 08  |2..".L...d5GN.=.|
-000001c0  83 12 fe 95 a8 e4 8e c9  30 27 5c 39 08 07 00 40  |........0'\9...@|
-000001d0  7f 90 cf e0 87 69 e3 50  e6 fa 5e 28 a1 0f 79 0a  |.....i.P..^(..y.|
-000001e0  6e cf f4 87 e8 2f 55 b2  dd cb 5e 8f 9a 14 bd c2  |n..../U...^.....|
-000001f0  2b 2b 2d ed 72 40 23 5d  6d f4 89 3a ff 09 82 ec  |++-.r@#]m..:....|
-00000200  b6 4b 27 9a 08 ea e9 73  94 b4 31 1f e1 39 86 0e  |.K'....s..1..9..|
+000001a0  03 03 00 6c 0c 00 00 68  03 00 1d 20 a7 28 ef 3e  |...l...h... .(.>|
+000001b0  1c 65 9f 8e 9a 80 0b 7d  ac 9c ce d6 1e 97 54 30  |.e.....}......T0|
+000001c0  53 9b e6 0c 61 e0 ea 9c  ae 70 f2 78 08 07 00 40  |S...a....p.x...@|
+000001d0  0c 49 38 23 a0 75 28 fb  ec 71 a4 89 79 45 d1 ca  |.I8#.u(..q..yE..|
+000001e0  83 6f 5d dd 01 d4 c6 63  53 5d 6e 8f 06 09 80 a1  |.o]....cS]n.....|
+000001f0  f7 ef af 2d 29 af aa 10  86 1c 18 19 3f be bb 90  |...-).......?...|
+00000200  0e c3 9d 1e 6e 60 49 7f  fc c8 42 61 89 c2 e3 04  |....n`I...Ba....|
 00000210  16 03 03 00 04 0e 00 00  00                       |.........|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 25 10 00 00  21 20 2f e5 7d a3 47 cd  |....%...! /.}.G.|
 00000010  62 43 15 28 da ac 5f bb  29 07 30 ff f6 84 af c4  |bC.(.._.).0.....|
 00000020  cf c2 ed 90 99 5f 58 cb  3b 74 14 03 03 00 01 01  |....._X.;t......|
-00000030  16 03 03 00 20 8f 97 36  bd 59 ef 8e 2f 11 28 b0  |.... ..6.Y../.(.|
-00000040  d7 20 79 bf 04 07 45 f9  89 de b0 c7 55 1a ad 80  |. y...E.....U...|
-00000050  0f 8c ef 1d c6                                    |.....|
+00000030  16 03 03 00 20 b2 7f b6  1b 9c ec bf 2e ae a5 70  |.... ..........p|
+00000040  d5 33 9b 63 02 66 77 7d  00 ec 86 e4 bb d4 57 68  |.3.c.fw}......Wh|
+00000050  49 2a d3 be e7                                    |I*...|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 20 47 6c 1f 86 47  |.......... Gl..G|
-00000010  72 03 94 e0 43 f8 e5 ca  03 7d f5 d5 dd 70 05 f5  |r...C....}...p..|
-00000020  98 5d 51 b4 11 49 71 7a  fd 37 9a                 |.]Q..Iqz.7.|
+00000000  14 03 03 00 01 01 16 03  03 00 20 4c 7d ef ed ea  |.......... L}...|
+00000010  ab 8d 4f 38 46 6e 8f 56  b4 1d f2 1f 2c df 57 c0  |..O8Fn.V....,.W.|
+00000020  f9 8a c2 71 f8 6d df b7  c7 1e 23                 |...q.m....#|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 16 b7 a2 f5  8e 7c d3 7d 61 af 29 1c  |.........|.}a.).|
-00000010  77 0c 8d b4 5b d3 be 77  a6 a5 99 15 03 03 00 12  |w...[..w........|
-00000020  d8 23 dc a8 99 fe 1c 6e  f2 2f 41 8e df 40 11 4f  |.#.....n./A..@.O|
-00000030  6b 92                                             |k.|
+00000000  17 03 03 00 16 26 f1 7c  ee c8 3a 61 b0 f7 5a bd  |.....&.|..:a..Z.|
+00000010  b7 61 61 60 69 db cd ea  10 ee 63 15 03 03 00 12  |.aa`i.....c.....|
+00000020  22 c0 65 a4 5d 0e 48 9c  56 f8 54 17 82 5f 29 97  |".e.].H.V.T.._).|
+00000030  be 6b                                             |.k|
index c900aa6d5e12d070eb26ad83c3ae9de18a3931f3..adf1f72dafd9072d403d1e72614c0b2104501acb 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 7c c1 7b 30 03  |....Y...U..|.{0.|
-00000010  3c d7 63 5f 47 1c b1 13  56 56 b4 fd 55 e2 27 3e  |<.c_G...VV..U.'>|
-00000020  39 bb ce 9b 5b 2c 1e 17  33 e1 da 20 65 8b 26 42  |9...[,..3.. e.&B|
-00000030  a4 38 29 c7 9a 25 13 fc  1d 69 cb 10 63 c6 26 fc  |.8)..%...i..c.&.|
-00000040  f4 46 64 31 28 06 b3 a5  a4 c2 f6 5a cc a8 00 00  |.Fd1(......Z....|
+00000000  16 03 03 00 59 02 00 00  55 03 03 79 92 2e 86 bc  |....Y...U..y....|
+00000010  c0 b7 56 2a 25 58 75 b3  25 ac 58 1d 8d 8e d5 87  |..V*%Xu.%.X.....|
+00000020  2d 67 8e 6e d4 d4 b6 67  b1 42 96 20 91 75 0b fa  |-g.n...g.B. .u..|
+00000030  d0 6f ab 91 4a c3 15 07  1d 6c 8e e5 55 f2 26 aa  |.o..J....l..U.&.|
+00000040  4d 5c 57 3b 93 a6 fc 46  c9 f6 80 1e cc a8 00 00  |M\W;...F........|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 59 0b 00 02 55 00  02 52 00 02 4f 30 82 02  |..Y...U..R..O0..|
 00000070  4b 30 82 01 b4 a0 03 02  01 02 02 09 00 e8 f0 9d  |K0..............|
 00000290  77 8d 0c 1c f1 0f a1 d8  40 83 61 c9 4c 72 2b 9d  |w.......@.a.Lr+.|
 000002a0  ae db 46 06 06 4d f4 c1  b3 3e c0 d1 bd 42 d4 db  |..F..M...>...B..|
 000002b0  fe 3d 13 60 84 5c 21 d3  3b e9 fa e7 16 03 03 00  |.=.`.\!.;.......|
-000002c0  ac 0c 00 00 a8 03 00 1d  20 f7 a2 97 2f 50 e4 e2  |........ .../P..|
-000002d0  fa ef 80 67 78 1c aa 6c  03 aa 05 3b 6f 98 97 11  |...gx..l...;o...|
-000002e0  7e 55 3d 50 f3 a9 9b 21  65 08 04 00 80 34 4a 4b  |~U=P...!e....4JK|
-000002f0  4b 6e 86 01 1b 6b 8e 3e  84 01 75 b8 05 c3 b2 52  |Kn...k.>..u....R|
-00000300  16 ee ac 61 83 dd 09 32  d5 55 6a 5d d6 6b 4a 1a  |...a...2.Uj].kJ.|
-00000310  2b f7 09 33 6f 3d 4f c1  e3 aa 03 27 fe af cd 6d  |+..3o=O....'...m|
-00000320  b8 76 00 02 42 98 e6 f6  b7 ed fb 35 35 29 23 b1  |.v..B......55)#.|
-00000330  4d 48 0a ba a1 1b e3 8e  a2 cb 80 11 ec 92 20 df  |MH............ .|
-00000340  1f a4 5e 5d 70 85 8e 5d  85 62 81 1f b3 3a 0d 8d  |..^]p..].b...:..|
-00000350  9a 07 d3 99 a5 3c 6c c2  52 08 f0 be 50 ed d2 4d  |.....<l.R...P..M|
-00000360  44 ed e7 40 06 64 4e 17  fe 4a 0e 1b d6 16 03 03  |D..@.dN..J......|
+000002c0  ac 0c 00 00 a8 03 00 1d  20 5f 3c a6 bb 4e 32 85  |........ _<..N2.|
+000002d0  69 4b 23 df 18 9c 07 ac  0b a8 dd 9b 59 33 00 02  |iK#.........Y3..|
+000002e0  99 de 4e 66 1e 04 3b ce  4b 08 04 00 80 82 41 7c  |..Nf..;.K.....A||
+000002f0  7b b8 ee d4 23 08 c3 23  8d b1 ea 27 43 e7 8e f1  |{...#..#...'C...|
+00000300  7b 87 b0 88 ab f7 b1 15  2e 45 c5 50 e7 cd 05 31  |{........E.P...1|
+00000310  bf 99 30 c8 ff 6a 23 ec  9d e5 c8 09 fa ec 50 a8  |..0..j#.......P.|
+00000320  fa b3 54 b7 c5 61 99 f6  94 12 e6 34 4a 59 e3 dd  |..T..a.....4JY..|
+00000330  e5 7f f4 88 c9 2a 4c 09  65 d9 75 a6 ce 12 96 82  |.....*L.e.u.....|
+00000340  a2 36 f2 5e 93 f2 4e 1c  05 91 a7 5a 67 36 e9 3d  |.6.^..N....Zg6.=|
+00000350  33 cd 6a 77 9c 8d 14 95  80 41 61 bd 80 ed 7b 51  |3.jw.....Aa...{Q|
+00000360  cf 76 87 4d ac dc 5f c1  5d 52 a7 f9 51 16 03 03  |.v.M.._.]R..Q...|
 00000370  00 04 0e 00 00 00                                 |......|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 25 10 00 00  21 20 2f e5 7d a3 47 cd  |....%...! /.}.G.|
 00000010  62 43 15 28 da ac 5f bb  29 07 30 ff f6 84 af c4  |bC.(.._.).0.....|
 00000020  cf c2 ed 90 99 5f 58 cb  3b 74 14 03 03 00 01 01  |....._X.;t......|
-00000030  16 03 03 00 20 30 8b ea  ef 6c 35 97 5b 26 5f ef  |.... 0...l5.[&_.|
-00000040  bc 28 fd e9 23 73 bb b3  ae 41 0c be 5f 83 a5 f7  |.(..#s...A.._...|
-00000050  96 07 8d 81 67                                    |....g|
+00000030  16 03 03 00 20 bc c3 7c  c2 cc a4 4e 8f d0 79 7a  |.... ..|...N..yz|
+00000040  a4 7d 4c 3d 17 8c 19 93  4f 49 03 50 f6 71 4d 16  |.}L=....OI.P.qM.|
+00000050  97 bb 18 88 67                                    |....g|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 20 29 fa a8 de f2  |.......... )....|
-00000010  8f 94 16 fc be 84 93 e9  34 98 c2 44 08 9b 2e 37  |........4..D...7|
-00000020  1f 41 61 53 fa 9c 23 ff  d8 6d c3                 |.AaS..#..m.|
+00000000  14 03 03 00 01 01 16 03  03 00 20 00 c4 8a f9 1e  |.......... .....|
+00000010  c0 66 ab ef 39 ae 41 7a  05 9c e3 06 e4 4d 00 bb  |.f..9.Az.....M..|
+00000020  d4 ef 21 71 a3 54 23 fe  db 4a 86                 |..!q.T#..J.|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 16 ab 6d 32  1c 16 cc 29 b1 21 4c b1  |......m2...).!L.|
-00000010  74 4c 50 e3 1f c5 f1 05  6a 8a 92 15 03 03 00 12  |tLP.....j.......|
-00000020  18 88 3d 23 81 d7 ba c5  1e 9a c4 3a 1b c8 cd 5b  |..=#.......:...[|
-00000030  c5 fa                                             |..|
+00000000  17 03 03 00 16 0c d3 9a  f5 1d f4 5f b2 45 c7 7c  |..........._.E.||
+00000010  38 59 6e df 6e 59 d5 94  8b a9 bb 15 03 03 00 12  |8Yn.nY..........|
+00000020  9e 74 a5 0e c1 7f 33 52  be 17 f6 f5 4d 9f 3d d1  |.t....3R....M.=.|
+00000030  b5 65                                             |.e|
index d75b670e1d535603e185682ee84ceea548fd2c6f..3331435315614614210dcc32767a5f93b2d229cf 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 96 00 05 00 05  01 00 00 00 00 00 0a 00  |................|
 00000090  04 00 02 00 17 00 0b 00  02 01 00 00 0d 00 1a 00  |................|
 000000a0  18 08 04 04 03 08 07 08  05 08 06 04 01 05 01 06  |................|
 00000100  07 9f 6c 4b 5b 83 56 e2  32 42 e9 58 b6 d7 49 a6  |..lK[.V.2B.X..I.|
 00000110  b5 68 1a 41 03 56 6b dc  5a 89                    |.h.A.Vk.Z.|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 b8 7d f5 69 c3  |....Y...U...}.i.|
-00000010  6a ca 8b df f3 30 2c 39  47 2e 74 2e 4f 89 4c 1e  |j....0,9G.t.O.L.|
-00000020  f0 eb 10 0e 06 1d 2c 4e  de 2e 8f 20 6c a0 5b 66  |......,N... l.[f|
-00000030  fc a6 05 df 29 6b ce 72  92 e7 d7 78 f5 46 38 f9  |....)k.r...x.F8.|
-00000040  91 1c 9a 08 4c b1 9a 41  e5 0c d2 cd c0 2f 00 00  |....L..A...../..|
+00000000  16 03 03 00 59 02 00 00  55 03 03 0b f0 3e a1 66  |....Y...U....>.f|
+00000010  13 35 53 83 59 3c 9e 2a  0f 0b b0 9a 42 de e4 f1  |.5S.Y<.*....B...|
+00000020  8a 2d 34 ef 15 fe 28 55  42 d8 bf 20 aa 27 5c 5f  |.-4...(UB.. .'\_|
+00000030  24 59 17 ef 43 f3 18 f8  40 97 8f 1a 6a f4 e4 4a  |$Y..C...@...j..J|
+00000040  a3 b7 11 39 01 bd 98 8c  61 08 d9 50 c0 2f 00 00  |...9....a..P./..|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 59 0b 00 02 55 00  02 52 00 02 4f 30 82 02  |..Y...U..R..O0..|
 00000070  4b 30 82 01 b4 a0 03 02  01 02 02 09 00 e8 f0 9d  |K0..............|
 00000290  77 8d 0c 1c f1 0f a1 d8  40 83 61 c9 4c 72 2b 9d  |w.......@.a.Lr+.|
 000002a0  ae db 46 06 06 4d f4 c1  b3 3e c0 d1 bd 42 d4 db  |..F..M...>...B..|
 000002b0  fe 3d 13 60 84 5c 21 d3  3b e9 fa e7 16 03 03 00  |.=.`.\!.;.......|
-000002c0  cd 0c 00 00 c9 03 00 17  41 04 3e 87 67 8b 87 08  |........A.>.g...|
-000002d0  fe 4e 4c c3 6b 42 4b 97  ad f4 1c 83 35 72 db 4f  |.NL.kBK.....5r.O|
-000002e0  39 83 ea 14 69 bb 8c 87  58 c5 a4 a8 8c d7 9d af  |9...i...X.......|
-000002f0  7a 5e 58 59 31 4d f2 01  4a 23 51 24 1b 04 0c e3  |z^XY1M..J#Q$....|
-00000300  94 9e 1b 6c ad aa 83 fd  2d 36 08 04 00 80 ab e9  |...l....-6......|
-00000310  ff 6d 7a cd 3b a7 da ff  d5 bd 27 49 68 53 f5 45  |.mz.;.....'IhS.E|
-00000320  c3 dd 5b a2 99 fb 8f 24  37 49 d3 08 87 d1 06 98  |..[....$7I......|
-00000330  39 72 25 78 b3 05 fb a2  c9 ac f9 c8 f7 fc ea 8a  |9r%x............|
-00000340  98 ce 78 83 64 f6 e0 c7  44 62 af a7 d5 26 df f1  |..x.d...Db...&..|
-00000350  2c cc ce 11 8b 03 4a e1  81 54 3f e1 6e 52 c9 1a  |,.....J..T?.nR..|
-00000360  d8 95 52 e0 3f a5 e3 c8  12 9a c7 57 5d 46 7a ce  |..R.?......W]Fz.|
-00000370  56 8a 90 0f 0d 1b ba 58  cf 1c a3 4b 39 5a 08 ee  |V......X...K9Z..|
-00000380  8a 61 bb 0f 7d f7 0e f2  1f 73 e0 c8 6f 54 16 03  |.a..}....s..oT..|
+000002c0  cd 0c 00 00 c9 03 00 17  41 04 79 6a df 70 26 49  |........A.yj.p&I|
+000002d0  c0 5a 39 fc 7c 80 d1 2c  cd 76 d0 4c 6f a7 7d bc  |.Z9.|..,.v.Lo.}.|
+000002e0  32 c6 54 c6 76 58 e2 0f  3f 33 ad 92 61 33 11 16  |2.T.vX..?3..a3..|
+000002f0  d7 42 a8 ba 2a 8f 22 2a  eb 88 3e 74 78 2a 67 de  |.B..*."*..>tx*g.|
+00000300  39 75 63 2c 1d 2e da 33  77 a5 08 04 00 80 61 f5  |9uc,...3w.....a.|
+00000310  ed 56 5b f1 dd 78 a0 c4  8a 9b ac 28 c5 91 0c bd  |.V[..x.....(....|
+00000320  f1 d5 c1 f6 31 2e 8c c3  d5 84 3a 15 e8 6d f1 bc  |....1.....:..m..|
+00000330  9e a6 04 fd 95 2f 51 60  2f c6 ff 99 cf 38 24 bf  |...../Q`/....8$.|
+00000340  a4 32 a2 1f a1 6b bd 27  98 00 14 23 0d 12 66 67  |.2...k.'...#..fg|
+00000350  48 33 92 51 e7 e7 3c f5  ef 13 ca 46 3c 39 53 70  |H3.Q..<....F<9Sp|
+00000360  41 78 4a 02 70 87 48 ce  b0 31 02 33 0b 06 78 b9  |AxJ.p.H..1.3..x.|
+00000370  87 0b 07 e0 f7 15 c8 3e  27 a1 a3 20 24 9e 20 93  |.......>'.. $. .|
+00000380  7f b5 53 7b 18 88 96 87  2b df 02 ba 0c d8 16 03  |..S{....+.......|
 00000390  03 00 04 0e 00 00 00                              |.......|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 46 10 00 00  42 41 04 1e 18 37 ef 0d  |....F...BA...7..|
 00000020  a7 24 20 3e b2 56 1c ce  97 28 5e f8 2b 2d 4f 9e  |.$ >.V...(^.+-O.|
 00000030  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
 00000040  a6 b5 68 1a 41 03 56 6b  dc 5a 89 14 03 03 00 01  |..h.A.Vk.Z......|
-00000050  01 16 03 03 00 28 00 00  00 00 00 00 00 00 b8 16  |.....(..........|
-00000060  ce 7d df 64 13 07 9e d8  37 bb 3f 9c 9e 2b 3c 0e  |.}.d....7.?..+<.|
-00000070  26 a7 9d 32 e5 44 b8 d6  66 bc 05 7b 27 7a        |&..2.D..f..{'z|
+00000050  01 16 03 03 00 28 00 00  00 00 00 00 00 00 c1 90  |.....(..........|
+00000060  a0 8b 53 87 a8 e3 56 4c  5c ad 5f dc 00 af 29 5f  |..S...VL\._...)_|
+00000070  11 53 7d 49 25 f8 74 16  dc 84 5f 3b c6 24        |.S}I%.t..._;.$|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 28 c0 73 5c 27 1b  |..........(.s\'.|
-00000010  19 d0 66 68 ea c5 ad 7d  a8 03 37 d2 9a ff 00 c4  |..fh...}..7.....|
-00000020  70 65 98 3b 88 59 c0 ca  e3 c0 d6 32 0e 8d 15 3c  |pe.;.Y.....2...<|
-00000030  e2 c3 f3                                          |...|
+00000000  14 03 03 00 01 01 16 03  03 00 28 00 f9 b2 51 85  |..........(...Q.|
+00000010  72 7e ec 79 72 59 90 ae  69 51 79 61 10 3b 4e 4b  |r~.yrY..iQya.;NK|
+00000020  45 d6 a5 9a c0 1a 69 c9  9f 1c ee cd ad 6a e8 ea  |E.....i......j..|
+00000030  c4 9e f1                                          |...|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 28 ef 47  |.............(.G|
-00000010  ad 7f 40 4b 34 78 f3 1e  01 a7 f4 20 0a d5 c1 41  |..@K4x..... ...A|
-00000020  f7 be 41 15 03 03 00 1a  00 00 00 00 00 00 00 02  |..A.............|
-00000030  fb fc eb 14 f2 a6 e7 2e  80 d6 93 31 25 01 e9 d2  |...........1%...|
-00000040  c3 ae                                             |..|
+00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 86 5a 45  |..............ZE|
+00000010  24 60 90 dc bc b3 f6 61  6f db 60 02 99 f9 e2 93  |$`.....ao.`.....|
+00000020  07 85 0d 15 03 03 00 1a  00 00 00 00 00 00 00 02  |................|
+00000030  36 86 b0 60 b5 5d dd 28  64 c6 5b c7 ed 01 07 b1  |6..`.].(d.[.....|
+00000040  12 39                                             |.9|
index ab2c4eb14d853574620dafcdb03cbc139fdfb6ac..12fb594c047b00888224443701d441a867773689 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 51 02 00 00  4d 03 03 34 50 1f 52 15  |....Q...M..4P.R.|
-00000010  85 c7 85 2c 4d a9 b2 0c  49 e5 a3 ea 57 21 96 39  |...,M...I...W!.9|
-00000020  db c9 97 b6 c4 d0 81 9a  39 a3 e8 20 59 f5 b9 db  |........9.. Y...|
-00000030  58 2e ef 1c b3 85 96 27  6a 23 71 3f 5c 72 ce cf  |X......'j#q?\r..|
-00000040  c5 b7 fe 05 00 f4 65 06  54 c1 2e 7c 00 05 00 00  |......e.T..|....|
+00000000  16 03 03 00 51 02 00 00  4d 03 03 b0 e7 ee 09 45  |....Q...M......E|
+00000010  36 f1 7a 92 be 9e d8 9d  ae cd c1 4e b2 12 94 3e  |6.z........N...>|
+00000020  6c 34 71 ed 5f e0 97 7f  25 e4 dd 20 f4 43 01 03  |l4q._...%.. .C..|
+00000030  88 33 26 7f 48 c1 f2 d1  4d d3 f8 1a bd 86 4c 50  |.3&.H...M.....LP|
+00000040  18 89 dc 08 99 f1 51 c5  84 be b9 fd 00 05 00 00  |......Q.........|
 00000050  05 ff 01 00 01 00 16 03  03 02 59 0b 00 02 55 00  |..........Y...U.|
 00000060  02 52 00 02 4f 30 82 02  4b 30 82 01 b4 a0 03 02  |.R..O0..K0......|
 00000070  01 02 02 09 00 e8 f0 9d  3f e2 5b ea a6 30 0d 06  |........?.[..0..|
 00000060  c5 70 0f 08 83 48 e9 48  ef 6e 50 8b 05 7e e5 84  |.p...H.H.nP..~..|
 00000070  25 fa 55 c7 ae 31 02 27  00 ef 3f 98 86 20 12 89  |%.U..1.'..?.. ..|
 00000080  91 59 28 b4 f7 d7 af d2  69 61 35 14 03 03 00 01  |.Y(.....ia5.....|
-00000090  01 16 03 03 00 24 ab 48  84 ae 77 f9 8b 82 44 52  |.....$.H..w...DR|
-000000a0  3e 65 94 27 cc f2 08 a7  f2 e5 21 0c 02 d0 89 ac  |>e.'......!.....|
-000000b0  50 be 69 57 c9 7c a0 f2  7f 6d                    |P.iW.|...m|
+00000090  01 16 03 03 00 24 08 65  01 80 0d 59 b8 ac 0f 09  |.....$.e...Y....|
+000000a0  bf 61 31 32 e0 74 e9 f4  72 e3 2c 79 11 4d b2 a2  |.a12.t..r.,y.M..|
+000000b0  55 65 94 c8 cd 0a 61 99  07 b8                    |Ue....a...|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 24 61 94 21 65 0f  |..........$a.!e.|
-00000010  10 ba 0c a6 d9 e3 08 54  86 ae f9 64 c7 e7 f4 4b  |.......T...d...K|
-00000020  aa f5 19 ca 2a 0d 50 88  85 42 32 14 04 29 d9     |....*.P..B2..).|
+00000000  14 03 03 00 01 01 16 03  03 00 24 04 20 46 cd fb  |..........$. F..|
+00000010  6c 46 9c 47 21 03 fe 9b  a4 c6 da 2c 71 2f db 92  |lF.G!......,q/..|
+00000020  40 da 7d 46 2e e4 9c 81  86 89 7f 53 46 91 28     |@.}F.......SF.(|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 1a cb 1d 43  67 de 7a 20 c7 ed 46 99  |.......Cg.z ..F.|
-00000010  86 1f b9 61 9f c6 34 9a  07 37 3c 94 45 b4 40 15  |...a..4..7<.E.@.|
-00000020  03 03 00 16 4e ac d3 12  23 b4 33 bc 5b 03 91 7e  |....N...#.3.[..~|
-00000030  d9 d0 7f d7 48 3e 8c 16  16 ec                    |....H>....|
+00000000  17 03 03 00 1a 89 2b 2e  49 21 19 b7 d0 df 85 da  |......+.I!......|
+00000010  b8 a7 f3 73 5f fe 44 e5  0c a1 af 16 74 93 bc 15  |...s_.D.....t...|
+00000020  03 03 00 16 5f 9e 64 d0  91 50 34 44 cf f6 1f e0  |...._.d..P4D....|
+00000030  e0 13 b9 67 da 5c 99 16  f1 b3                    |...g.\....|
index 48a99eda1556a6540258d2155873c7f63ea8f639..06752dea01ebcc664c8efbe8de8c134d641daa23 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 f1 d8 72 0c 79  |....Y...U....r.y|
-00000010  e2 ca 92 11 1c 30 cc 45  00 9b ea 3d a3 ed 23 d5  |.....0.E...=..#.|
-00000020  22 f0 da 9c 03 32 7b c3  13 d3 df 20 8f 7a 61 43  |"....2{.... .zaC|
-00000030  cb 72 46 5e c1 39 78 42  32 97 cc 2b 90 2e 53 59  |.rF^.9xB2..+..SY|
-00000040  31 38 ec 7b 2b 8a f3 80  e0 03 f0 0e cc a8 00 00  |18.{+...........|
+00000000  16 03 03 00 59 02 00 00  55 03 03 5b 4b bb c4 39  |....Y...U..[K..9|
+00000010  fb 45 5c 54 03 30 0f 71  c3 2e 48 25 33 fd 6d 40  |.E\T.0.q..H%3.m@|
+00000020  18 6e 75 43 66 9e 08 fb  6a a1 f8 20 34 3c c4 2a  |.nuCf...j.. 4<.*|
+00000030  b5 9b 65 b0 cd b9 fc ce  cf 51 f8 cc a1 5d 00 ed  |..e......Q...]..|
+00000040  49 5b 43 9a ff c4 cf 6b  d8 2a ea e5 cc a8 00 00  |I[C....k.*......|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 59 0b 00 02 55 00  02 52 00 02 4f 30 82 02  |..Y...U..R..O0..|
 00000070  4b 30 82 01 b4 a0 03 02  01 02 02 09 00 e8 f0 9d  |K0..............|
 00000290  77 8d 0c 1c f1 0f a1 d8  40 83 61 c9 4c 72 2b 9d  |w.......@.a.Lr+.|
 000002a0  ae db 46 06 06 4d f4 c1  b3 3e c0 d1 bd 42 d4 db  |..F..M...>...B..|
 000002b0  fe 3d 13 60 84 5c 21 d3  3b e9 fa e7 16 03 03 00  |.=.`.\!.;.......|
-000002c0  ac 0c 00 00 a8 03 00 1d  20 96 cb 1d cd f6 2f ff  |........ ...../.|
-000002d0  fe 32 ef d6 18 a2 6b 57  66 cd 3d 50 42 56 dc a4  |.2....kWf.=PBV..|
-000002e0  5f fe e4 91 ce d1 17 34  3c 08 04 00 80 b1 47 de  |_......4<.....G.|
-000002f0  b3 19 b0 fd 02 35 eb 3c  a1 04 d3 6b 53 84 20 c7  |.....5.<...kS. .|
-00000300  08 4b 96 12 23 ae bf ca  a8 83 1d 90 16 ae d3 7c  |.K..#..........||
-00000310  fa 1b b4 f0 bb bb 4e 3f  70 13 2f 40 6c d4 76 61  |......N?p./@l.va|
-00000320  5b 23 85 3f e7 37 ef e1  55 47 8d 01 e1 24 22 7f  |[#.?.7..UG...$".|
-00000330  a4 2c 6f 97 47 5f d6 69  bf b4 db 4b b8 a1 ad 66  |.,o.G_.i...K...f|
-00000340  5f d5 5d b6 06 ac 93 ed  d7 06 cb b5 a4 d4 4b a7  |_.]...........K.|
-00000350  7b de f7 73 60 af ad 23  f4 6a f1 bf 2a ee 5b 4e  |{..s`..#.j..*.[N|
-00000360  83 94 d7 95 3b e5 5e a5  3d 1a 0a 7a 9e 16 03 03  |....;.^.=..z....|
+000002c0  ac 0c 00 00 a8 03 00 1d  20 76 c4 f4 ec a2 d6 c1  |........ v......|
+000002d0  b1 d8 b0 41 71 8a ee e9  8a 17 06 90 6b 0c 05 66  |...Aq.......k..f|
+000002e0  54 d8 a6 ad 50 95 11 f0  03 08 04 00 80 46 0b da  |T...P........F..|
+000002f0  0b 0c 6c 1a 2e a2 7e 28  40 1b 40 9a b4 5c 36 88  |..l...~(@.@..\6.|
+00000300  c1 ad cd 45 be 23 17 a6  98 e5 11 fe a8 78 c6 21  |...E.#.......x.!|
+00000310  17 a6 a8 7d ce 28 c4 ef  51 76 f8 b1 b1 75 31 04  |...}.(..Qv...u1.|
+00000320  b9 14 bc 3b bf 59 50 b8  e1 ad c6 86 45 3c e1 70  |...;.YP.....E<.p|
+00000330  fb cd 69 8c 0a 5f f6 2d  bd 10 95 30 ed 4c 9a 47  |..i.._.-...0.L.G|
+00000340  73 8b 39 72 00 0a 7e 8f  a9 42 27 01 6f 3d 37 f9  |s.9r..~..B'.o=7.|
+00000350  7d d4 1b a2 6a 07 37 dc  5e 6c 8b b1 d5 75 3a 9b  |}...j.7.^l...u:.|
+00000360  d1 45 c5 d8 e0 90 f0 62  3d d5 01 00 9e 16 03 03  |.E.....b=.......|
 00000370  00 04 0e 00 00 00                                 |......|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 25 10 00 00  21 20 2f e5 7d a3 47 cd  |....%...! /.}.G.|
 00000010  62 43 15 28 da ac 5f bb  29 07 30 ff f6 84 af c4  |bC.(.._.).0.....|
 00000020  cf c2 ed 90 99 5f 58 cb  3b 74 14 03 03 00 01 01  |....._X.;t......|
-00000030  16 03 03 00 20 f2 6f 2e  79 5c db 90 b8 2e cf 59  |.... .o.y\.....Y|
-00000040  0a 56 69 86 f1 71 0c ff  a9 7c 0b a0 e7 c9 8d 17  |.Vi..q...|......|
-00000050  65 ad a5 6c 82                                    |e..l.|
+00000030  16 03 03 00 20 bb f4 78  64 23 f7 31 50 42 3d 97  |.... ..xd#.1PB=.|
+00000040  8f 73 89 b9 90 8f 74 b6  e4 7d 58 27 65 25 59 8a  |.s....t..}X'e%Y.|
+00000050  5a 8d 8f fa bd                                    |Z....|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 20 d5 90 08 84 71  |.......... ....q|
-00000010  bc 09 48 be ad 59 11 76  c6 39 bb 94 8c 60 80 29  |..H..Y.v.9...`.)|
-00000020  44 1a 0d fe 5c 00 4c bc  47 3c 1e                 |D...\.L.G<.|
+00000000  14 03 03 00 01 01 16 03  03 00 20 0a 43 74 53 47  |.......... .CtSG|
+00000010  41 4b 0a f1 f7 75 51 a9  22 c9 e0 5c 53 90 6b d7  |AK...uQ."..\S.k.|
+00000020  97 18 c6 ef c3 85 32 f5  7c 26 97                 |......2.|&.|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 16 42 cd 1c  e5 91 35 b0 c1 4d df e4  |.....B....5..M..|
-00000010  b0 ca f3 8a 7a 41 85 31  7a 7d 59                 |....zA.1z}Y|
+00000000  17 03 03 00 16 8e 83 1a  32 53 02 1c fa 84 89 4f  |........2S.....O|
+00000010  25 fb 5f 85 4f bd ee ae  9f 0f ea                 |%._.O......|
 >>> Flow 6 (server to client)
-00000000  16 03 03 00 14 3b 0f 40  64 9f ff 8f b9 85 18 af  |.....;.@d.......|
-00000010  b4 bc e7 33 8a 9b 03 de  ed                       |...3.....|
+00000000  16 03 03 00 14 96 76 32  c4 6d e6 23 bf 21 a8 09  |......v2.m.#.!..|
+00000010  a3 8b 69 98 cd c3 c9 ce  73                       |..i.....s|
 >>> Flow 7 (client to server)
-00000000  16 03 03 01 16 17 a7 61  5b 22 97 6e eb dd 43 84  |.......a[".n..C.|
-00000010  b9 ac 15 c2 76 7d 1f c0  e3 46 11 af c0 59 7d cc  |....v}...F...Y}.|
-00000020  d4 5d 02 90 28 bb b3 7c  85 76 46 34 7c bf 2b bf  |.]..(..|.vF4|.+.|
-00000030  c4 e9 e1 46 b0 15 7e af  c1 03 4a 17 b3 7a 03 cd  |...F..~...J..z..|
-00000040  e0 90 b1 1b 59 ac 1f 33  b0 41 c3 47 ee 58 af 5b  |....Y..3.A.G.X.[|
-00000050  5b c4 7a 92 02 e2 34 8d  cd 70 20 c4 59 5e 25 f2  |[.z...4..p .Y^%.|
-00000060  28 b1 f2 a5 e0 c4 f9 d0  ae cc 2b 1e ea d4 5a fe  |(.........+...Z.|
-00000070  62 97 bc d7 57 94 5c b8  ce 4c 62 1a e5 29 02 1e  |b...W.\..Lb..)..|
-00000080  0e 68 1d 8a 17 f9 47 55  ac 65 cf 13 88 d3 95 0d  |.h....GU.e......|
-00000090  d7 e0 d8 03 f8 f6 6f 9c  5b de 5c 80 c3 34 7e 82  |......o.[.\..4~.|
-000000a0  5c 8b c4 a3 99 c8 1e f0  f2 e5 6e 73 40 62 31 8e  |\.........ns@b1.|
-000000b0  3b 08 62 ba a8 b9 18 c4  84 a0 b4 9f 68 81 2f ae  |;.b.........h./.|
-000000c0  8d 7c cc 54 ba 4a ec 26  a5 8a 9b a7 bd 36 17 2c  |.|.T.J.&.....6.,|
-000000d0  52 69 4c 57 81 64 e6 34  88 27 81 d2 32 eb d2 8d  |RiLW.d.4.'..2...|
-000000e0  4d 8d c1 8b 14 b3 07 19  63 f8 d6 4a 9a 7d 3f c1  |M.......c..J.}?.|
-000000f0  af 18 72 f7 2d c8 7e 82  52 28 51 80 59 0c 9b 9f  |..r.-.~.R(Q.Y...|
-00000100  ac 40 69 25 0e 6d d7 4a  72 b5 18 f8 78 b9 52 c3  |.@i%.m.Jr...x.R.|
-00000110  d6 32 6c 7d 29 70 a8 33  18 d0 4b                 |.2l})p.3..K|
+00000000  16 03 03 01 16 72 5b d9  30 b2 b0 91 e2 3d 2b 12  |.....r[.0....=+.|
+00000010  2c c9 43 f1 67 ae 54 ee  ce a1 15 12 12 9a 27 46  |,.C.g.T.......'F|
+00000020  7e 47 90 d4 f2 7d b9 98  ec f8 61 b8 84 52 9f 21  |~G...}....a..R.!|
+00000030  c1 83 6a ce 1a 68 fc 5b  25 42 f3 8f 55 ee 92 45  |..j..h.[%B..U..E|
+00000040  af a4 d1 c4 a6 b5 0e 58  3d 70 76 98 ec 47 af 6f  |.......X=pv..G.o|
+00000050  e3 4f 9f ef 52 a3 aa 33  75 83 f6 57 33 a8 dc f5  |.O..R..3u..W3...|
+00000060  36 49 09 1c 72 31 c1 43  52 64 4a b5 ca ce 06 f5  |6I..r1.CRdJ.....|
+00000070  91 18 90 85 f0 c9 96 4f  bf 4c de 9e 50 a2 1c de  |.......O.L..P...|
+00000080  86 51 1f 0b 73 e1 df 1d  2d 90 6d 7f a2 f1 28 e8  |.Q..s...-.m...(.|
+00000090  5f 2a 78 2d 8e ab f2 05  19 85 4e 92 a8 cf cd 16  |_*x-......N.....|
+000000a0  1e df 1d 51 ee 8b ba 72  cd ac d2 01 4b 84 46 62  |...Q...r....K.Fb|
+000000b0  1c 28 4d 3f 44 c1 62 12  13 4f f8 73 f4 da c0 98  |.(M?D.b..O.s....|
+000000c0  14 da 31 6a 48 0d 1d bb  24 6c ef 0f 98 c0 3c 86  |..1jH...$l....<.|
+000000d0  c6 d6 8e ab bd 20 bd 06  e9 ba aa ce 3a 88 25 95  |..... ......:.%.|
+000000e0  54 15 fb c6 49 c7 98 ff  27 92 c0 60 6a 3c f8 26  |T...I...'..`j<.&|
+000000f0  fd 28 ac c4 8f 5c 4f 15  24 10 45 3c 07 3d 3f 50  |.(...\O.$.E<.=?P|
+00000100  e5 db cf 78 bd b0 d2 24  a2 4b 3e a6 9c 2d 3b 0d  |...x...$.K>..-;.|
+00000110  d8 1b 86 88 dc 0c 3c 9c  16 cf ea                 |......<....|
 >>> Flow 8 (server to client)
-00000000  16 03 03 00 81 8b e2 a1  f5 15 55 13 f6 f2 fa 95  |..........U.....|
-00000010  3b bb 0f 3d 3e 9b 3c b1  60 cb 69 7f 63 62 2d 9b  |;..=>.<.`.i.cb-.|
-00000020  20 47 3a 7d 5e d0 98 38  49 c3 94 f8 1d 56 1d 69  | G:}^..8I....V.i|
-00000030  27 65 bc ca 63 22 65 61  60 67 49 35 f0 eb 83 1b  |'e..c"ea`gI5....|
-00000040  44 c4 f0 91 64 5a 81 b5  06 4b 3e 3a ef 3b 5c b0  |D...dZ...K>:.;\.|
-00000050  81 b4 36 df f3 0d a3 0a  1c 40 03 fa 81 48 42 70  |..6......@...HBp|
-00000060  bf 4c b3 6b 67 19 7b 83  05 a1 31 a3 1c 79 49 2c  |.L.kg.{...1..yI,|
-00000070  1f 58 bc 7d 98 4e 5b 64  44 3d 3c 43 fb 77 c7 7c  |.X.}.N[dD=<C.w.||
-00000080  65 aa 0a 3d 49 a1 16 03  03 02 69 de 2a 3b 96 9f  |e..=I.....i.*;..|
-00000090  21 b4 5d de 2b b6 c5 03  ec ab 79 35 eb da 8b 1f  |!.].+.....y5....|
-000000a0  f8 c4 58 7c d1 af 3d 6e  f9 73 63 2b dc 2e a5 4f  |..X|..=n.sc+...O|
-000000b0  88 93 24 5e d7 2a ab 0a  a5 0f bf 5d 2d 74 9c 19  |..$^.*.....]-t..|
-000000c0  3a 97 88 f7 17 25 ad 6a  81 3a f1 e3 bb 4c 7a b6  |:....%.j.:...Lz.|
-000000d0  4c b0 f3 25 e5 66 06 14  b0 a3 3d 3a 25 36 4c e1  |L..%.f....=:%6L.|
-000000e0  62 25 fc ac 22 7b 25 0d  f9 5f 5b a6 1b 7f b9 14  |b%.."{%.._[.....|
-000000f0  4d 71 81 6b de 9d 6a 40  80 ba 88 20 60 c6 e2 50  |Mq.k..j@... `..P|
-00000100  c6 a6 3d 01 ee 04 dc ad  3c 95 a7 ef a7 dd 3a 6c  |..=.....<.....:l|
-00000110  0f f2 c2 c2 e0 fc 3c d2  75 88 ad 1a 23 94 2a 69  |......<.u...#.*i|
-00000120  28 66 c2 8a 5c 34 69 da  cc 5d 13 dd 86 fc 66 13  |(f..\4i..]....f.|
-00000130  de c2 c6 86 6d 4a b4 ea  b0 99 61 38 72 1e 7f 36  |....mJ....a8r..6|
-00000140  df 32 4b a7 12 23 8f f3  d1 8d d7 2f d1 65 67 4f  |.2K..#...../.egO|
-00000150  10 07 03 6a b2 87 aa a4  b0 41 c9 20 f4 84 5e b7  |...j.....A. ..^.|
-00000160  5e 4d 47 d4 7f 6c 8d 2e  a5 bb 7d 07 1b 5b e5 50  |^MG..l....}..[.P|
-00000170  5d 27 c0 8b f8 5e a7 a8  ef d7 f3 b0 6d 07 7a 9b  |]'...^......m.z.|
-00000180  1d 54 5a 18 c7 4f 6f b8  92 44 16 ec 92 43 1a 1a  |.TZ..Oo..D...C..|
-00000190  a8 d0 a3 40 25 b0 ff 35  9c b7 4c f9 cd 06 59 a6  |...@%..5..L...Y.|
-000001a0  25 ca 4a b7 34 31 0a 23  29 3a 09 8b 7b 05 15 b0  |%.J.41.#):..{...|
-000001b0  67 ae 1b 8b f4 67 16 e0  c1 67 a1 58 09 c9 10 f0  |g....g...g.X....|
-000001c0  f0 62 02 52 14 6d 02 3d  e6 ab 16 fb 7f 38 69 7c  |.b.R.m.=.....8i||
-000001d0  d1 f3 db 69 3c cd 78 28  b2 fa 94 1c a0 2f b7 bb  |...i<.x(...../..|
-000001e0  31 4f f6 56 2a 98 5a d1  bf 5d e4 0d ec 8f 47 42  |1O.V*.Z..]....GB|
-000001f0  62 a6 59 39 77 d8 bd 11  71 64 b4 2b 65 2a 10 5d  |b.Y9w...qd.+e*.]|
-00000200  46 51 bf 8d b6 13 df 61  b8 1e 37 ad fc c0 86 a9  |FQ.....a..7.....|
-00000210  b4 09 2f 33 8e 93 4a 5b  32 f4 f9 7d 01 a8 b8 09  |../3..J[2..}....|
-00000220  8e da 90 8f a7 fb 82 76  fd 6b 7e 93 57 13 e1 99  |.......v.k~.W...|
-00000230  cb b8 12 0a da c2 62 0e  0c 65 53 d4 5b 75 c2 22  |......b..eS.[u."|
-00000240  3f 91 5c e6 c4 12 48 78  c4 6d 2c 1f 45 dc a2 a1  |?.\...Hx.m,.E...|
-00000250  73 cf 69 97 8b 64 42 d5  22 06 de 04 4b 8c f5 5f  |s.i..dB."...K.._|
-00000260  d6 97 1a 73 4f 4e d2 55  e1 8d 8c 21 fd 7f 26 1c  |...sON.U...!..&.|
-00000270  53 9f 69 c9 01 11 be 4e  d0 ab 78 56 af bb 0a 0f  |S.i....N..xV....|
-00000280  73 cb c5 d2 07 4a 16 a0  71 9f dd 46 17 0e 86 5e  |s....J..q..F...^|
-00000290  e2 90 34 7d af b1 86 6c  e3 33 cf ff 2f bf ea 8e  |..4}...l.3../...|
-000002a0  62 7e 7f b9 f7 c4 1b 4c  61 b6 8d 6f a9 b4 56 27  |b~.....La..o..V'|
-000002b0  0a 0d fa d7 d9 ce 6a 1a  e3 4e 4d f8 04 c8 74 75  |......j..NM...tu|
-000002c0  07 6f 38 96 c7 04 df a4  e0 6a 08 c5 5b 93 b7 c1  |.o8......j..[...|
-000002d0  fb 4d 4f 01 67 3c 8b 03  93 f7 46 c2 db 2f 41 2d  |.MO.g<....F../A-|
-000002e0  e1 d6 dd 39 d5 0c dc 6a  10 c2 50 fe 34 64 79 9a  |...9...j..P.4dy.|
-000002f0  5e 88 35 89 16 03 03 00  bc d1 42 6c 11 23 45 dd  |^.5.......Bl.#E.|
-00000300  41 9e 81 0a 3d d1 c1 99  6f 91 b5 16 96 e6 d3 eb  |A...=...o.......|
-00000310  9b 8f c3 30 14 7f 19 d5  9a fa ea 9c de 53 23 7c  |...0.........S#||
-00000320  d8 49 d2 c5 e7 7c ff 96  22 0a 57 fc 11 ed b9 ca  |.I...|..".W.....|
-00000330  2e 18 a5 30 7e 3a d2 86  70 de 48 28 83 a1 3b 65  |...0~:..p.H(..;e|
-00000340  67 b9 2e 89 87 92 0e eb  b5 70 1d 36 7b 98 4b 8e  |g........p.6{.K.|
-00000350  12 49 db 85 18 dc e1 f4  51 a9 bb e4 5c ae 56 31  |.I......Q...\.V1|
-00000360  c1 56 84 bb e5 42 ec d1  41 e7 a7 4e 08 d7 5f 1d  |.V...B..A..N.._.|
-00000370  67 9a ed 10 b6 80 ff ea  36 70 ac a0 a9 ec 4a e3  |g.......6p....J.|
-00000380  37 ae bf f3 bd a9 aa 3f  b0 14 f6 0b 05 18 09 dd  |7......?........|
-00000390  29 b4 97 55 88 24 59 ce  5b 42 e2 b5 1f 04 76 f3  |)..U.$Y.[B....v.|
-000003a0  f1 c0 49 7d 47 ef 5e 6c  c3 ed 30 2c a0 a1 df c6  |..I}G.^l..0,....|
-000003b0  12 13 22 8b 65 16 03 03  00 4a 3e 6c f8 63 5b 93  |..".e....J>l.c[.|
-000003c0  f0 c6 3a 58 e0 6c 6b 70  46 d0 be 6f 13 34 7a 30  |..:X.lkpF..o.4z0|
-000003d0  e6 e4 b2 fd 39 ee 79 b1  7e 73 5e 9b 2d d9 3f 4f  |....9.y.~s^.-.?O|
-000003e0  61 d5 53 37 79 57 15 a3  3a 7c b7 02 cc 76 25 1d  |a.S7yW..:|...v%.|
-000003f0  96 8b dd 9e 32 8b 1a 9e  37 b1 1a b8 f2 4f ef 3c  |....2...7....O.<|
-00000400  78 e1 b9 07 16 03 03 00  14 bf da c1 d4 16 fd 48  |x..............H|
-00000410  a9 ad 59 6d 8c dc e1 6c  fd 73 ca 9c 1b           |..Ym...l.s...|
+00000000  16 03 03 00 81 2e c9 cd  ad df 75 cf b6 8d 7f 8c  |..........u.....|
+00000010  c6 bb 5b e6 2b 40 a0 36  45 13 ae 93 f1 04 bf f3  |..[.+@.6E.......|
+00000020  62 bd c8 62 d9 cf 05 a3  4c e9 37 af 35 a6 83 8e  |b..b....L.7.5...|
+00000030  71 46 b8 2a 5b 02 3b 81  d5 15 b8 17 72 c4 1e 00  |qF.*[.;.....r...|
+00000040  78 d9 4a 04 a7 b3 5b 80  bd 1f 88 ba fa 22 b5 0e  |x.J...[......"..|
+00000050  ca 44 55 27 c0 67 ce 37  4c 9a 9a d7 77 da 58 35  |.DU'.g.7L...w.X5|
+00000060  83 b3 39 90 8d e2 7f 08  2e cc 5a 8e 5e a8 c3 bb  |..9.......Z.^...|
+00000070  db e5 a2 56 56 04 37 13  f3 b1 71 2d ea 0a 56 00  |...VV.7...q-..V.|
+00000080  6e 8d 8b 20 79 30 16 03  03 02 69 76 4b a4 c6 5e  |n.. y0....ivK..^|
+00000090  0a a2 3c 89 24 f6 93 94  25 4e 0b 8a d2 33 2f 03  |..<.$...%N...3/.|
+000000a0  ab 20 22 33 ad 84 6d aa  31 6b 5a 10 0e 42 1b dd  |. "3..m.1kZ..B..|
+000000b0  35 9b a0 dc 31 f8 65 91  c4 14 78 2e 74 2e 1d 46  |5...1.e...x.t..F|
+000000c0  3a 66 41 f0 a3 9a 4e ae  bc 9b 55 f9 d1 9c c5 6e  |:fA...N...U....n|
+000000d0  38 24 19 15 fb e6 c3 85  de ef f0 97 a2 a1 db ed  |8$..............|
+000000e0  b8 d0 05 ae 93 77 d7 45  50 a5 4e 8a 83 84 07 fb  |.....w.EP.N.....|
+000000f0  3a 80 c6 69 3c 6e b2 e3  e0 97 f7 03 93 76 dd 32  |:..i<n.......v.2|
+00000100  0c 5d a2 e6 1f 82 90 8b  dd 93 06 ef eb b7 e0 74  |.].............t|
+00000110  1a 7d 8f 37 c2 c1 41 9c  30 74 ca 37 17 5e 71 a0  |.}.7..A.0t.7.^q.|
+00000120  cb d6 00 47 9d 14 93 aa  fe 57 56 10 ae 88 13 65  |...G.....WV....e|
+00000130  f4 6c 20 4e f9 14 87 73  36 5e d5 20 93 34 db 87  |.l N...s6^. .4..|
+00000140  e7 f8 84 6e 36 9d 60 20  b5 8f 47 33 84 94 22 e1  |...n6.` ..G3..".|
+00000150  5d c6 1c 35 39 61 71 47  90 a9 b4 c6 5e 31 58 d1  |]..59aqG....^1X.|
+00000160  40 d8 22 22 23 c2 53 e3  75 1f 98 1c cc 7f 2d 11  |@.""#.S.u.....-.|
+00000170  31 5e 49 a1 2c d9 c8 db  6e 4e 9d da 57 e1 c9 32  |1^I.,...nN..W..2|
+00000180  03 6c f0 9b df c2 03 d5  b7 e2 04 77 e8 87 bc 14  |.l.........w....|
+00000190  73 66 b0 fb d1 d6 26 0c  36 90 2c 20 43 16 c6 68  |sf....&.6., C..h|
+000001a0  6c c0 ee be 2c da 6f 4f  95 1e cf a0 31 e8 40 48  |l...,.oO....1.@H|
+000001b0  88 61 26 7b 53 5b 42 14  2a 89 a3 1e 03 01 16 9d  |.a&{S[B.*.......|
+000001c0  41 6d de 60 75 1d 36 12  cd 16 8b 1c 93 da 17 79  |Am.`u.6........y|
+000001d0  4b d2 1d 78 64 da 6c cc  5c 7c e3 f9 4d 70 a2 07  |K..xd.l.\|..Mp..|
+000001e0  b4 24 33 de 19 bc d2 1a  43 42 f4 26 8b c0 81 e4  |.$3.....CB.&....|
+000001f0  a3 32 97 09 ec 6f 39 d7  ca c9 c5 ee 38 fd 91 dd  |.2...o9.....8...|
+00000200  c4 dc 3c 53 38 60 c7 b6  60 c6 a9 ff ae 81 e9 8c  |..<S8`..`.......|
+00000210  ea 49 19 3f fe 0e 8e b8  e6 7c ec 4b 63 66 d8 7a  |.I.?.....|.Kcf.z|
+00000220  82 51 7f 24 51 ae ad 91  5d 0e 2c aa ee fa 9f d3  |.Q.$Q...].,.....|
+00000230  22 1a 8b 8d 12 48 bb 3a  7c ea f0 09 af 1a 7e 7e  |"....H.:|.....~~|
+00000240  47 74 b9 b9 1f 97 8e 64  62 52 ae 08 d5 f1 13 cb  |Gt.....dbR......|
+00000250  51 64 b0 6a 33 1f 48 78  c1 91 91 91 a7 75 29 cb  |Qd.j3.Hx.....u).|
+00000260  32 60 96 d4 27 3f a4 8f  12 e9 5d 79 4d fd f9 19  |2`..'?....]yM...|
+00000270  b8 f7 39 d8 53 e5 45 96  0f c6 4f f2 27 c6 e6 07  |..9.S.E...O.'...|
+00000280  40 47 29 94 b9 6a 38 9e  24 bf 9e 92 f6 67 3f e3  |@G)..j8.$....g?.|
+00000290  48 0f 3b 3a d7 7b 14 4e  34 a3 8a 25 b4 a2 d6 15  |H.;:.{.N4..%....|
+000002a0  3f 38 9e ba fa 7e 33 fd  a4 4c ed e7 58 93 65 7d  |?8...~3..L..X.e}|
+000002b0  90 48 fc 70 7e 10 a5 d0  0a ec 96 c4 cf 26 ae 94  |.H.p~........&..|
+000002c0  d7 3f 92 40 2f ad ed c8  bb 69 b1 3e 0b ab 4f 4e  |.?.@/....i.>..ON|
+000002d0  73 91 a6 05 2b a7 89 e8  63 28 39 51 53 8d 2c 5e  |s...+...c(9QS.,^|
+000002e0  c8 64 90 c3 b7 2d ee 00  aa 7f 38 ca 57 ab b8 aa  |.d...-....8.W...|
+000002f0  93 12 af c5 16 03 03 00  bc 0e 58 31 64 e6 68 e6  |..........X1d.h.|
+00000300  10 81 2f 79 e3 49 3a d9  cc 70 09 7e b6 b5 61 c4  |../y.I:..p.~..a.|
+00000310  92 16 22 d0 e5 af b8 b8  91 2e 72 7c cf 95 cb ef  |..".......r|....|
+00000320  14 81 73 33 34 98 65 1b  69 db 2c 9d eb 1c ce be  |..s34.e.i.,.....|
+00000330  1f ce 48 b4 22 8d f0 6e  48 21 8e aa af 83 43 d2  |..H."..nH!....C.|
+00000340  65 54 0f 57 6b ce b1 24  ef 09 bf 7f 23 92 35 07  |eT.Wk..$....#.5.|
+00000350  55 2f 2f e7 b7 d7 72 d2  7c 5f 71 d6 20 9a 68 e8  |U//...r.|_q. .h.|
+00000360  1b 90 0b 13 f7 37 e2 35  0d fc 04 ea 32 50 2d 04  |.....7.5....2P-.|
+00000370  72 1a db d9 71 e1 4e d1  76 7c c3 f5 22 97 92 c5  |r...q.N.v|.."...|
+00000380  61 19 e0 40 b1 14 de 37  9d 8e e7 fd fe 2b 28 97  |a..@...7.....+(.|
+00000390  91 77 8f a7 d4 b1 db bc  a2 78 65 5c a8 8d 41 21  |.w.......xe\..A!|
+000003a0  0e 56 6b ac 0b da a9 dd  b1 51 84 19 20 ab e5 eb  |.Vk......Q.. ...|
+000003b0  f2 52 8d 48 a2 16 03 03  00 4a 69 44 32 65 c2 09  |.R.H.....JiD2e..|
+000003c0  9c c1 d6 66 06 29 c3 a6  c3 10 2e d9 9e d6 0a d3  |...f.)..........|
+000003d0  06 a3 d2 d2 67 52 bd 19  26 a8 ef 08 ed 9f 2b e8  |....gR..&.....+.|
+000003e0  96 ea 08 b7 46 a2 36 e3  c1 84 4b c2 a2 b5 34 9c  |....F.6...K...4.|
+000003f0  83 ea 94 51 e6 ca 9c 0b  e1 e3 86 13 b7 1b 1f 4e  |...Q...........N|
+00000400  ee a1 10 70 16 03 03 00  14 5a 1c c1 14 fd d9 ff  |...p.....Z......|
+00000410  e3 46 ac 89 3b b3 e1 8e  6b 90 41 44 1f           |.F..;...k.AD.|
 >>> Flow 9 (client to server)
-00000000  16 03 03 02 69 11 1e 53  9b b7 57 6d ea 89 bb 37  |....i..S..Wm...7|
-00000010  1b c6 01 bd 27 db fa 17  cc 5d 20 be ee 5b a9 64  |....'....] ..[.d|
-00000020  48 4e 4a 4c 82 65 8e 3d  42 d6 ce 5c a8 50 d4 fa  |HNJL.e.=B..\.P..|
-00000030  0f 02 b2 19 90 b5 4e ae  6c e9 d6 b7 b8 64 ca 0e  |......N.l....d..|
-00000040  09 2d a9 7b ab 0f b8 83  97 b6 e0 eb bf 03 5a 1c  |.-.{..........Z.|
-00000050  e7 16 31 67 30 46 60 26  df 19 cf 5f fa 40 36 43  |..1g0F`&..._.@6C|
-00000060  91 d5 7c 2f 5f 29 74 03  e0 90 cd 55 25 e5 1e fe  |..|/_)t....U%...|
-00000070  6b 13 ec 58 29 b0 f4 a3  b2 8d ba 4e 3b f1 11 d8  |k..X)......N;...|
-00000080  85 49 50 b9 e0 03 89 a1  0f da ce 57 83 aa 4a 8c  |.IP........W..J.|
-00000090  3b 15 d5 10 47 01 22 32  4f 78 87 69 4c bf a6 6e  |;...G."2Ox.iL..n|
-000000a0  d4 e6 a5 1e fa 5b ff b0  38 a5 fa 83 1d 45 c5 18  |.....[..8....E..|
-000000b0  72 65 91 6c 41 d2 21 be  5b 1d e9 f5 19 eb d0 5a  |re.lA.!.[......Z|
-000000c0  7e 0d 81 c9 ca f0 97 9e  cc 9b 5c 77 6b 9c 15 d3  |~.........\wk...|
-000000d0  bd 43 4d 42 e5 f9 82 a9  d6 f2 44 93 ae 74 a3 fd  |.CMB......D..t..|
-000000e0  c5 1f 15 13 a0 ea d2 f3  4c 4c ea 2d fe 3b 6e 7b  |........LL.-.;n{|
-000000f0  f4 11 f7 2e 7d 45 26 a0  d9 29 4e 4d ec 90 e2 3e  |....}E&..)NM...>|
-00000100  51 52 dd 6e e1 b5 77 b1  a2 f5 17 b5 34 7f e8 8f  |QR.n..w.....4...|
-00000110  38 9c d6 1c b5 6c 2d 99  00 a1 41 95 15 c5 e5 bf  |8....l-...A.....|
-00000120  c1 67 fb ea 53 6c a8 85  8c c4 a6 74 e3 dc f7 90  |.g..Sl.....t....|
-00000130  b8 cc 99 39 1a a1 c6 51  db 65 e9 b8 ad 2b 1f 35  |...9...Q.e...+.5|
-00000140  b5 90 ae f7 af c2 d0 a9  92 eb 63 21 24 4f 5e 62  |..........c!$O^b|
-00000150  ba 69 ce 1a c8 41 79 db  c0 6c ef bc cf 19 4a 2c  |.i...Ay..l....J,|
-00000160  e0 66 6e 72 97 2d 75 e5  ee 14 82 e8 26 98 fe c4  |.fnr.-u.....&...|
-00000170  8a 17 c4 fb 48 2a d7 7e  d9 3e 5b f9 d4 7d 0e da  |....H*.~.>[..}..|
-00000180  56 44 5e 33 9d 5f 97 ab  d1 60 a8 ee 3d 16 6a 2a  |VD^3._...`..=.j*|
-00000190  33 b1 7d e2 e6 86 cd 88  ac e1 48 49 4e 19 a2 b0  |3.}.......HIN...|
-000001a0  16 53 ec ff b8 a4 f7 35  2d a7 7a 04 86 66 42 52  |.S.....5-.z..fBR|
-000001b0  51 3d 21 62 c5 35 9c e5  cb f9 bf 7b d1 12 b0 18  |Q=!b.5.....{....|
-000001c0  7b 6f 88 d9 ef d2 1a 45  3e 51 ac 3e c8 87 8c 47  |{o.....E>Q.>...G|
-000001d0  08 d0 90 b5 66 f6 4e c3  75 74 68 c8 7d 14 3a 2b  |....f.N.uth.}.:+|
-000001e0  83 7d 12 78 37 9e 11 02  3d 63 ba 78 b6 ba 6d 26  |.}.x7...=c.x..m&|
-000001f0  30 b0 bf a9 23 1e 83 aa  3d a8 02 5b 77 5f 2a 95  |0...#...=..[w_*.|
-00000200  d0 b9 c8 22 a3 a9 fe b0  32 99 8a 46 67 10 b3 d9  |..."....2..Fg...|
-00000210  3e 84 02 ec a2 68 7e 69  db 51 99 37 ee 49 66 0b  |>....h~i.Q.7.If.|
-00000220  af e1 cd b0 25 74 dc ce  29 ed 70 1c 3a bb f2 99  |....%t..).p.:...|
-00000230  03 86 6d af 3f 78 4a 86  70 b8 85 15 02 91 be f6  |..m.?xJ.p.......|
-00000240  4f f2 73 98 00 c6 76 20  c2 19 c6 e9 6c d0 e5 09  |O.s...v ....l...|
-00000250  5c 12 c8 1c a1 3d b7 41  18 26 cb ea d0 92 61 53  |\....=.A.&....aS|
-00000260  06 7c f8 5e a8 27 de 76  4e 83 49 2a ab 82 16 03  |.|.^.'.vN.I*....|
-00000270  03 00 35 4f b7 51 7c c8  51 25 a4 58 de 8b 4a e2  |..5O.Q|.Q%.X..J.|
-00000280  97 cc 48 d0 4d be 9b 8a  44 3b 22 43 b9 82 a4 a5  |..H.M...D;"C....|
-00000290  76 38 0b ae 91 d3 20 75  18 50 f3 1b eb 11 fd 86  |v8.... u.P......|
-000002a0  4a 1a f1 e8 2a f8 e0 60  16 03 03 00 98 ae e6 1b  |J...*..`........|
-000002b0  b1 00 f9 14 93 55 be 63  ea 5b 5e d4 18 37 6b 14  |.....U.c.[^..7k.|
-000002c0  5c 8e fb 82 51 e1 57 24  b7 4a 8b 55 74 79 70 55  |\...Q.W$.J.UtypU|
-000002d0  de 33 82 14 0a 39 0d 91  92 9a 11 c0 4a dd 12 49  |.3...9......J..I|
-000002e0  ea 1a 41 df fd f2 4a 79  c3 0a d5 93 5c ea 82 ff  |..A...Jy....\...|
-000002f0  16 4a 20 91 25 34 5d 72  9d ea 0e 40 dd 6d 86 fd  |.J .%4]r...@.m..|
-00000300  e9 d1 d9 db 61 e6 62 17  6b 09 47 c4 a7 32 1c 22  |....a.b.k.G..2."|
-00000310  f6 e4 41 2a 3e 2b d0 c3  92 56 c5 b8 5f 6d 25 44  |..A*>+...V.._m%D|
-00000320  81 e7 1a ed 70 6a a6 94  89 d1 ad 8d d1 c0 df a2  |....pj..........|
-00000330  26 6f 20 0b 0e 51 15 dd  05 86 36 88 72 3f e1 5d  |&o ..Q....6.r?.]|
-00000340  da 9d d3 76 e4 14 03 03  00 11 52 70 cd 84 39 32  |...v......Rp..92|
-00000350  7c c0 58 53 9b 32 00 96  14 b6 57 16 03 03 00 20  ||.XS.2....W.... |
-00000360  98 94 aa 9f 77 71 42 3e  48 e8 74 8e 27 60 54 c2  |....wqB>H.t.'`T.|
-00000370  55 ac 52 99 37 21 f3 1e  30 93 5f 71 06 19 e5 1c  |U.R.7!..0._q....|
+00000000  16 03 03 02 69 c8 db 54  92 d3 ea 2f 24 47 f9 24  |....i..T.../$G.$|
+00000010  53 c1 d4 6a e8 dd 1d 71  d6 fb 2c 7e 3a 41 75 f6  |S..j...q..,~:Au.|
+00000020  0c 08 70 b6 f9 0a 12 4b  0d 3d 34 03 a9 36 9e f1  |..p....K.=4..6..|
+00000030  c7 93 dc 51 e4 15 3d fd  a7 67 28 24 32 fe ff d3  |...Q..=..g($2...|
+00000040  cd 69 d6 4a 5d 11 78 3b  aa 07 8d 1e c4 97 22 34  |.i.J].x;......"4|
+00000050  df 03 f2 37 fd 4f 76 c3  04 a6 a6 0f 35 1c 0f 13  |...7.Ov.....5...|
+00000060  7e 0a b9 5e 47 d2 9a 8c  d8 a3 f4 7a e4 92 5f 12  |~..^G......z.._.|
+00000070  a6 20 fb 51 16 af eb 55  d0 23 4e b5 f9 e8 cc 33  |. .Q...U.#N....3|
+00000080  bd d1 52 27 21 96 06 05  67 fa 68 0e ab 2c 84 05  |..R'!...g.h..,..|
+00000090  c9 97 6a db 69 57 a8 5c  55 a9 e1 cf 33 01 28 9a  |..j.iW.\U...3.(.|
+000000a0  76 09 64 a4 a3 31 36 13  72 27 0c 85 e9 59 47 27  |v.d..16.r'...YG'|
+000000b0  89 07 ee e2 e0 68 a6 f0  fa d5 c3 8b 2f 75 68 d0  |.....h....../uh.|
+000000c0  8e d8 fe ae 1d 0d af 0b  40 3d 9f ec 85 03 24 20  |........@=....$ |
+000000d0  c5 11 30 aa 25 ee 2c 86  42 ae 4f 0d 6b 18 70 1d  |..0.%.,.B.O.k.p.|
+000000e0  5f ae 1e cf 99 a7 0e c8  9b b3 63 58 cd b6 7d be  |_.........cX..}.|
+000000f0  01 43 96 37 87 45 5f 2f  aa 9c 12 48 ef 3b c8 d9  |.C.7.E_/...H.;..|
+00000100  60 20 26 69 68 56 48 aa  64 59 9e 41 ed 7e 8d c3  |` &ihVH.dY.A.~..|
+00000110  0f cd 0e 19 7a 76 89 95  f8 20 68 cd f9 81 e9 a0  |....zv... h.....|
+00000120  21 ff 60 e5 0f 6d dd 73  d2 19 1e 2a 76 f7 9a 46  |!.`..m.s...*v..F|
+00000130  5d d5 6b b2 19 28 c2 ac  9c e0 35 c8 d2 2a 53 fa  |].k..(....5..*S.|
+00000140  3e 58 9e f2 05 7e 6b ce  51 6d 3d 2a ce 2e 9b 59  |>X...~k.Qm=*...Y|
+00000150  aa d4 8d cc ad 1f 82 e7  ca 5a ef a6 87 d5 41 0b  |.........Z....A.|
+00000160  8d 27 6d 09 4d 40 c3 26  a3 a9 91 dd 1b 37 5d ff  |.'m.M@.&.....7].|
+00000170  8f c3 c7 b1 bf be f5 d1  19 4d 93 86 a7 5f 5e 8f  |.........M..._^.|
+00000180  14 34 82 50 76 25 42 04  b8 4b d3 da 15 ee 60 d1  |.4.Pv%B..K....`.|
+00000190  35 56 4c 63 0d ba 64 13  4f 3d 12 87 84 5a 45 41  |5VLc..d.O=...ZEA|
+000001a0  14 b6 6f 91 c4 b9 4f 97  c1 10 d6 3e b3 99 21 18  |..o...O....>..!.|
+000001b0  c3 91 82 e4 b6 91 3e bb  01 89 9a f0 60 ac 8e 7d  |......>.....`..}|
+000001c0  cf c2 f9 b4 4f da 40 e3  5e 83 a1 8f b4 fa 28 aa  |....O.@.^.....(.|
+000001d0  c9 ae 7b 8f 7d c9 d1 f8  7b b2 b5 3f 0a 9b 00 9e  |..{.}...{..?....|
+000001e0  1d fa 59 ff 39 b7 85 4d  2a b9 b8 67 03 df a0 f9  |..Y.9..M*..g....|
+000001f0  f1 7e 9d 27 1c 55 a9 76  44 9e f1 13 78 7d 34 4d  |.~.'.U.vD...x}4M|
+00000200  c9 23 07 e6 db 93 d7 70  3c 1b 5d 89 ed 8d 3d 43  |.#.....p<.]...=C|
+00000210  2e 89 f6 14 83 ff 87 db  26 a5 9a cd 98 5d 32 24  |........&....]2$|
+00000220  70 d2 e0 72 a7 6f a4 b4  2b 37 db 7e 39 4f d7 37  |p..r.o..+7.~9O.7|
+00000230  ea 68 b5 98 33 0e 23 21  3f 43 b3 ff 18 8e df 85  |.h..3.#!?C......|
+00000240  ba 15 48 3a fe 09 9b b6  27 40 d4 60 a8 3e 55 a3  |..H:....'@.`.>U.|
+00000250  75 c9 32 38 b5 21 46 ab  41 99 24 e6 09 3f 64 e6  |u.28.!F.A.$..?d.|
+00000260  09 40 cb 93 25 ab 1a 90  c7 d5 a6 40 36 a0 16 03  |.@..%......@6...|
+00000270  03 00 35 0f c7 e4 c3 16  c0 4f 7f 25 04 06 63 e7  |..5......O.%..c.|
+00000280  79 79 f9 4f c9 66 ca cd  ba e3 af 4a 50 a3 3d c3  |yy.O.f.....JP.=.|
+00000290  79 0c 71 d9 2f df 93 79  30 8f 6b 0f 54 f9 be 07  |y.q./..y0.k.T...|
+000002a0  f3 d6 9b c0 2a 3a 0a a1  16 03 03 00 98 b8 f1 fc  |....*:..........|
+000002b0  87 62 e9 6b 40 fd 50 ac  b7 fa 52 69 51 66 ae 9b  |.b.k@.P...RiQf..|
+000002c0  05 7e f2 38 73 27 d8 0c  2a 53 37 30 62 76 5d e9  |.~.8s'..*S70bv].|
+000002d0  fd 95 c6 14 d2 9d 34 13  e9 4c a5 7c c0 b6 e0 c4  |......4..L.|....|
+000002e0  97 ef 01 c0 f9 38 39 ee  17 c0 20 01 76 4f a7 10  |.....89... .vO..|
+000002f0  b0 45 9d c7 c3 cd a9 47  14 4a ed 00 1f 06 70 5b  |.E.....G.J....p[|
+00000300  f5 04 8b 77 ad af 1e 77  7a 9d cc fc a4 1f d2 8d  |...w...wz.......|
+00000310  8f e3 31 d3 3c de e6 85  f3 3d c0 ae 78 f7 22 c6  |..1.<....=..x.".|
+00000320  ec 2e a2 f0 5f ed 95 33  54 8c 89 35 c9 e4 25 4b  |...._..3T..5..%K|
+00000330  84 5e 31 83 04 d0 f1 67  69 73 8b 7f 24 ae e0 87  |.^1....gis..$...|
+00000340  6b f7 ba f0 23 14 03 03  00 11 7a c7 6a 32 2b 9b  |k...#.....z.j2+.|
+00000350  25 c2 d2 ee 37 b2 8d 7b  f2 90 6d 16 03 03 00 20  |%...7..{..m.... |
+00000360  c1 1c 9d 18 a9 41 92 fc  05 19 93 7c 7e 2f b2 39  |.....A.....|~/.9|
+00000370  8c 76 4b 29 5a 67 cc f5  55 9f c0 e3 8f ad ee 3c  |.vK)Zg..U......<|
 >>> Flow 10 (server to client)
-00000000  14 03 03 00 11 45 8e f9  74 04 d0 44 c6 94 80 60  |.....E..t..D...`|
-00000010  c1 50 7d b2 64 76 16 03  03 00 20 d5 65 8a b9 26  |.P}.dv.... .e..&|
-00000020  54 70 26 de c6 8a 8f 61  a3 b1 9e 8b 49 40 f7 24  |Tp&....a....I@.$|
-00000030  4f 75 e0 94 e6 e7 68 51  38 8a 37 17 03 03 00 19  |Ou....hQ8.7.....|
-00000040  42 7e 5a e2 46 7b ba 7d  0d 07 20 2a c0 56 fe aa  |B~Z.F{.}.. *.V..|
-00000050  01 eb ca d2 29 1d ff 85  10                       |....)....|
+00000000  14 03 03 00 11 49 66 13  ec 09 83 0d 47 82 45 61  |.....If.....G.Ea|
+00000010  06 14 cc f5 da 41 16 03  03 00 20 34 d4 0c bd 86  |.....A.... 4....|
+00000020  6d ef a9 b6 97 68 e6 88  84 ed 1c 9d a1 8d 2b c9  |m....h........+.|
+00000030  2f 45 75 5b e5 6a 08 72  71 a9 c6 17 03 03 00 19  |/Eu[.j.rq.......|
+00000040  e8 83 4c f5 19 ea d1 ef  e3 27 25 f9 af d2 f0 a6  |..L......'%.....|
+00000050  b3 62 15 66 ec 72 ce 4e  e2                       |.b.f.r.N.|
 >>> Flow 11 (client to server)
-00000000  15 03 03 00 12 1d 01 c7  d5 d5 d1 ce 8c 52 15 8f  |.............R..|
-00000010  75 1e 97 fa 38 5c 65                              |u...8\e|
+00000000  15 03 03 00 12 2e 39 ba  ca ad 7c a9 ae 3f 6a 78  |......9...|..?jx|
+00000010  b6 31 d2 d0 4e 1f dc                              |.1..N..|
index 006e2d7cef8adb395f9c9d5168386b6323147a10..20aa6c9fcf9d525a86989e23043f996260241505 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 47 d0 f5 d9 f0  |....Y...U..G....|
-00000010  59 d1 bf 28 d0 39 36 c0  bc d1 25 fd 5a 63 18 06  |Y..(.96...%.Zc..|
-00000020  1e 8a 5c a6 6f d0 f9 b4  02 23 e1 20 df a0 2a 74  |..\.o....#. ..*t|
-00000030  1a 52 8b d9 90 01 c2 86  69 12 b8 13 58 aa 59 b0  |.R......i...X.Y.|
-00000040  66 79 ff 01 9b 9a 72 1c  a6 83 e6 91 cc a8 00 00  |fy....r.........|
+00000000  16 03 03 00 59 02 00 00  55 03 03 68 39 1d 0e 5a  |....Y...U..h9..Z|
+00000010  22 ba 13 5f b6 c1 52 5d  13 e5 07 18 aa ec 24 0f  |".._..R]......$.|
+00000020  c9 56 3a 83 a1 32 a1 7f  02 e8 7b 20 31 e2 f8 c4  |.V:..2....{ 1...|
+00000030  5b c2 57 9a 1d a4 6f a7  9c 1c 93 b1 9f 19 c3 cb  |[.W...o.........|
+00000040  e1 73 87 1b a8 88 d9 4c  67 2f 44 aa cc a8 00 00  |.s.....Lg/D.....|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 59 0b 00 02 55 00  02 52 00 02 4f 30 82 02  |..Y...U..R..O0..|
 00000070  4b 30 82 01 b4 a0 03 02  01 02 02 09 00 e8 f0 9d  |K0..............|
 00000290  77 8d 0c 1c f1 0f a1 d8  40 83 61 c9 4c 72 2b 9d  |w.......@.a.Lr+.|
 000002a0  ae db 46 06 06 4d f4 c1  b3 3e c0 d1 bd 42 d4 db  |..F..M...>...B..|
 000002b0  fe 3d 13 60 84 5c 21 d3  3b e9 fa e7 16 03 03 00  |.=.`.\!.;.......|
-000002c0  ac 0c 00 00 a8 03 00 1d  20 20 97 bd 85 2f cb 85  |........  .../..|
-000002d0  be a8 9c e3 ae 6b 23 a5  5b 18 65 5c f5 cc 24 2b  |.....k#.[.e\..$+|
-000002e0  34 2c 5f c8 4d e9 86 35  0b 08 04 00 80 d2 b6 ee  |4,_.M..5........|
-000002f0  86 76 aa 1d 9c 1c ee ef  0e 59 63 1d ec f1 cf a1  |.v.......Yc.....|
-00000300  f3 5b 6d da 99 9c 40 07  bf 28 ad 72 cd 80 6c 9d  |.[m...@..(.r..l.|
-00000310  bf a2 20 33 2d d0 67 ef  90 28 88 2b d0 8e c6 9d  |.. 3-.g..(.+....|
-00000320  87 7a 18 8f 80 ce 25 92  13 8d ef 38 0a 14 f9 67  |.z....%....8...g|
-00000330  88 94 ef af 97 d2 21 90  9e 24 2f af 1e bb fa 10  |......!..$/.....|
-00000340  4c a7 9f f5 27 63 e6 d8  1a 86 53 c6 3c 15 a8 6c  |L...'c....S.<..l|
-00000350  b9 bc 8f c4 38 1a 4b 34  36 ec af b2 1e d0 bf 58  |....8.K46......X|
-00000360  74 36 ad fb e4 f0 fd 9d  6d 01 cf 51 6c 16 03 03  |t6......m..Ql...|
+000002c0  ac 0c 00 00 a8 03 00 1d  20 57 22 18 98 ed 7f 12  |........ W".....|
+000002d0  e7 e3 83 6b 42 82 ff 49  54 f8 0b 7d 93 3d 11 42  |...kB..IT..}.=.B|
+000002e0  67 cf 89 47 77 31 c5 59  4a 08 04 00 80 69 d4 13  |g..Gw1.YJ....i..|
+000002f0  f8 1c 68 9d 40 10 c8 aa  e6 44 0e 14 b9 38 6e ca  |..h.@....D...8n.|
+00000300  a9 50 05 4a ce a0 03 ea  02 92 e4 5a ed 42 6f 70  |.P.J.......Z.Bop|
+00000310  e1 c1 99 49 a4 34 20 6b  5e 14 e8 a1 d3 27 ff 0d  |...I.4 k^....'..|
+00000320  0c d7 47 49 1e 8f 8a 3a  62 1d c9 81 3c 5f a3 16  |..GI...:b...<_..|
+00000330  16 34 a0 53 a7 01 1d 09  f7 d9 d4 62 b2 0a 1c 1f  |.4.S.......b....|
+00000340  b2 e5 24 1b 7e 78 35 43  ed 47 f8 62 53 2d 04 ec  |..$.~x5C.G.bS-..|
+00000350  81 b5 68 11 3a 2d ee 88  ef 86 eb 71 d0 5e 31 42  |..h.:-.....q.^1B|
+00000360  57 6d b6 f2 be 32 4c 38  f8 2a 93 2f db 16 03 03  |Wm...2L8.*./....|
 00000370  00 04 0e 00 00 00                                 |......|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 25 10 00 00  21 20 2f e5 7d a3 47 cd  |....%...! /.}.G.|
 00000010  62 43 15 28 da ac 5f bb  29 07 30 ff f6 84 af c4  |bC.(.._.).0.....|
 00000020  cf c2 ed 90 99 5f 58 cb  3b 74 14 03 03 00 01 01  |....._X.;t......|
-00000030  16 03 03 00 20 e8 d5 df  da 49 9a 94 10 30 90 81  |.... ....I...0..|
-00000040  c6 19 54 d4 0d e2 0d e0  d9 a3 c0 21 7f a6 d1 cc  |..T........!....|
-00000050  ea 75 2e 17 01                                    |.u...|
+00000030  16 03 03 00 20 2a 03 0a  58 36 31 ec 26 df e5 7c  |.... *..X61.&..||
+00000040  88 b5 d1 f7 6d fc 4b 0a  91 54 4a e7 8c 83 a3 54  |....m.K..TJ....T|
+00000050  0a 10 5b ff 69                                    |..[.i|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 20 f3 92 03 fb 7b  |.......... ....{|
-00000010  0f 32 0b 5b dd 9e eb c3  26 2c 92 4d 58 35 a8 96  |.2.[....&,.MX5..|
-00000020  74 d6 d8 0f 61 b2 7d b6  8d ec e6                 |t...a.}....|
+00000000  14 03 03 00 01 01 16 03  03 00 20 27 b0 69 0c 67  |.......... '.i.g|
+00000010  c7 3a ec c1 aa 02 20 cf  f9 e8 22 86 3b d3 e1 4f  |.:.... ...".;..O|
+00000020  bc fd 04 40 19 77 bf bd  38 28 56                 |...@.w..8(V|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 16 ab 69 44  d0 fe 95 93 ae f9 1b d7  |......iD........|
-00000010  33 6c 59 a5 41 cc d2 1b  ca 2c 63                 |3lY.A....,c|
+00000000  17 03 03 00 16 8a 2c 24  1b b8 53 01 54 c8 bd f3  |......,$..S.T...|
+00000010  e1 ec a9 ab 83 a0 66 a9  29 1c 4e                 |......f.).N|
 >>> Flow 6 (server to client)
-00000000  16 03 03 00 14 99 96 92  c4 82 c8 27 77 a6 f4 ca  |...........'w...|
-00000010  e5 5b ff 78 bc 54 b6 d7  cd                       |.[.x.T...|
+00000000  16 03 03 00 14 c5 e3 03  06 89 d8 47 1a 66 18 0e  |...........G.f..|
+00000010  8d 36 c5 f4 30 80 7e 72  a2                       |.6..0.~r.|
 >>> Flow 7 (client to server)
-00000000  16 03 03 01 16 d9 6a 26  33 e5 d8 df 32 d1 f5 84  |......j&3...2...|
-00000010  1f 37 7f 07 6a ae be 20  84 20 dc 28 31 8e 46 32  |.7..j.. . .(1.F2|
-00000020  0b 96 c8 22 28 fb 98 d9  8e 6f 6d 97 66 55 e2 1e  |..."(....om.fU..|
-00000030  b5 b8 e4 9b 52 25 28 c2  72 cb 9e 14 4c ba 58 6c  |....R%(.r...L.Xl|
-00000040  3b 33 da 56 db fe 14 d3  4c b4 ce a9 57 64 ae 4e  |;3.V....L...Wd.N|
-00000050  5f c5 a7 e6 f4 01 51 d7  81 f4 1d ca fa 3f 86 e7  |_.....Q......?..|
-00000060  9f 64 28 6e 3f e4 ef 79  77 20 64 45 ed a2 16 e1  |.d(n?..yw dE....|
-00000070  b4 63 99 9f 62 6d b7 6d  f4 ad 1f fe d9 de 00 84  |.c..bm.m........|
-00000080  4b bb 0c bc c8 82 a8 1d  8a ac f6 10 2d 5d d4 c7  |K...........-]..|
-00000090  37 f8 fc 89 24 ea c4 b8  87 f4 f4 f0 4b cd db e2  |7...$.......K...|
-000000a0  15 03 95 1e c1 10 7c e8  6d 99 6c e0 bc e1 0a a5  |......|.m.l.....|
-000000b0  d8 36 eb 59 93 6d 1c 96  1c 61 1b 11 36 04 58 6b  |.6.Y.m...a..6.Xk|
-000000c0  c5 b0 fb 8e 9f 21 4a 25  a1 59 ee 5d 1b e3 e3 98  |.....!J%.Y.]....|
-000000d0  71 0a d8 3f 18 f2 b2 1c  6f ec 6d 87 13 b9 d3 25  |q..?....o.m....%|
-000000e0  53 c1 00 78 be 99 82 f6  27 05 24 01 10 1c 59 19  |S..x....'.$...Y.|
-000000f0  94 6a af 7e e5 ae c5 03  14 04 e2 fe 5e 59 e8 e0  |.j.~........^Y..|
-00000100  45 3d af c0 40 ea 84 0a  13 9c d3 0f d4 69 3f 3e  |E=..@........i?>|
-00000110  97 83 ac b5 b9 07 56 9a  19 44 ca                 |......V..D.|
+00000000  16 03 03 01 16 7e eb a3  b5 ea 58 e3 4a 26 35 7d  |.....~....X.J&5}|
+00000010  54 15 93 74 e8 e4 63 34  38 d9 e0 02 3d 28 f8 98  |T..t..c48...=(..|
+00000020  0f 24 6b ca 08 7f b6 77  68 ec 85 c3 4a 6b 69 c3  |.$k....wh...Jki.|
+00000030  8d 8e 1b 8b 41 11 9b 0d  d1 c8 99 2b c9 d2 4c f1  |....A......+..L.|
+00000040  fd 82 e5 35 ba a3 3b f3  6d 47 82 45 08 e7 02 bb  |...5..;.mG.E....|
+00000050  10 a6 7b 76 83 78 e0 aa  5a 78 24 59 1c db ae a3  |..{v.x..Zx$Y....|
+00000060  37 20 b3 12 98 48 68 d3  b3 72 9f 4f d4 de 50 b4  |7 ...Hh..r.O..P.|
+00000070  4a c1 37 93 e0 55 ae e8  37 2a 40 de ac 30 e1 1d  |J.7..U..7*@..0..|
+00000080  f0 03 19 8c af 77 f5 26  98 af a8 a8 d2 72 6c 68  |.....w.&.....rlh|
+00000090  75 00 32 10 e6 3f 91 a8  24 a7 d8 05 23 04 52 23  |u.2..?..$...#.R#|
+000000a0  e7 e6 83 ac 37 1b 36 a7  ca d4 7e d5 21 4c ab 38  |....7.6...~.!L.8|
+000000b0  23 cb 7c a9 f4 66 26 5e  7f 3e d6 ab 7a ac 34 38  |#.|..f&^.>..z.48|
+000000c0  95 16 df e2 e4 cf 3a 62  82 78 cb 71 32 06 6d 07  |......:b.x.q2.m.|
+000000d0  84 91 0c e9 d0 63 88 9e  d1 b5 f0 fb 43 2b 07 0b  |.....c......C+..|
+000000e0  32 d7 20 af b8 76 17 da  ee cc e6 03 bb 7a 0b f2  |2. ..v.......z..|
+000000f0  61 4f db 7f a3 66 b0 05  a8 88 b8 0b b3 6e 9c df  |aO...f.......n..|
+00000100  48 8b 7e eb 42 cd ea eb  1d bb 63 a0 e4 ee df 21  |H.~.B.....c....!|
+00000110  20 67 11 26 dd f1 47 1b  15 2b a0                 | g.&..G..+.|
 >>> Flow 8 (server to client)
-00000000  16 03 03 00 81 4b d8 09  ef 6a 5b a2 c2 e0 2c b3  |.....K...j[...,.|
-00000010  fa e9 21 b3 64 c7 51 8d  d4 14 14 ba 7b 2f f8 1a  |..!.d.Q.....{/..|
-00000020  e9 f8 7a 69 8b 0b b4 5f  26 c5 b6 2e dd c9 90 04  |..zi..._&.......|
-00000030  7d af fd 56 f7 9a 0d 56  09 6c 74 48 49 74 90 71  |}..V...V.ltHIt.q|
-00000040  e1 ee 66 4c 1a da 66 43  50 fa 94 2c 84 21 10 f0  |..fL..fCP..,.!..|
-00000050  00 85 a7 c2 ea 73 19 52  b7 f2 2a e8 17 17 23 67  |.....s.R..*...#g|
-00000060  b6 80 d6 3f e0 a1 ed 81  66 89 0a 0d 48 9f 7f dc  |...?....f...H...|
-00000070  79 c4 27 9b c0 b8 68 ef  2a 5b ab df 8f 82 d6 ff  |y.'...h.*[......|
-00000080  84 38 f8 a4 f2 98 16 03  03 02 69 1f c6 1c dc 85  |.8........i.....|
-00000090  f1 66 8d 7f 7f aa 36 cd  c6 d4 cc 38 c8 8d 98 75  |.f....6....8...u|
-000000a0  92 d2 db b4 49 0c 09 cc  af e6 5b 07 64 76 34 c8  |....I.....[.dv4.|
-000000b0  41 49 85 5e b4 68 ac 35  04 72 00 70 33 f7 5f a7  |AI.^.h.5.r.p3._.|
-000000c0  84 40 34 03 2f 89 25 06  a1 50 dc ea d7 c4 29 57  |.@4./.%..P....)W|
-000000d0  f9 5b 57 63 14 02 1e 74  db 5d 02 cf c4 f1 89 f6  |.[Wc...t.]......|
-000000e0  6a 77 ce 87 5c 3a 61 b8  7d 02 f0 0e 6e 85 2a 51  |jw..\:a.}...n.*Q|
-000000f0  d8 ad 4a 9f 65 04 4c 00  d0 35 76 01 dc 03 cf ca  |..J.e.L..5v.....|
-00000100  6b 11 83 9e 70 33 82 f6  cb eb 4c da 44 76 89 ab  |k...p3....L.Dv..|
-00000110  d4 65 01 e6 08 7b 2a 3d  49 02 39 85 e8 ff 53 fd  |.e...{*=I.9...S.|
-00000120  d0 ce 2a f0 11 3c 02 8f  bd b8 2f ea 81 a1 64 10  |..*..<..../...d.|
-00000130  7b c2 8b 72 f3 32 7b 36  80 13 17 8b 83 dc ce 3a  |{..r.2{6.......:|
-00000140  29 44 06 66 c9 c3 83 cc  28 38 c5 02 7c 3d b6 30  |)D.f....(8..|=.0|
-00000150  55 07 a0 08 bb b3 e1 1e  a8 a5 74 60 51 be ee dd  |U.........t`Q...|
-00000160  aa 83 09 e9 f3 c7 a5 1e  20 fc 6d d5 82 af f5 b6  |........ .m.....|
-00000170  5b 23 dd 81 ce 78 5a 3c  92 c3 96 e1 aa e5 ad 24  |[#...xZ<.......$|
-00000180  da 89 41 44 8b 0b 42 df  e5 28 11 8e 9a e0 06 51  |..AD..B..(.....Q|
-00000190  80 93 15 31 ec 8c 3e 60  92 ab a5 ec 25 5c c5 10  |...1..>`....%\..|
-000001a0  ac 0f 01 1b c4 36 d5 f0  52 c7 0b f7 9b 40 9b c0  |.....6..R....@..|
-000001b0  18 ad 1c eb 49 ed 8e 27  b6 35 b4 20 e0 e6 df 04  |....I..'.5. ....|
-000001c0  69 d6 b5 56 04 30 d4 3d  b0 9f e6 21 66 e7 97 cb  |i..V.0.=...!f...|
-000001d0  2f bd b2 b2 c1 be 4b 4f  6e 88 60 a1 cb eb b4 86  |/.....KOn.`.....|
-000001e0  92 07 da 3c fa 8b 1a de  1c e7 6b c0 53 70 e7 ee  |...<......k.Sp..|
-000001f0  2f 70 4f e0 2a a3 b4 dc  af 64 4f 5a 44 f9 ff fc  |/pO.*....dOZD...|
-00000200  7f 2f 7e 22 13 47 ed f4  ec 0c fa 01 21 e3 c1 d6  |./~".G......!...|
-00000210  c7 53 f4 de 6c 91 c5 85  bd 3c a7 f3 d6 e7 f3 31  |.S..l....<.....1|
-00000220  13 59 b7 ee 0b f7 6a 88  76 94 ab 45 41 9e ab d7  |.Y....j.v..EA...|
-00000230  71 59 7e 45 ed 4d a0 12  4a 81 6a 15 05 a9 21 94  |qY~E.M..J.j...!.|
-00000240  40 f0 1d aa 7e b3 d4 6d  a6 ff 46 94 e6 d0 16 46  |@...~..m..F....F|
-00000250  60 ac c5 15 94 d5 f7 76  1e 8b 90 e6 17 ff 5c 21  |`......v......\!|
-00000260  d0 f9 98 25 0f 98 8b 6c  0f 2c 2a 92 0a f0 90 3d  |...%...l.,*....=|
-00000270  ef 9a 40 67 21 83 f7 5c  95 24 97 f6 45 51 81 4c  |..@g!..\.$..EQ.L|
-00000280  4b e1 64 0a f5 dd 02 fd  8d 21 d1 ef f8 96 70 4b  |K.d......!....pK|
-00000290  58 aa 3c f9 b1 f1 e9 fd  31 ea fc 68 4b c9 fa 79  |X.<.....1..hK..y|
-000002a0  6d 2e 54 d7 1c 9d 5d 62  fc 43 2f cb 6a 48 4d 2e  |m.T...]b.C/.jHM.|
-000002b0  07 71 7b f2 b3 e6 08 8b  13 ca f0 e9 c1 d2 cc 7a  |.q{............z|
-000002c0  9a 49 e9 7b aa e8 bb d2  cf 97 73 b8 9a 3f 8b 01  |.I.{......s..?..|
-000002d0  b9 cf c6 81 fd 99 fc c9  43 08 35 2c a0 fb 38 32  |........C.5,..82|
-000002e0  8b d8 5b d4 20 41 a0 57  e6 34 c1 d8 66 6e 16 e7  |..[. A.W.4..fn..|
-000002f0  78 4f e8 58 16 03 03 00  bc d3 91 f3 88 2f ec 1c  |xO.X........./..|
-00000300  da 94 cb b0 69 70 a2 41  4c fd 40 0d a0 97 01 34  |....ip.AL.@....4|
-00000310  35 83 e6 3f a8 b0 c9 26  8d f1 8a c1 f6 a6 ab a4  |5..?...&........|
-00000320  63 65 5a 10 38 d2 87 a7  8d ae ca 9e c6 23 7e c6  |ceZ.8........#~.|
-00000330  c8 45 37 e8 7c 4b 40 5a  5b 68 19 bb 36 83 81 41  |.E7.|K@Z[h..6..A|
-00000340  b2 fe 7c 39 7e 9f 95 3a  45 2e 9f 96 35 26 81 73  |..|9~..:E...5&.s|
-00000350  4d 0f c3 09 61 32 eb 64  4b 46 76 c1 0e ca cf 02  |M...a2.dKFv.....|
-00000360  6a f3 75 f3 bf aa b0 f8  43 e3 6b d1 c4 27 3e fe  |j.u.....C.k..'>.|
-00000370  06 a2 49 e4 bb 56 c5 c0  5d 36 81 06 97 ed ff a2  |..I..V..]6......|
-00000380  99 78 43 0a c5 20 df a3  ac b7 8f 61 a2 ff 48 66  |.xC.. .....a..Hf|
-00000390  ea c1 b6 57 38 fc 36 7c  dd 30 b5 ce 58 b1 18 82  |...W8.6|.0..X...|
-000003a0  e5 2a 54 d8 4d da f1 fc  98 06 97 43 d5 dc d9 3e  |.*T.M......C...>|
-000003b0  d4 f8 a3 76 9c 16 03 03  00 4a 78 c0 f2 02 60 a4  |...v.....Jx...`.|
-000003c0  8e 9a cd 31 30 e9 16 df  ce 98 bb 95 50 a0 05 48  |...10.......P..H|
-000003d0  6c c2 ce c5 e2 77 f2 4a  d0 45 80 97 98 d4 38 d1  |l....w.J.E....8.|
-000003e0  90 04 91 48 cb 52 40 d3  a4 cb 8d 68 dc 64 9c 07  |...H.R@....h.d..|
-000003f0  cb 8c b9 3b f8 44 fe 47  69 67 fb 2d ab 44 db d0  |...;.D.Gig.-.D..|
-00000400  58 55 83 81 16 03 03 00  14 51 82 e0 57 8e cb 4a  |XU.......Q..W..J|
-00000410  d4 59 6e 58 f7 6d 44 3f  f5 83 64 52 51           |.YnX.mD?..dRQ|
+00000000  16 03 03 00 81 60 70 d6  32 5a 0a 8f df ed cd f2  |.....`p.2Z......|
+00000010  d7 bf d0 da fd 53 63 65  bf f5 26 83 0c f5 6e e9  |.....Sce..&...n.|
+00000020  78 9b 03 7b 17 5f f4 d2  af 2a a3 85 13 92 be 00  |x..{._...*......|
+00000030  93 3f b3 f1 cb 04 aa 55  f8 ed c8 e6 9c 32 08 79  |.?.....U.....2.y|
+00000040  86 84 ef ac 72 bd 93 07  9c ca d2 e7 74 dd 51 a0  |....r.......t.Q.|
+00000050  6d 0e d3 32 3c 33 9d 58  aa 46 a9 ff 22 08 bc 2c  |m..2<3.X.F.."..,|
+00000060  de 81 aa a8 5a 3c f8 36  93 d3 12 06 79 61 1f 71  |....Z<.6....ya.q|
+00000070  5f 45 d7 99 b2 55 10 22  db 56 d9 39 64 57 ad c3  |_E...U.".V.9dW..|
+00000080  59 a9 bd cb f2 22 16 03  03 02 69 34 e7 f2 7a bc  |Y...."....i4..z.|
+00000090  0b 90 72 a3 3b 6b 38 a3  f8 7a 19 39 ff b4 d6 8c  |..r.;k8..z.9....|
+000000a0  c9 92 4f a3 23 1a f0 89  bb 01 e4 b2 24 f7 db 3d  |..O.#.......$..=|
+000000b0  f4 4b 02 75 d0 ca 3c ed  e8 d9 13 61 c5 61 4e 7c  |.K.u..<....a.aN||
+000000c0  fe b9 49 69 63 cc 23 5f  9b 23 85 ec 86 e5 17 28  |..Iic.#_.#.....(|
+000000d0  8a 1e 0c 45 e5 4d c2 be  66 92 47 88 28 ec 52 eb  |...E.M..f.G.(.R.|
+000000e0  72 e5 30 89 58 8d 15 2b  98 eb cd e2 18 7c 53 f2  |r.0.X..+.....|S.|
+000000f0  89 ba 71 a5 91 20 64 17  7c 56 f1 01 8a 52 17 66  |..q.. d.|V...R.f|
+00000100  ef d7 bc 5b ff 54 53 13  2e 80 53 4c 84 6d a2 20  |...[.TS...SL.m. |
+00000110  0f e6 3d 33 90 7a 5b 1a  50 29 ce 1e af 74 a5 b3  |..=3.z[.P)...t..|
+00000120  0e 29 c8 e5 c1 50 b6 5d  c8 bb e4 b5 f5 6b 04 a8  |.)...P.].....k..|
+00000130  24 a6 a8 cc 77 7c 72 d5  b1 f3 6a 1c 2e d7 7e e0  |$...w|r...j...~.|
+00000140  4c 46 3f 26 61 2e 54 7d  ab d8 d6 ec 1e b0 0d d1  |LF?&a.T}........|
+00000150  02 57 00 7f 29 aa d3 1d  a4 40 73 d7 21 12 76 58  |.W..)....@s.!.vX|
+00000160  7d 79 a5 c1 d2 57 63 48  0e 63 5f 24 49 8a 57 ba  |}y...WcH.c_$I.W.|
+00000170  26 1c 39 4a f8 b3 89 79  e2 be 4e 8e 37 ae 16 75  |&.9J...y..N.7..u|
+00000180  42 5e 2e 9b 14 d5 b3 06  5f b9 c8 f7 16 8f eb 1c  |B^......_.......|
+00000190  48 0a da 1e b3 4a 78 f7  f8 b4 35 bf 7d 3f c5 8d  |H....Jx...5.}?..|
+000001a0  fa 7d c0 b7 52 af d3 13  de 96 39 76 fd 49 80 55  |.}..R.....9v.I.U|
+000001b0  bb b3 0f 5b 0c 84 4d 8b  da 62 8a 20 4b a1 28 28  |...[..M..b. K.((|
+000001c0  3d 74 cc 34 9d 95 8e af  c0 05 a2 5c 73 9d 73 d8  |=t.4.......\s.s.|
+000001d0  6c 4e 77 25 c5 8c 22 07  c6 b9 55 47 0c b2 12 73  |lNw%.."...UG...s|
+000001e0  2e f5 95 f7 28 c3 e4 24  2c fd 05 ac e2 3e df 93  |....(..$,....>..|
+000001f0  5a 28 66 aa d4 86 8a 48  e2 c8 69 01 18 90 54 10  |Z(f....H..i...T.|
+00000200  67 80 a1 be a8 9a 7f f3  17 ee dc 83 06 7a 70 6c  |g............zpl|
+00000210  59 c2 2d 8f ff 79 a7 e5  e2 f2 f3 f3 5b 44 42 25  |Y.-..y......[DB%|
+00000220  a3 8c a0 83 07 5c f6 73  e9 bd f5 6b 86 89 b4 11  |.....\.s...k....|
+00000230  7b 9a 28 52 4f 55 70 4a  75 00 73 cc 84 fa 4a ef  |{.(ROUpJu.s...J.|
+00000240  f8 8a 8d f9 18 e2 bc 13  48 cb 80 4d 6f fc d7 23  |........H..Mo..#|
+00000250  3a 9c 6c fd 46 27 94 8a  3d 9d fb 17 f5 06 4d a1  |:.l.F'..=.....M.|
+00000260  18 75 a7 9b 08 f8 47 b5  52 b4 19 4b b7 0f a4 e0  |.u....G.R..K....|
+00000270  78 f8 8b a4 cc eb d3 85  e1 ad 21 29 0f c7 09 28  |x.........!)...(|
+00000280  3f 21 12 6c fd 76 05 13  10 a0 c1 ce ba 7c e8 6f  |?!.l.v.......|.o|
+00000290  e9 99 67 0a 9d 3a 7f f1  a6 8a 53 56 f1 09 22 21  |..g..:....SV.."!|
+000002a0  24 23 6e bc 77 fc 56 3b  31 15 58 1b e9 03 a1 bf  |$#n.w.V;1.X.....|
+000002b0  0a 06 a0 fb 47 77 b7 ad  01 db ee 6a bc a4 a1 77  |....Gw.....j...w|
+000002c0  6f 3e 70 84 4c a6 21 ec  ff fa f0 f0 68 ee 7d b1  |o>p.L.!.....h.}.|
+000002d0  e6 37 f1 1c aa 43 c7 b9  0e c4 52 7d 54 d8 f7 c5  |.7...C....R}T...|
+000002e0  16 21 99 89 cb 02 d0 54  b8 0e 91 2e 58 25 32 6e  |.!.....T....X%2n|
+000002f0  fa ae 62 c9 16 03 03 00  bc 0c 2f 7e 22 d8 7f 21  |..b......./~"..!|
+00000300  0c 1a ec e1 37 72 3f 03  1d cc 73 f9 63 95 cd 47  |....7r?...s.c..G|
+00000310  66 17 60 8c da b4 35 a2  44 b1 d8 d1 1c 98 5b 8b  |f.`...5.D.....[.|
+00000320  c8 9b c8 cb c4 15 0d 8d  08 1e 7c 3a 6b 20 3a f1  |..........|:k :.|
+00000330  d1 86 ae 08 bb fd 74 c5  62 9a 50 74 07 96 10 0e  |......t.b.Pt....|
+00000340  e0 e4 a4 da c4 9d d1 f4  15 97 7d 21 0f 6f cb 39  |..........}!.o.9|
+00000350  8e 4e 40 1a 2a 7f 15 88  94 52 bc fd 61 b8 37 d1  |.N@.*....R..a.7.|
+00000360  48 62 bc 53 a3 a6 62 ec  0e c3 1f 82 67 19 71 fa  |Hb.S..b.....g.q.|
+00000370  99 16 c3 cf d6 82 44 36  9e 0b f0 41 12 ca 7b 67  |......D6...A..{g|
+00000380  c3 a6 2d f7 13 14 0f d1  16 f9 2a 5a dd 43 45 c6  |..-.......*Z.CE.|
+00000390  c0 f4 17 36 64 11 fc ed  e6 66 b6 0c e2 3d fb 72  |...6d....f...=.r|
+000003a0  93 27 46 20 db 1b 24 f9  69 a0 c7 71 e2 27 6a 93  |.'F ..$.i..q.'j.|
+000003b0  36 73 71 10 bd 16 03 03  00 4a cb 15 91 9c 22 96  |6sq......J....".|
+000003c0  f0 c8 b9 4d 9a 6c b0 eb  1a c5 d4 06 12 89 44 1b  |...M.l........D.|
+000003d0  52 cd fb 32 3f 2c 25 f4  d3 88 0f e4 9c 18 91 59  |R..2?,%........Y|
+000003e0  42 98 a8 65 35 62 f7 ce  fa a3 56 46 c5 b1 da ac  |B..e5b....VF....|
+000003f0  9e 4e de 8d 14 fc 3c f3  94 74 50 99 1d 65 6b a6  |.N....<..tP..ek.|
+00000400  a9 38 93 9f 16 03 03 00  14 d7 5b 68 ca 4c 80 92  |.8........[h.L..|
+00000410  f8 13 5d fe 14 22 6f 9a  42 3a 27 de c8           |..].."o.B:'..|
 >>> Flow 9 (client to server)
-00000000  16 03 03 02 69 96 85 13  d5 b1 07 ec bb 1c c1 be  |....i...........|
-00000010  a3 42 10 c8 e0 ec f8 f1  67 29 d5 52 ef bb 32 e8  |.B......g).R..2.|
-00000020  7b e5 a7 3f ab 71 2d 74  20 f7 8a a7 1f bf 7c 4b  |{..?.q-t .....|K|
-00000030  8b 95 db 07 3c ad 86 5e  b3 98 32 e9 5a ce 96 08  |....<..^..2.Z...|
-00000040  c5 64 44 27 fb bc 44 29  49 44 32 3f 64 e8 86 1b  |.dD'..D)ID2?d...|
-00000050  54 63 74 3d a1 99 4d 4a  3e 5a 76 71 39 81 de df  |Tct=..MJ>Zvq9...|
-00000060  90 e4 f6 ac 96 15 0b 70  ad 7e 8a 1d 69 86 65 6e  |.......p.~..i.en|
-00000070  63 bf fb f2 6f 21 d5 66  ad f1 b1 09 05 04 f9 09  |c...o!.f........|
-00000080  0e 0c 12 74 c1 cd f1 5e  fa f1 1b cd 3b 2b 13 8f  |...t...^....;+..|
-00000090  fb f6 fd b0 ca ea 73 1b  38 ad db 6b fd 29 34 db  |......s.8..k.)4.|
-000000a0  51 4a 44 97 a7 2f 2a 98  d6 cc d5 c4 b9 17 23 ab  |QJD../*.......#.|
-000000b0  09 27 15 a5 35 3b 2b 7e  b2 3b fd 12 1b 11 90 4d  |.'..5;+~.;.....M|
-000000c0  81 1b 84 bb fd 72 09 31  5e 78 0e f6 b6 60 44 bb  |.....r.1^x...`D.|
-000000d0  6c 06 72 0b ba ba 60 f6  c1 cb 7e 45 a9 25 44 3d  |l.r...`...~E.%D=|
-000000e0  ba da 71 99 bb 79 b3 73  ef eb c2 cc 07 87 76 f5  |..q..y.s......v.|
-000000f0  e9 7c d9 47 8c fc 7d b7  a0 70 72 04 1e 3d 9b 2f  |.|.G..}..pr..=./|
-00000100  85 9f c8 2f d9 20 4e 00  97 d6 dd dc ae a1 04 96  |.../. N.........|
-00000110  83 e1 4f f3 0d ad 9c ce  5f e7 7b 88 7a b7 d2 ce  |..O....._.{.z...|
-00000120  0a 61 95 d2 78 e3 45 a8  10 5e d9 ae d2 e1 22 bf  |.a..x.E..^....".|
-00000130  59 9c 4a 2c 28 fb c1 b6  89 3b 65 8c 94 a9 f0 7c  |Y.J,(....;e....||
-00000140  86 98 8f 22 c4 18 47 e4  f0 b9 42 dd 34 ab 2a 8e  |..."..G...B.4.*.|
-00000150  fc 8f ce 09 ec 6f 57 6b  d1 ab 32 fd 84 e2 9f 7e  |.....oWk..2....~|
-00000160  f5 b7 5d 26 aa 37 da e9  f3 18 6f 56 74 03 ff 1e  |..]&.7....oVt...|
-00000170  87 95 fb 93 57 2e 32 fb  b3 cf d2 0d 42 02 4f 6a  |....W.2.....B.Oj|
-00000180  9e de ee 6a e6 7e e5 d2  ba cb 00 5d ff b4 6d 7f  |...j.~.....]..m.|
-00000190  23 5e 93 be e9 3a c1 b4  78 30 53 90 07 e4 a7 af  |#^...:..x0S.....|
-000001a0  da e1 29 7d 50 a5 76 ec  a8 5e 96 50 45 26 c4 9d  |..)}P.v..^.PE&..|
-000001b0  c1 99 98 c6 1a bf 93 c1  63 b3 0a 2d af c8 29 7d  |........c..-..)}|
-000001c0  ef b2 d3 8f aa 93 fb be  39 c0 a1 65 51 e8 6e c4  |........9..eQ.n.|
-000001d0  45 cb 2a 52 b7 ec e0 48  c0 b2 cc c7 72 12 18 e0  |E.*R...H....r...|
-000001e0  c7 9f fa 09 97 95 16 9f  f4 5d 70 c5 d6 7f 23 d5  |.........]p...#.|
-000001f0  53 98 d0 80 50 9b 52 46  11 d4 97 ea 47 26 f5 6f  |S...P.RF....G&.o|
-00000200  66 7b 8a cc f8 8d 70 c7  ec fa 72 de ba ac d4 b2  |f{....p...r.....|
-00000210  be 7d d8 78 44 dd de 66  53 26 f4 c0 8a 67 61 cb  |.}.xD..fS&...ga.|
-00000220  46 34 3d 6f 9e 9b dc ee  4a b9 5c 67 2b d9 87 2a  |F4=o....J.\g+..*|
-00000230  35 42 1c 3e b8 08 c9 32  13 a6 6f fc 4d cc be dd  |5B.>...2..o.M...|
-00000240  ad 76 19 1c 2d b3 6e 04  a1 17 05 93 b9 69 27 42  |.v..-.n......i'B|
-00000250  23 13 7b c0 f1 53 9c b5  1d 8e 5c f6 40 7e 5a e9  |#.{..S....\.@~Z.|
-00000260  20 dd 18 7a 0c f2 7b 5a  ec 3d 4e 3b 29 b2 16 03  | ..z..{Z.=N;)...|
-00000270  03 00 35 15 15 54 38 4e  87 f1 c1 9a 90 b2 74 df  |..5..T8N......t.|
-00000280  72 34 aa 0b 41 f3 df b4  c5 fd 50 00 2a 36 a8 d5  |r4..A.....P.*6..|
-00000290  c4 49 ac b8 58 3e 89 48  cb a9 4e b1 a9 0f ee 51  |.I..X>.H..N....Q|
-000002a0  37 d3 60 ca 23 76 68 0b  16 03 03 00 98 53 3c 0e  |7.`.#vh......S<.|
-000002b0  d5 3b d3 78 9f 47 5d 9e  1b b6 04 5f d4 04 66 55  |.;.x.G]...._..fU|
-000002c0  68 bd d7 ab 54 b7 e5 9a  12 9b 0c 1d 75 7b c7 35  |h...T.......u{.5|
-000002d0  e3 9e 9d a0 8f 61 7a 32  d1 a7 23 2a b6 ba 48 7c  |.....az2..#*..H||
-000002e0  1a 62 66 61 b4 3d e8 e3  a9 4e 85 7a 8d 5b f3 69  |.bfa.=...N.z.[.i|
-000002f0  c8 bc 0a 8a c7 e4 df 78  9b a8 cf 1d 37 14 90 a5  |.......x....7...|
-00000300  a8 ce f7 1f e7 a3 e5 d8  97 be 95 fd d3 c0 d0 81  |................|
-00000310  bf a6 e1 b3 6b 29 ee c6  16 3c 4c 68 6e b4 42 72  |....k)...<Lhn.Br|
-00000320  84 a0 97 0f 0e b2 44 0c  4f c6 df 04 b7 bf d8 e7  |......D.O.......|
-00000330  08 af 33 35 56 ed 6b cc  42 a8 9f 8e 59 9c 9c 32  |..35V.k.B...Y..2|
-00000340  29 77 87 6e d6 14 03 03  00 11 97 7a db d1 50 96  |)w.n.......z..P.|
-00000350  68 b7 04 90 79 fd f3 79  ed f3 de 16 03 03 00 20  |h...y..y....... |
-00000360  16 57 80 e9 30 65 46 29  74 09 32 70 13 1f f8 5d  |.W..0eF)t.2p...]|
-00000370  54 3f 14 4b af a1 51 b3  cd 1f e6 01 d6 68 11 fc  |T?.K..Q......h..|
+00000000  16 03 03 02 69 aa 39 9e  c8 e7 89 97 7f 22 3c 28  |....i.9......"<(|
+00000010  76 ac d9 48 51 e0 cd 22  53 a1 6d e7 b4 00 27 7d  |v..HQ.."S.m...'}|
+00000020  89 4b f0 54 d8 39 d0 a3  fc 35 a6 36 4b 3c eb 3a  |.K.T.9...5.6K<.:|
+00000030  00 b0 c1 17 9d c8 13 a5  58 ba 16 9e cb 21 50 dd  |........X....!P.|
+00000040  8a e0 2d 57 dd a6 bf 4d  6e b3 21 3b 46 f4 c3 77  |..-W...Mn.!;F..w|
+00000050  a1 86 07 c7 db e9 0a cb  2d 0f ff b5 1b ad 6b c4  |........-.....k.|
+00000060  c4 a4 4e 14 cf cb b2 6c  07 65 17 d2 db 30 e9 ec  |..N....l.e...0..|
+00000070  41 4e 78 26 12 27 08 a6  a7 84 39 c0 4b e7 4b 23  |ANx&.'....9.K.K#|
+00000080  2f ca ff 1e 41 9a e8 44  fc 5d a0 34 4e ca a8 6d  |/...A..D.].4N..m|
+00000090  31 51 57 c9 7e d1 0a 42  22 f2 b4 f9 a7 f9 28 d8  |1QW.~..B".....(.|
+000000a0  2a dd 19 0d 90 8b e1 78  b1 1c da 3a bb 5e 05 54  |*......x...:.^.T|
+000000b0  0d 0e f8 73 ed 01 e2 e4  d4 c1 f8 fa c3 d6 6f 42  |...s..........oB|
+000000c0  cc cb 99 99 97 18 b0 fb  ab 51 42 66 45 67 b6 29  |.........QBfEg.)|
+000000d0  02 60 ab 74 30 db f6 16  8a 8f 8e 9c cc d5 47 fa  |.`.t0.........G.|
+000000e0  f5 af 94 4f b1 94 40 57  ab 85 59 e4 3e cc c5 a0  |...O..@W..Y.>...|
+000000f0  61 b7 64 f9 dc 96 40 ae  fb 4c 57 39 9e 9a 23 8e  |a.d...@..LW9..#.|
+00000100  c9 36 6c 75 11 c7 6e 54  c3 1c e9 25 6a a0 f8 bb  |.6lu..nT...%j...|
+00000110  6b 5c ca 5c 06 6c 03 88  01 27 4c 89 02 e6 b6 1a  |k\.\.l...'L.....|
+00000120  92 99 4d 15 c1 1a aa 58  20 49 d7 4a f9 09 34 1e  |..M....X I.J..4.|
+00000130  d7 d8 31 79 9f d8 b3 a0  76 ba 96 77 77 77 5b 80  |..1y....v..www[.|
+00000140  88 ab a0 90 c7 5f 3d 82  e1 23 29 6e 3a 4d 9b f0  |....._=..#)n:M..|
+00000150  7b 6a b1 9d 78 ba 4c 7e  02 1f a0 73 3e 91 cf 75  |{j..x.L~...s>..u|
+00000160  c6 52 2d c6 79 be 85 65  0e e4 73 39 fe 53 6d e0  |.R-.y..e..s9.Sm.|
+00000170  a3 18 d5 69 80 ca f1 c8  ad f5 f4 fb b5 40 2e f8  |...i.........@..|
+00000180  30 82 ca 2c 46 6a ab a6  b2 83 9f a8 95 95 30 e3  |0..,Fj........0.|
+00000190  e3 30 6d f5 7c 83 96 af  12 d8 d6 d6 f9 6a ad bd  |.0m.|........j..|
+000001a0  bb 96 83 99 99 d8 6d 20  0e e1 be da 58 05 44 88  |......m ....X.D.|
+000001b0  a6 07 47 84 d4 77 fc 9b  fb d7 ac 60 70 0b e7 76  |..G..w.....`p..v|
+000001c0  13 c7 38 d9 3d 60 eb a6  9f a5 6d fc 5c d5 f6 2f  |..8.=`....m.\../|
+000001d0  31 02 38 65 8d be 04 06  84 95 86 b1 84 d9 ce c7  |1.8e............|
+000001e0  30 b9 d3 85 9f 1b 12 0f  5c 0e d6 8d e3 a0 15 04  |0.......\.......|
+000001f0  03 62 9d 52 7b e7 f4 13  aa 02 64 d9 d4 4b fd 6f  |.b.R{.....d..K.o|
+00000200  de ea 4a aa 91 60 e7 78  af 84 b5 9d c3 d2 c6 3a  |..J..`.x.......:|
+00000210  2a 9f 9b c6 8d 9e 5e 2c  90 6c d3 9d c1 be 96 5a  |*.....^,.l.....Z|
+00000220  60 d8 73 6c 49 50 c8 03  ec 58 73 bc b3 8c 30 c1  |`.slIP...Xs...0.|
+00000230  f4 a2 7d 74 3d 8d 7e 64  c1 a7 b6 24 13 06 72 1b  |..}t=.~d...$..r.|
+00000240  d0 87 22 af df 2a e7 fe  57 fa db e7 00 ba 74 35  |.."..*..W.....t5|
+00000250  16 34 20 3f 75 69 35 5f  64 7e 26 56 7c 93 05 4e  |.4 ?ui5_d~&V|..N|
+00000260  42 65 b8 bf 59 8e 82 13  f1 d0 05 95 c2 3d 16 03  |Be..Y........=..|
+00000270  03 00 35 99 1d 52 84 73  d6 e7 90 f6 41 9e 69 07  |..5..R.s....A.i.|
+00000280  39 0b bc b6 c7 f4 f2 a0  93 80 b9 c7 bb b4 a6 06  |9...............|
+00000290  50 5b 5d 75 97 cf c5 dc  2d 07 3d 8f 9e ae fa bf  |P[]u....-.=.....|
+000002a0  5b 6b 3e 98 02 fd e4 7d  16 03 03 00 98 80 ac e9  |[k>....}........|
+000002b0  4e e0 f8 b5 8c c2 2e 84  ec e0 3b eb b7 a0 14 2d  |N.........;....-|
+000002c0  ff d2 bf 35 14 20 06 00  2e 48 c7 f8 a3 fd 4f 50  |...5. ...H....OP|
+000002d0  4a 04 3e c7 07 50 90 72  29 f0 5c ac e1 fd 9d 3f  |J.>..P.r).\....?|
+000002e0  42 99 77 32 a9 79 24 7f  9e cc 84 1c d0 db 87 1c  |B.w2.y$.........|
+000002f0  3c 9a ae e3 45 e5 67 83  5f 75 e9 27 f3 ef 8a 15  |<...E.g._u.'....|
+00000300  88 2b 3f cc 6f 6f a4 78  d5 b2 96 3e 72 d4 c8 43  |.+?.oo.x...>r..C|
+00000310  98 a7 60 ae 38 8e fe 21  49 5b c2 80 d6 ef 6f 9b  |..`.8..!I[....o.|
+00000320  08 18 07 c2 64 00 a1 a0  09 8b b4 b7 eb 0c 68 30  |....d.........h0|
+00000330  26 87 f9 99 85 63 35 81  5a e4 31 19 9e f8 b8 7b  |&....c5.Z.1....{|
+00000340  81 aa 24 ff cd 14 03 03  00 11 84 c7 e1 8f 74 66  |..$...........tf|
+00000350  e6 bd 14 55 a8 d3 67 30  2d c4 fb 16 03 03 00 20  |...U..g0-...... |
+00000360  3a 63 a5 86 f3 78 f1 62  18 77 f7 25 71 52 56 17  |:c...x.b.w.%qRV.|
+00000370  d2 a5 e4 fa bc bb 44 07  85 37 cb 36 84 c7 6a 97  |......D..7.6..j.|
 >>> Flow 10 (server to client)
-00000000  14 03 03 00 11 1b a8 a8  a9 c6 a8 85 60 bc 14 0d  |............`...|
-00000010  86 ce a5 0f 45 17 16 03  03 00 20 cb 3a 73 db 55  |....E..... .:s.U|
-00000020  05 7e 3e 4b 6d d0 eb ca  68 39 bf 71 ba 6c e5 0c  |.~>Km...h9.q.l..|
-00000030  a7 90 d6 c1 b8 55 87 c6  20 40 35 17 03 03 00 19  |.....U.. @5.....|
-00000040  28 50 71 7c f0 7c 1e 61  fb de 5d d1 bb 77 f6 c8  |(Pq|.|.a..]..w..|
-00000050  a4 76 8d ab d4 c2 fe 27  96 16 03 03 00 14 e4 7e  |.v.....'.......~|
-00000060  51 bb 26 a8 9c 0c b0 25  7a 57 b9 98 c2 20 5a 50  |Q.&....%zW... ZP|
-00000070  07 ca                                             |..|
+00000000  14 03 03 00 11 9e 99 89  2d 10 21 a1 38 04 77 1a  |........-.!.8.w.|
+00000010  f8 1d b4 01 d1 9f 16 03  03 00 20 2a cb 67 8b 1b  |.......... *.g..|
+00000020  44 26 41 7b c4 6d a1 f4  cb ee 15 87 01 65 18 5a  |D&A{.m.......e.Z|
+00000030  c7 2d 10 e4 91 01 cb 22  e8 92 1a 17 03 03 00 19  |.-....."........|
+00000040  1a 46 a0 9a c5 1a 27 0c  e2 f9 03 55 3a e8 43 a7  |.F....'....U:.C.|
+00000050  d7 47 a5 95 6a e7 a1 12  69 16 03 03 00 14 d6 e0  |.G..j...i.......|
+00000060  1d 89 e0 c2 9a 52 d5 bc  d4 08 3e f6 81 dd 57 a2  |.....R....>...W.|
+00000070  25 f6                                             |%.|
 >>> Flow 11 (client to server)
-00000000  16 03 03 01 16 66 3c 1a  62 c3 4a f9 e4 66 01 d4  |.....f<.b.J..f..|
-00000010  f7 e8 5a fb 95 c4 40 33  d4 af 61 78 d6 54 91 2b  |..Z...@3..ax.T.+|
-00000020  62 72 d5 7b b8 2c 71 11  4e 0c 2d 79 6d 41 b1 9e  |br.{.,q.N.-ymA..|
-00000030  df 59 d8 e0 5c 72 98 b5  29 55 1e 9b 01 a5 af 2c  |.Y..\r..)U.....,|
-00000040  c3 87 4b f0 c8 ca 4d 56  fb 3a 7e 04 e5 b6 4f 6d  |..K...MV.:~...Om|
-00000050  1e 53 26 5d af fb 17 ee  97 87 45 2f df 1b 21 80  |.S&]......E/..!.|
-00000060  21 81 2b 18 2d 2d e9 3c  c4 01 32 91 b7 88 27 9e  |!.+.--.<..2...'.|
-00000070  26 40 e7 6a 27 c5 a0 b4  a3 ed 4d 4b a4 e3 0b c7  |&@.j'.....MK....|
-00000080  49 42 ca ef e9 16 5c 98  8d ab fc 7d 00 83 03 89  |IB....\....}....|
-00000090  a4 97 1e 3f 9e d8 ba c5  f5 2a 0b 0a ed a0 a5 59  |...?.....*.....Y|
-000000a0  27 03 36 7e 94 d8 9a 3c  fc f6 f6 52 b6 a7 fa 36  |'.6~...<...R...6|
-000000b0  04 83 2f e7 99 e5 1c 56  27 48 13 a0 59 ca ca 3b  |../....V'H..Y..;|
-000000c0  36 2d 25 e8 6f 6a cb 07  74 f8 1b 7d ba 3e 6e e1  |6-%.oj..t..}.>n.|
-000000d0  1d 3e 93 c6 23 f4 eb bf  ad 62 21 1a da 53 e1 13  |.>..#....b!..S..|
-000000e0  0a 3a 9c 57 48 d5 ee d3  72 af c3 74 fc 74 67 7d  |.:.WH...r..t.tg}|
-000000f0  b4 76 fc 21 55 67 49 92  fc 71 5d 42 69 d6 01 b5  |.v.!UgI..q]Bi...|
-00000100  83 4e b8 cd f9 ed 28 41  ae 95 2f d6 69 b0 d3 b8  |.N....(A../.i...|
-00000110  bd 06 d6 00 74 44 c9 47  aa 8e 1d                 |....tD.G...|
+00000000  16 03 03 01 16 27 50 ce  c0 8e 5a e2 54 55 cb c0  |.....'P...Z.TU..|
+00000010  08 c7 20 87 7e 78 c6 da  a6 7a 62 fd 7f f5 87 b3  |.. .~x...zb.....|
+00000020  83 a0 c8 70 ab 57 9b ca  bf 4c 07 06 f1 89 b9 b6  |...p.W...L......|
+00000030  24 f0 ae 72 e1 36 31 9f  74 ed 06 ad 44 3b 51 2c  |$..r.61.t...D;Q,|
+00000040  ed f0 c2 d8 9b 27 d2 9a  ec 44 88 80 7c 5a d0 66  |.....'...D..|Z.f|
+00000050  3d 84 e3 7c 24 89 b9 dd  8c eb 86 cd ce 69 0d e3  |=..|$........i..|
+00000060  97 ee ad 74 53 7f 9c f0  05 31 43 2a 8c 09 c4 11  |...tS....1C*....|
+00000070  46 3e 82 2c 3c 69 91 d1  eb 4b 8a ab a9 cb 24 00  |F>.,<i...K....$.|
+00000080  00 25 bd 26 d3 85 19 ff  3b 2b 92 3f 43 b0 9f 24  |.%.&....;+.?C..$|
+00000090  59 4f 3d a6 ce 65 27 5c  75 47 92 7b 4a d3 ca 55  |YO=..e'\uG.{J..U|
+000000a0  38 00 ac 37 0c 6e 2d 04  bc 6e fe 3a 9a 43 b6 7f  |8..7.n-..n.:.C..|
+000000b0  18 c1 a6 ce 49 b4 61 d3  97 8d a2 c9 fb fb cd 23  |....I.a........#|
+000000c0  f6 2f 0c 0b 2a b8 31 9e  fd ff 9f 44 1e 33 c3 23  |./..*.1....D.3.#|
+000000d0  bf 09 d2 de 90 b6 61 9c  33 33 33 46 bc 00 7e 16  |......a.333F..~.|
+000000e0  3c bd 82 2d 31 51 5b 11  87 ec 7f 25 d8 95 f9 9c  |<..-1Q[....%....|
+000000f0  df 00 54 40 f3 c1 08 fa  ef ba bc 5d b1 96 ae 8f  |..T@.......]....|
+00000100  35 0e 43 b2 50 c7 7e c4  b2 71 2e 40 3a b7 90 2b  |5.C.P.~..q.@:..+|
+00000110  81 ac 00 14 9d da d8 ca  5e 25 62                 |........^%b|
 >>> Flow 12 (server to client)
-00000000  16 03 03 00 81 d3 99 6f  14 2b a1 f4 d7 45 c9 94  |.......o.+...E..|
-00000010  69 0b b3 72 f4 2c 2e 5c  80 96 09 20 2f 63 a1 e4  |i..r.,.\... /c..|
-00000020  8b df d7 22 11 71 bd 17  db da 2d c6 78 e8 9a 95  |...".q....-.x...|
-00000030  6b 39 34 a2 13 7f 39 77  8b e5 1b 6c 4b 20 79 40  |k94...9w...lK y@|
-00000040  a1 d9 69 89 b1 e2 60 8a  75 88 ae 83 b9 4f 42 a4  |..i...`.u....OB.|
-00000050  c9 c7 44 ac 0d 3f 1c ca  49 f9 a7 05 e2 c7 05 cd  |..D..?..I.......|
-00000060  30 30 d2 f9 c2 87 60 33  3b 25 d0 e0 5e c2 bd 98  |00....`3;%..^...|
-00000070  9c 51 d8 38 c9 ef 04 f4  39 30 50 b6 35 53 f6 95  |.Q.8....90P.5S..|
-00000080  eb 5d 67 05 62 9a 16 03  03 02 69 39 94 a1 8d 01  |.]g.b.....i9....|
-00000090  37 64 c6 be bb 9c 22 9d  56 e8 68 ab 0f 7a 3a e7  |7d....".V.h..z:.|
-000000a0  2d 26 b7 ba 3e 54 38 b3  32 9d 7b d7 43 c4 d2 b3  |-&..>T8.2.{.C...|
-000000b0  9a 84 62 73 03 7a f2 68  ec 3e 41 d2 68 c9 22 1a  |..bs.z.h.>A.h.".|
-000000c0  e9 4d 9c e8 80 6a a9 9e  6a bd 67 5d 77 97 8b f7  |.M...j..j.g]w...|
-000000d0  32 cb 3a cb c2 c0 a1 40  7e 63 81 5f 19 a5 71 20  |2.:....@~c._..q |
-000000e0  c3 76 88 ae 5c d4 bd 54  08 e7 7e e7 77 7e 3d 91  |.v..\..T..~.w~=.|
-000000f0  b5 40 f7 7e 95 d5 e3 f2  e5 4a 57 f6 d9 94 df 07  |.@.~.....JW.....|
-00000100  56 45 09 c4 bc 65 05 04  57 f4 00 c5 91 4c dc 4d  |VE...e..W....L.M|
-00000110  a0 1e c6 e2 37 35 d0 5a  e9 79 ce f5 91 6d 3e 39  |....75.Z.y...m>9|
-00000120  c3 68 6a 76 6d f3 29 1d  e0 ef b2 20 3e 2a ac 11  |.hjvm.).... >*..|
-00000130  7e 11 2d a3 84 60 94 b5  8e 3a e6 4b 34 70 aa f8  |~.-..`...:.K4p..|
-00000140  e3 f9 0f 2c a4 bf 5b 27  7e c9 5e 6f c0 11 b4 ff  |...,..['~.^o....|
-00000150  53 6b 98 ee 20 77 87 87  fc 8e 30 1b 8f 74 29 af  |Sk.. w....0..t).|
-00000160  a2 c7 e8 c1 da e5 d7 0f  70 ec 27 23 46 3f 16 b1  |........p.'#F?..|
-00000170  59 bd 43 76 09 1d 8c f4  eb 17 10 a5 c1 1a e0 c6  |Y.Cv............|
-00000180  45 e2 d2 dc 6d f4 9a 87  36 ef 71 18 5c 1d e7 7c  |E...m...6.q.\..||
-00000190  40 d6 4c 16 ee 58 75 d7  56 9f 2e 17 80 1d 74 1c  |@.L..Xu.V.....t.|
-000001a0  fd 86 7c 2b 05 ac ef 07  18 a3 98 73 fa 9c 16 6c  |..|+.......s...l|
-000001b0  14 95 37 91 1e a2 c7 47  a8 87 11 35 30 d8 ed 60  |..7....G...50..`|
-000001c0  ba 65 ee 66 2b 1f db 67  c2 d0 71 26 3d ae 17 94  |.e.f+..g..q&=...|
-000001d0  f0 f6 65 01 bb 1d 85 7e  b3 d8 2c f1 96 c5 d5 e0  |..e....~..,.....|
-000001e0  97 a4 3e df 97 ff 8f 4b  e3 72 49 c4 5b 87 4e 06  |..>....K.rI.[.N.|
-000001f0  93 11 75 04 7b 80 9d 1c  a7 85 a3 2c f1 16 8a b9  |..u.{......,....|
-00000200  78 6b 27 1e 9a e3 86 eb  f9 42 95 10 02 d5 b6 01  |xk'......B......|
-00000210  b3 94 04 63 49 50 9e 11  71 07 aa a1 d6 9d d1 db  |...cIP..q.......|
-00000220  f4 ea 2e bb fa ca 1e 00  53 75 70 de 0a 72 eb 55  |........Sup..r.U|
-00000230  ab b7 ff 30 ad 5e 7e 13  90 75 42 5d 07 07 21 0f  |...0.^~..uB]..!.|
-00000240  db a6 f4 61 9c bf 31 34  e4 98 bb c4 ac 41 2d 76  |...a..14.....A-v|
-00000250  fb 6c 30 b0 e2 98 5f ed  d9 a8 42 d7 75 a1 bc 36  |.l0..._...B.u..6|
-00000260  f2 3e c5 ac 50 ae c7 2e  42 35 6c 1a 47 aa 1f 0a  |.>..P...B5l.G...|
-00000270  2f ff 6e 0a a5 c4 b5 a5  92 3f 54 d0 4e 62 6e 3e  |/.n......?T.Nbn>|
-00000280  cb 07 2d 4d 1a fb 94 5b  f8 d0 5b 26 34 2b 1b 26  |..-M...[..[&4+.&|
-00000290  8c dd 91 a7 66 21 89 d0  11 24 a5 5f 99 ae 62 84  |....f!...$._..b.|
-000002a0  34 9c d2 45 71 74 8c 68  db 8b ad 6f df 08 35 38  |4..Eqt.h...o..58|
-000002b0  ed 5c 3b 3e 55 a1 c3 16  b6 61 f4 4d 6d d0 2a 5d  |.\;>U....a.Mm.*]|
-000002c0  10 fb 64 c9 6f 87 6f 3d  ff d1 a0 97 64 b4 12 f9  |..d.o.o=....d...|
-000002d0  2a a8 46 59 1b e4 6b d8  c9 3e ac 14 00 4f 1a e6  |*.FY..k..>...O..|
-000002e0  26 9b 86 32 a3 9b 37 eb  c1 cf 9a 70 16 2e 4a b0  |&..2..7....p..J.|
-000002f0  6e e5 fc c2 16 03 03 00  bc bf c4 ea e0 dc be fe  |n...............|
-00000300  33 7f ef 2b d9 50 f7 87  d5 30 2b 09 bb 63 1e 4c  |3..+.P...0+..c.L|
-00000310  9c 3c a9 10 4e 04 e1 85  29 44 f9 ea 32 61 12 6e  |.<..N...)D..2a.n|
-00000320  63 0f d9 e7 e9 c8 81 a0  eb 4e fe 90 bf f4 f4 af  |c........N......|
-00000330  22 66 21 86 dc 2c f6 ed  b1 be eb b1 ac 14 f5 ce  |"f!..,..........|
-00000340  6c b9 a8 45 e4 3f 09 d1  b1 f3 69 f7 df c4 f0 6c  |l..E.?....i....l|
-00000350  48 f6 15 80 8a b8 b0 39  0e e9 22 9a 5c 72 f9 fa  |H......9..".\r..|
-00000360  95 01 9d ca e4 68 ef 72  e2 34 28 a5 04 5d d2 30  |.....h.r.4(..].0|
-00000370  c6 33 80 a8 f1 8f fb 6c  ec 15 c3 7c 68 7c a2 2e  |.3.....l...|h|..|
-00000380  4d ba 64 af fb f5 b8 f7  6b 6b 8c 5c 56 dc dd 69  |M.d.....kk.\V..i|
-00000390  39 d8 73 75 e3 be 17 09  3f 80 ed cc 12 5b ca d9  |9.su....?....[..|
-000003a0  e6 e2 50 88 41 0b 39 8e  84 6f fb 6a c3 8e 4f fc  |..P.A.9..o.j..O.|
-000003b0  dc 18 ca 02 18 16 03 03  00 14 5e ac 52 4d 0b 89  |..........^.RM..|
-000003c0  33 7d fe 1c d9 b5 1d 1c  2b 6d d4 4f 12 33        |3}......+m.O.3|
+00000000  16 03 03 00 81 37 3a f4  1b 6a 43 d2 6a 02 02 33  |.....7:..jC.j..3|
+00000010  b9 d5 9a 5c d1 3b 52 73  f2 27 a6 c0 f0 9b dd f3  |...\.;Rs.'......|
+00000020  d7 cd 89 ec 21 e0 d3 2f  4d 6c b0 cf 50 a7 39 43  |....!../Ml..P.9C|
+00000030  c2 56 d2 f8 45 d7 3c a6  b6 b9 06 3f ca a7 f8 37  |.V..E.<....?...7|
+00000040  4c 89 01 49 82 5f 27 15  3c bf f0 86 7c 1a 84 03  |L..I._'.<...|...|
+00000050  5a 90 77 03 01 fd b8 60  2a be cc 60 c6 54 b5 ec  |Z.w....`*..`.T..|
+00000060  c1 5d 6b e6 f0 2c 8c e6  7e e3 b6 c3 8b 63 3c 69  |.]k..,..~....c<i|
+00000070  ac 2c 9a 24 a7 77 5f 0c  36 08 68 6c 8b 76 f1 80  |.,.$.w_.6.hl.v..|
+00000080  4a bf f7 e6 15 5b 16 03  03 02 69 a1 ce a6 de 44  |J....[....i....D|
+00000090  cf d6 f7 88 f4 da 01 06  2b e5 cf 54 8d f6 78 ab  |........+..T..x.|
+000000a0  53 c5 ea d9 97 4b 94 22  24 9b 98 ba ba ee 42 9d  |S....K."$.....B.|
+000000b0  c3 e4 12 e3 be 35 24 86  3d 38 a0 6e b7 e6 cf dc  |.....5$.=8.n....|
+000000c0  e7 5c e1 0d 7c 05 bb 63  7c 8b c4 a4 db 9a 85 a4  |.\..|..c|.......|
+000000d0  ba d6 d4 79 38 79 01 52  2d cf c1 c7 6e 09 64 ff  |...y8y.R-...n.d.|
+000000e0  e9 b6 3e f2 a0 2b 4c 91  3f e2 fe 1a 40 4b 14 ea  |..>..+L.?...@K..|
+000000f0  77 8f 40 1c a2 96 7c d3  ce 34 5e d8 13 5a 82 33  |w.@...|..4^..Z.3|
+00000100  41 59 fa d9 81 1c 85 41  9c 61 b9 ca d5 46 e2 77  |AY.....A.a...F.w|
+00000110  3d a9 50 4f 11 b1 34 aa  ae fd e5 ec fe 12 e6 10  |=.PO..4.........|
+00000120  36 84 fb 25 f8 a4 6f 44  e3 ac 89 67 e4 9a 02 c4  |6..%..oD...g....|
+00000130  8f a9 4a d0 f4 64 e2 de  da 80 02 60 cb a9 2d e0  |..J..d.....`..-.|
+00000140  fa d9 b9 ee 43 e1 3e ed  79 79 6b 21 62 3d 6f b0  |....C.>.yyk!b=o.|
+00000150  77 53 db 26 60 e1 d6 ff  a7 01 2b b7 f0 49 df b8  |wS.&`.....+..I..|
+00000160  bc d9 ac 77 80 f8 53 66  16 8d 3a 8d 63 fa 12 e1  |...w..Sf..:.c...|
+00000170  ed f7 8b c0 40 46 16 70  e3 db f3 38 87 9f 11 eb  |....@F.p...8....|
+00000180  0b f5 b3 44 e4 16 e1 ed  85 e6 67 d5 35 60 20 99  |...D......g.5` .|
+00000190  7d bd 9f 65 b9 52 68 6c  6b 83 f9 06 e3 a7 3e 0f  |}..e.Rhlk.....>.|
+000001a0  9e 7c a5 ac 87 7a 45 53  a5 3f 27 5b 99 a9 34 c2  |.|...zES.?'[..4.|
+000001b0  5a 44 9a 30 08 30 c6 ff  60 8a a5 72 f7 49 d3 7c  |ZD.0.0..`..r.I.||
+000001c0  1f f9 8b 74 a0 b1 c8 65  84 6d 91 86 ab 1e 82 3b  |...t...e.m.....;|
+000001d0  d5 c4 bb 06 b3 31 61 bb  0e 65 3e 18 4d 0c c1 c1  |.....1a..e>.M...|
+000001e0  9d 7f ea ad cf 53 2e 9c  1c 7e aa c8 84 9e 0d ce  |.....S...~......|
+000001f0  91 53 3c d4 05 7e 57 d1  8b 55 ea e4 6e 57 90 4c  |.S<..~W..U..nW.L|
+00000200  bb 74 9c 87 1c 6a 89 cf  2c 50 8d 04 04 e6 18 c8  |.t...j..,P......|
+00000210  0c 9f 38 84 f4 f4 94 8d  33 2b a1 27 0b 5c 6a 2a  |..8.....3+.'.\j*|
+00000220  0c 13 b7 07 b7 a0 c9 e5  3c 9d 5a 7e 96 c9 53 fc  |........<.Z~..S.|
+00000230  ff c4 3a 8f 16 1f 2d 64  50 1d 13 c3 55 fb af d2  |..:...-dP...U...|
+00000240  0e f9 e6 18 e3 62 ce 6a  8f 96 ff 00 0e fe 27 53  |.....b.j......'S|
+00000250  70 57 53 2d fd f3 02 c7  fe b3 19 49 88 27 7e a2  |pWS-.......I.'~.|
+00000260  42 7b 22 d0 77 4e e5 04  aa 0d b6 9d b9 48 97 ab  |B{".wN.......H..|
+00000270  33 e7 14 97 65 82 f9 2c  dc 71 9e 4b eb ed 42 73  |3...e..,.q.K..Bs|
+00000280  c6 c8 93 8a 3a 24 bd f9  b4 6a 95 c1 1b 22 1d f5  |....:$...j..."..|
+00000290  c8 33 c5 38 1e a7 2e 91  68 35 4c 0a 37 57 ac e2  |.3.8....h5L.7W..|
+000002a0  c9 37 9e d9 1c b8 76 73  c2 d2 0c d0 c4 a1 c0 d5  |.7....vs........|
+000002b0  72 39 bf 03 f7 8d db e0  8f fe e2 d6 d0 d4 cc bb  |r9..............|
+000002c0  7d 78 c6 c5 13 a8 4e 45  1e 66 60 77 fe 26 4d 18  |}x....NE.f`w.&M.|
+000002d0  90 e8 e1 0c 5b 2b 25 9b  ee 6d 76 3f f6 23 a2 26  |....[+%..mv?.#.&|
+000002e0  52 8d a9 4e 7f ed 8e e2  6d 7c b4 eb 25 46 54 27  |R..N....m|..%FT'|
+000002f0  e2 2d 2c 59 16 03 03 00  bc 6e c1 fb 66 55 ca ea  |.-,Y.....n..fU..|
+00000300  56 62 78 2f fd c4 ff da  78 dd e7 4d 34 59 a5 8f  |Vbx/....x..M4Y..|
+00000310  05 ab ac 7f 80 35 f6 de  9d 3f fe 4b d4 79 07 3b  |.....5...?.K.y.;|
+00000320  c0 8d 02 b8 1a 28 b5 eb  9b 55 6c 26 12 8d 38 01  |.....(...Ul&..8.|
+00000330  55 ed 28 68 aa 48 13 61  d3 fe 29 f0 fe 18 4e ae  |U.(h.H.a..)...N.|
+00000340  6e f9 47 7c 65 91 f9 5e  17 80 68 fd 19 4d ed 17  |n.G|e..^..h..M..|
+00000350  7f 11 c4 15 5d 4b fc ea  a7 5c df 76 a0 08 2e 15  |....]K...\.v....|
+00000360  d1 c6 ae 7b 0d 1f 79 d7  0c 59 6b 53 46 b6 c0 2b  |...{..y..YkSF..+|
+00000370  ce 09 39 12 7a df f6 7d  a2 4b 86 2a df ab b8 7c  |..9.z..}.K.*...||
+00000380  07 10 3c 34 cd 15 4c ac  68 a4 28 8a f8 fc 30 a4  |..<4..L.h.(...0.|
+00000390  4f 15 77 b4 91 ca 02 ee  bb 64 36 90 1b 4b 9d 2b  |O.w......d6..K.+|
+000003a0  72 e7 dc 10 bd 83 97 18  3c 56 68 58 c9 e3 22 df  |r.......<VhX..".|
+000003b0  33 43 81 7d 5f 16 03 03  00 14 a8 eb 40 73 19 19  |3C.}_.......@s..|
+000003c0  22 10 63 ed f0 6d 73 8c  f4 bd f9 ba ad 2e        |".c..ms.......|
 >>> Flow 13 (client to server)
-00000000  16 03 03 00 35 a4 b8 43  07 6e 71 c9 b4 fa e1 9c  |....5..C.nq.....|
-00000010  a7 9d 0b 47 d8 ea 8b bd  ea c2 f5 bf 36 fa 88 95  |...G........6...|
-00000020  3b 98 b3 7e 19 21 9b 0f  58 76 e8 de 5b 24 d3 b5  |;..~.!..Xv..[$..|
-00000030  81 bd 11 ce 86 02 b0 d1  3b ac 14 03 03 00 11 3f  |........;......?|
-00000040  4e a4 96 06 71 44 5f 57  30 5e 1a bc 22 8d 42 97  |N...qD_W0^..".B.|
-00000050  16 03 03 00 20 23 e7 90  a5 0a 32 b4 69 06 d7 77  |.... #....2.i..w|
-00000060  df ef f6 2f b8 d8 22 39  08 4f 39 02 e0 7f 62 93  |.../.."9.O9...b.|
-00000070  02 b9 8e a5 b6                                    |.....|
+00000000  16 03 03 00 35 67 14 4b  ca 21 7f d2 82 1d 2e b3  |....5g.K.!......|
+00000010  1a 82 ae 2d d9 d6 7c 76  94 78 d4 ec 0e 4d fe 5c  |...-..|v.x...M.\|
+00000020  d5 56 5e 6d 32 f4 a0 64  50 1e f6 e4 32 28 92 80  |.V^m2..dP...2(..|
+00000030  d4 15 1c d5 f6 52 fc ca  c0 e7 14 03 03 00 11 df  |.....R..........|
+00000040  9d f3 d1 64 92 92 7e 11  77 64 e5 67 01 33 49 17  |...d..~.wd.g.3I.|
+00000050  16 03 03 00 20 c8 0f d9  d2 c8 b7 d6 a5 ac 2c 33  |.... .........,3|
+00000060  f8 77 8f b1 df db 16 de  43 6c e6 5a eb a0 6e ff  |.w......Cl.Z..n.|
+00000070  be 1d 69 ab 30                                    |..i.0|
 >>> Flow 14 (server to client)
-00000000  14 03 03 00 11 0e 2d 1e  73 95 29 15 86 03 a2 da  |......-.s.).....|
-00000010  6c f4 d2 02 2c 57 16 03  03 00 20 cd a2 f5 b6 da  |l...,W.... .....|
-00000020  0c 35 45 96 54 c3 96 5d  d8 e6 03 49 7b 5c d4 6f  |.5E.T..]...I{\.o|
-00000030  02 da 27 9e 2f a7 09 57  1b de 7b 17 03 03 00 19  |..'./..W..{.....|
-00000040  18 06 7d aa 5c 93 a9 b3  d3 14 0b 76 78 a2 57 73  |..}.\......vx.Ws|
-00000050  2f a3 4f 66 c4 b3 ee 21  95                       |/.Of...!.|
+00000000  14 03 03 00 11 6e 2c 51  c5 dd fa 70 2a 34 e0 cc  |.....n,Q...p*4..|
+00000010  3c 9f b8 66 15 e6 16 03  03 00 20 78 02 96 c6 24  |<..f...... x...$|
+00000020  57 ca 4a 60 47 68 f6 5a  13 8b 3b ce 90 60 d2 e3  |W.J`Gh.Z..;..`..|
+00000030  1b d8 ab 1c df d4 5e c2  8d 5c 5b 17 03 03 00 19  |......^..\[.....|
+00000040  b7 15 fb 91 10 48 ae 25  0c cd 4f 06 fa 2a 59 49  |.....H.%..O..*YI|
+00000050  2f 18 5e 7e 36 1b 2e cb  3a                       |/.^~6...:|
 >>> Flow 15 (client to server)
-00000000  15 03 03 00 12 55 f7 2f  b2 a2 e7 59 6c f6 a9 2d  |.....U./...Yl..-|
-00000010  d1 17 88 01 49 c6 f2                              |....I..|
+00000000  15 03 03 00 12 c3 ff f7  b3 dc d4 b3 f5 d4 7c a3  |..............|.|
+00000010  18 db 08 a2 50 ad 75                              |....P.u|
index 441fa0fd2aa82cd3005a30e8f64c12e91ed8d53a..784bcef92ef5ae52d19f3f767033f9c156ef989e 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 bb ec 39 c5 f2  |....Y...U....9..|
-00000010  dd a8 26 56 80 09 60 f5  d8 0a 93 6d 08 c4 30 c2  |..&V..`....m..0.|
-00000020  cf 0c 44 86 49 a3 19 84  20 38 98 20 0d 8b 81 b5  |..D.I... 8. ....|
-00000030  a7 42 37 27 1b 9c be 36  8f 9b 49 31 4f 73 67 a7  |.B7'...6..I1Osg.|
-00000040  78 9f 46 e5 9e 3b 45 ff  e9 16 11 ca cc a8 00 00  |x.F..;E.........|
+00000000  16 03 03 00 59 02 00 00  55 03 03 96 8a 79 30 8b  |....Y...U....y0.|
+00000010  13 f5 d3 1c 09 45 76 83  d7 2e e5 ad e3 ee e1 c4  |.....Ev.........|
+00000020  d4 b4 4c 37 93 cb 90 e1  9a 5e 52 20 fb 25 91 ea  |..L7.....^R .%..|
+00000030  1a 96 b6 fb 1f 0c a8 62  06 a0 fe 51 68 c0 fb a5  |.......b...Qh...|
+00000040  f1 05 28 02 be dc 87 31  e6 ff 90 1a cc a8 00 00  |..(....1........|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 59 0b 00 02 55 00  02 52 00 02 4f 30 82 02  |..Y...U..R..O0..|
 00000070  4b 30 82 01 b4 a0 03 02  01 02 02 09 00 e8 f0 9d  |K0..............|
 00000290  77 8d 0c 1c f1 0f a1 d8  40 83 61 c9 4c 72 2b 9d  |w.......@.a.Lr+.|
 000002a0  ae db 46 06 06 4d f4 c1  b3 3e c0 d1 bd 42 d4 db  |..F..M...>...B..|
 000002b0  fe 3d 13 60 84 5c 21 d3  3b e9 fa e7 16 03 03 00  |.=.`.\!.;.......|
-000002c0  ac 0c 00 00 a8 03 00 1d  20 2f ad 87 a5 c9 9e c7  |........ /......|
-000002d0  f6 f1 05 9a 44 97 57 34  6b 3a 30 54 4c 0e 47 5e  |....D.W4k:0TL.G^|
-000002e0  16 d3 c9 c2 25 a8 47 e5  63 08 04 00 80 9f 54 b4  |....%.G.c.....T.|
-000002f0  c1 aa bb 15 07 5c b1 52  ef bd 26 fa ec ce 70 31  |.....\.R..&...p1|
-00000300  90 fb f5 4d d2 26 0c 64  6f b3 9f 7f 27 c7 a5 b2  |...M.&.do...'...|
-00000310  d1 6d cf 0e 9c 91 e3 c4  20 f7 e3 ae 95 ff 6d ce  |.m...... .....m.|
-00000320  80 b5 30 89 6c a2 dd 31  26 5b 24 19 7a 30 f7 43  |..0.l..1&[$.z0.C|
-00000330  71 a8 e9 1a 27 ee 46 86  44 56 b1 f3 2e e1 bd d5  |q...'.F.DV......|
-00000340  79 99 34 0c 9b 01 e6 bb  0f ad 96 4a 68 0f 10 79  |y.4........Jh..y|
-00000350  e9 91 7f 06 e6 02 32 ba  8c b6 a2 0c 4b 6d 09 f6  |......2.....Km..|
-00000360  28 8f 94 e8 10 e1 ca 48  6c de 56 c2 5c 16 03 03  |(......Hl.V.\...|
+000002c0  ac 0c 00 00 a8 03 00 1d  20 ad 8e 56 2a c0 d0 7c  |........ ..V*..||
+000002d0  e1 cb 6b 20 0b 3e 53 33  28 25 37 42 5b 13 3c d5  |..k .>S3(%7B[.<.|
+000002e0  26 98 9e 0f df 45 6d 27  67 08 04 00 80 72 49 21  |&....Em'g....rI!|
+000002f0  f0 02 02 a3 7c e1 2a 18  d0 d0 21 8e 50 17 ad 0c  |....|.*...!.P...|
+00000300  3c a2 6d 65 b5 cb bc 7f  9e 7d 7f e2 36 3d b6 c8  |<.me.....}..6=..|
+00000310  df 7e b9 28 ab 01 99 2a  68 a4 be 46 11 94 9f 8c  |.~.(...*h..F....|
+00000320  67 02 92 1e 3c 51 78 f3  7a 35 ed f4 bb 8b fe b3  |g...<Qx.z5......|
+00000330  8c 32 aa c1 05 4f 99 68  b0 8a 75 65 1d e6 d6 6a  |.2...O.h..ue...j|
+00000340  61 65 aa 00 01 6b 29 06  99 d4 5b c7 c3 d2 0c 17  |ae...k)...[.....|
+00000350  74 59 d4 ee 99 b8 ef 5b  53 ff 33 df 9e 05 49 4f  |tY.....[S.3...IO|
+00000360  31 c6 95 81 67 c2 52 8a  0c e9 6a 46 22 16 03 03  |1...g.R...jF"...|
 00000370  00 04 0e 00 00 00                                 |......|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 25 10 00 00  21 20 2f e5 7d a3 47 cd  |....%...! /.}.G.|
 00000010  62 43 15 28 da ac 5f bb  29 07 30 ff f6 84 af c4  |bC.(.._.).0.....|
 00000020  cf c2 ed 90 99 5f 58 cb  3b 74 14 03 03 00 01 01  |....._X.;t......|
-00000030  16 03 03 00 20 d5 77 86  8e 32 60 6b 0f 0f 36 33  |.... .w..2`k..63|
-00000040  89 fe 51 b8 69 3a 1f 37  b3 d1 eb 43 ab e0 f6 db  |..Q.i:.7...C....|
-00000050  8b 9d 3c 0d 9a                                    |..<..|
+00000030  16 03 03 00 20 b8 c8 5d  3d b8 b8 2b c7 06 94 ec  |.... ..]=..+....|
+00000040  cc 92 01 22 3d cd 38 d8  aa 9f 1f 18 ef a0 ee 59  |..."=.8........Y|
+00000050  c0 3b 04 56 49                                    |.;.VI|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 20 ed 78 35 a3 71  |.......... .x5.q|
-00000010  34 a9 40 b2 be 15 dc a9  10 86 e0 de 94 23 e9 51  |4.@..........#.Q|
-00000020  2c 01 1e 34 19 07 53 20  59 ac f9                 |,..4..S Y..|
+00000000  14 03 03 00 01 01 16 03  03 00 20 be 6c dd f4 ef  |.......... .l...|
+00000010  71 1d 9c a7 24 ef 74 81  c4 01 1e e0 ef ac 78 90  |q...$.t.......x.|
+00000020  4e 51 fd 8a ca 83 e7 57  95 07 fa                 |NQ.....W...|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 16 f3 a2 5f  da 1c 09 70 76 af 14 83  |......._...pv...|
-00000010  e5 7f 6f c9 9a 61 7f d9  e6 86 3c                 |..o..a....<|
+00000000  17 03 03 00 16 35 96 43  38 06 49 b1 3f 01 ae 85  |.....5.C8.I.?...|
+00000010  1a ee 4b 2b fe c0 75 76  b6 4a b0                 |..K+..uv.J.|
 >>> Flow 6 (server to client)
-00000000  16 03 03 00 14 71 23 15  46 93 87 94 38 01 d0 1b  |.....q#.F...8...|
-00000010  1a 34 db 58 17 d0 ac 62  87                       |.4.X...b.|
+00000000  16 03 03 00 14 df 6c d7  78 02 f5 a7 cb d8 2f fb  |......l.x...../.|
+00000010  04 dc 30 bc 28 51 f9 ec  b8                       |..0.(Q...|
 >>> Flow 7 (client to server)
-00000000  16 03 03 01 16 46 70 b5  5f 98 fc af a8 cb d6 7c  |.....Fp._......||
-00000010  8c 1e 60 c3 68 25 20 7b  95 9a 0c 04 b3 2c 52 b2  |..`.h% {.....,R.|
-00000020  30 f9 db cf 64 48 0a 46  9b 7a 11 76 11 5c 22 0c  |0...dH.F.z.v.\".|
-00000030  ef fa e6 6e a1 90 29 b3  64 aa ff 4d cb 7d 4d 91  |...n..).d..M.}M.|
-00000040  c0 05 99 a0 3d 25 b2 1e  7c c4 d2 94 6b bf f0 f7  |....=%..|...k...|
-00000050  0f 6a 3b 4c 66 c7 8a 26  9e 4f 79 68 50 5c f9 92  |.j;Lf..&.OyhP\..|
-00000060  97 e1 a5 86 aa f2 e9 d5  8a a1 96 a7 37 82 71 7d  |............7.q}|
-00000070  7d 7e b6 77 a3 3d 84 40  58 0d 66 cd 52 6c 9b 18  |}~.w.=.@X.f.Rl..|
-00000080  e2 c4 f0 dc 3d 9e 0e b8  49 ca 64 f3 71 c5 24 34  |....=...I.d.q.$4|
-00000090  e7 ca c3 87 f6 b9 2c 6a  95 12 4d 9d 4a 4d fe 8a  |......,j..M.JM..|
-000000a0  51 16 6e c9 00 64 c0 d1  da ae e6 14 66 d2 a8 80  |Q.n..d......f...|
-000000b0  35 ae 86 f6 64 f8 56 87  8a 40 46 43 ae d1 d1 fb  |5...d.V..@FC....|
-000000c0  64 1d 00 a1 3d e9 d9 7a  b5 fb 71 2a db 76 5a 74  |d...=..z..q*.vZt|
-000000d0  03 c3 79 df e6 90 e9 7e  de f9 0e 70 7a 65 3c 68  |..y....~...pze<h|
-000000e0  4f 2e c0 b8 13 e6 9d 1b  86 b8 65 57 fa dc 46 a7  |O.........eW..F.|
-000000f0  26 ba c3 64 fa b3 6f d5  e8 98 1f 10 d5 a5 1f 3e  |&..d..o........>|
-00000100  cc f9 8d a6 56 37 0d ff  92 8f 1b 36 b3 3d 0b f5  |....V7.....6.=..|
-00000110  5b fb fb 1e 4d c8 cb 84  39 5b 87                 |[...M...9[.|
+00000000  16 03 03 01 16 8c 2a 91  5b 60 aa 44 e7 b7 7e b8  |......*.[`.D..~.|
+00000010  ee c2 3e f3 c4 2f 6a 75  8e 25 07 5a 5c 42 81 fd  |..>../ju.%.Z\B..|
+00000020  65 4c 2a fb a9 80 f0 ba  33 1b 06 a8 79 a8 15 8e  |eL*.....3...y...|
+00000030  3a c4 08 95 a5 23 f0 ba  fb 43 58 26 84 b5 9d 17  |:....#...CX&....|
+00000040  03 e5 e7 08 ce 8b 79 9c  5e fb c6 6e a6 b8 12 cf  |......y.^..n....|
+00000050  b9 6e 4a 2a 90 d0 6b 65  93 bf 41 31 25 7f 3a 7c  |.nJ*..ke..A1%.:||
+00000060  75 1f d6 4e 22 d3 90 7b  71 14 57 c6 b6 89 ef 79  |u..N"..{q.W....y|
+00000070  74 7e 63 79 b9 63 d6 ef  02 b7 54 4b 53 0e 7f 70  |t~cy.c....TKS..p|
+00000080  8a 34 b1 85 98 ae a7 05  b8 41 9d 49 a3 ca eb 7d  |.4.......A.I...}|
+00000090  8b 64 e7 5d ca 11 71 93  e0 ff 6e 43 37 b4 e9 ec  |.d.]..q...nC7...|
+000000a0  23 6f d6 c6 bc cb ef a2  0b d0 4b ba 4f 40 b0 4b  |#o........K.O@.K|
+000000b0  ec 57 cb 8a 10 ae fe cd  14 70 42 a0 b9 1c 81 f6  |.W.......pB.....|
+000000c0  d2 79 47 31 4a b8 aa ac  89 98 cf ae 4e 8f 3d 36  |.yG1J.......N.=6|
+000000d0  c5 41 0e d8 e6 f3 88 2a  19 e5 e7 71 e2 2f 32 93  |.A.....*...q./2.|
+000000e0  ae 05 95 25 8f ec 4e 10  25 7e 53 60 6e c2 f2 72  |...%..N.%~S`n..r|
+000000f0  fc 7a 69 c1 93 e9 b8 2e  94 f3 19 31 5b 23 7c fd  |.zi........1[#|.|
+00000100  04 5d 59 ca 00 cc 37 0b  05 0d 50 10 50 3f b0 86  |.]Y...7...P.P?..|
+00000110  84 d4 fc 6a 0a 94 dc ba  88 fe ad                 |...j.......|
 >>> Flow 8 (server to client)
-00000000  16 03 03 00 81 25 44 f6  91 ed d5 01 fa 88 d6 74  |.....%D........t|
-00000010  f7 cd 6d ba 85 76 1d bd  ef 7b 31 51 db b4 42 a3  |..m..v...{1Q..B.|
-00000020  0a 89 3f 47 dc ca 18 39  84 5d 5a 4e d2 cd ba 75  |..?G...9.]ZN...u|
-00000030  b9 75 53 28 8c 85 6e 84  02 39 0a d2 59 ee ac 2f  |.uS(..n..9..Y../|
-00000040  fe a3 e4 fb 8c a1 72 e3  9f 28 8b 13 92 a8 5b 70  |......r..(....[p|
-00000050  24 f0 1b 6d 19 aa f1 b2  bf 8a 1f e2 3a 3e 3f e2  |$..m........:>?.|
-00000060  57 16 12 9e e8 21 11 66  b9 96 71 36 46 e1 2e fc  |W....!.f..q6F...|
-00000070  1e 40 a2 e2 6a 4d 4b 91  7a 50 0b d0 87 d1 04 16  |.@..jMK.zP......|
-00000080  2f 47 4d f2 c9 68 16 03  03 02 69 9a 28 7b f7 fc  |/GM..h....i.({..|
-00000090  8b e7 2b 40 88 1c 30 c1  5a f6 1d 51 a9 a8 5e 70  |..+@..0.Z..Q..^p|
-000000a0  73 1c 43 a7 3c 11 7e d5  92 78 b1 4f fd 5d 55 c6  |s.C.<.~..x.O.]U.|
-000000b0  5a ef 83 88 b2 e2 33 2a  27 cd 2e e8 d2 f4 2b d4  |Z.....3*'.....+.|
-000000c0  d5 b0 35 54 f6 a1 9c 07  75 10 8b 5d b9 dc bb 83  |..5T....u..]....|
-000000d0  76 43 f6 7e 70 2f 7c fe  8e 64 ca 00 65 df a4 e1  |vC.~p/|..d..e...|
-000000e0  a9 ad 71 79 d6 83 21 f6  9c 1b 88 d4 bb 51 3c 8a  |..qy..!......Q<.|
-000000f0  8c e5 c2 13 30 bd 6b 60  29 01 3e a0 cc 19 69 54  |....0.k`).>...iT|
-00000100  f0 2d dd a9 a1 24 a3 cc  13 9b 9a 8b f5 06 88 a9  |.-...$..........|
-00000110  9d ec c1 6f 0c b2 dd b3  60 be 23 ee 67 26 2d 65  |...o....`.#.g&-e|
-00000120  b1 99 9a 5b 92 c5 06 79  47 c6 4d 39 36 83 3b 4b  |...[...yG.M96.;K|
-00000130  96 f0 03 41 5c f9 fa 7c  3e d5 bf 67 1c a3 cf 6f  |...A\..|>..g...o|
-00000140  26 98 e0 2a 2d 64 60 c2  71 b1 b3 35 ba 8a 38 00  |&..*-d`.q..5..8.|
-00000150  88 cf 5a a5 2b 89 83 f3  04 ad 24 97 fa 34 69 fd  |..Z.+.....$..4i.|
-00000160  d7 70 00 09 ce 0f 60 f7  84 7d e3 5e 19 a9 1b dd  |.p....`..}.^....|
-00000170  45 3f 34 ae d4 c5 5c 1f  32 81 69 ea 22 44 1d c6  |E?4...\.2.i."D..|
-00000180  a3 ca 99 c5 44 09 76 cb  e2 ed 2e fd 23 09 d4 ea  |....D.v.....#...|
-00000190  62 cf cb 93 88 02 ca 8c  90 05 c9 0e 8d ff 8f e1  |b...............|
-000001a0  2d ef 52 1c ed 01 53 ef  a6 ee 11 11 b7 2b c8 b4  |-.R...S......+..|
-000001b0  6e 32 8c 54 7a 2b 19 e1  32 3e d0 92 87 81 76 04  |n2.Tz+..2>....v.|
-000001c0  c0 fd 99 3b 04 00 fb 76  d7 ed b0 81 e3 81 8c 1f  |...;...v........|
-000001d0  2b a0 59 d6 41 cd 8d 7d  b6 62 9d ab 60 33 24 f5  |+.Y.A..}.b..`3$.|
-000001e0  ec 70 8b b2 46 60 8f 53  c8 a3 f1 47 df e0 e8 b0  |.p..F`.S...G....|
-000001f0  9a cf 61 d4 d0 f5 0b b6  cd 85 47 1b b2 26 7d f2  |..a.......G..&}.|
-00000200  0a 32 af 5c 25 2a cc d2  66 9a 36 a1 68 95 34 18  |.2.\%*..f.6.h.4.|
-00000210  2d 9a 5a 62 a7 39 be 00  70 59 63 38 6a f9 53 b7  |-.Zb.9..pYc8j.S.|
-00000220  6d dd d4 cd c4 d2 12 b0  67 06 b5 d3 28 06 e4 43  |m.......g...(..C|
-00000230  98 b5 13 9f 1a d5 5e 07  70 f9 96 3c 66 a0 60 d6  |......^.p..<f.`.|
-00000240  79 1f 67 98 0b 38 ab 5a  1c 6f b0 31 e9 d9 6e 58  |y.g..8.Z.o.1..nX|
-00000250  28 c4 c5 82 9f 57 12 ae  35 12 c5 5c 29 f9 50 93  |(....W..5..\).P.|
-00000260  07 d8 e4 b8 36 5a 1e 10  a9 ee 33 5d ce 9c fe b8  |....6Z....3]....|
-00000270  78 11 99 2a 88 9d ce 49  6f 1c 73 41 65 5f c2 d5  |x..*...Io.sAe_..|
-00000280  46 a7 25 27 bc 3d 69 25  04 3a 37 ee e6 8a c0 d8  |F.%'.=i%.:7.....|
-00000290  e8 72 7a a9 21 03 9a 63  c9 f5 16 76 c4 11 b9 12  |.rz.!..c...v....|
-000002a0  03 cf ec 91 a0 6b 90 24  ba 0b f6 f2 4a 41 0d 9f  |.....k.$....JA..|
-000002b0  32 23 a3 df 3c ff c3 44  01 9c 77 5a 01 3f 00 d0  |2#..<..D..wZ.?..|
-000002c0  44 4d 48 23 58 9f 18 99  97 9c 32 7f cb 40 bb 35  |DMH#X.....2..@.5|
-000002d0  1f b8 06 07 28 7d 39 5a  47 66 12 95 30 07 24 b1  |....(}9ZGf..0.$.|
-000002e0  81 bc ea c0 6d 10 15 82  5f fe 68 50 1d aa 61 19  |....m..._.hP..a.|
-000002f0  c9 47 7c dc 16 03 03 00  bc e8 5f 40 20 1a cd d8  |.G|......._@ ...|
-00000300  5b b7 1e db 9d c0 10 96  e2 11 86 bc 0c e1 5f bd  |[............._.|
-00000310  9c cc 70 37 85 87 94 3c  cd 7d 0a c3 56 1e 18 9a  |..p7...<.}..V...|
-00000320  dc 21 4b e6 e1 63 c0 e6  2e 32 69 96 7e a0 cf cc  |.!K..c...2i.~...|
-00000330  58 74 a9 31 97 c1 e4 87  79 7f e7 7e 94 32 93 8d  |Xt.1....y..~.2..|
-00000340  31 97 51 27 26 cf ac e9  f9 34 ae 3e 1d f0 e9 5a  |1.Q'&....4.>...Z|
-00000350  71 82 05 10 8e be 0b 83  39 44 28 45 c6 e1 4a 85  |q.......9D(E..J.|
-00000360  c0 bf 3f 80 9b 61 97 82  d1 54 37 5f bc b2 f7 1f  |..?..a...T7_....|
-00000370  a1 ef 0f c5 be 74 96 3b  e8 89 30 3f d7 06 18 77  |.....t.;..0?...w|
-00000380  ed 3b aa 6e df 0c 15 e1  3e b1 36 ae 85 23 7d 9a  |.;.n....>.6..#}.|
-00000390  17 c3 f4 91 3a ac b1 64  03 a9 59 19 89 c2 d9 ad  |....:..d..Y.....|
-000003a0  82 d7 8e 85 36 cb 81 61  0d 3a 24 a1 84 55 37 bb  |....6..a.:$..U7.|
-000003b0  13 80 61 38 ef 16 03 03  00 4a 88 8d 13 b9 32 18  |..a8.....J....2.|
-000003c0  3c e2 72 b5 5c 0b 81 87  a0 ef 87 53 89 b1 f4 8b  |<.r.\......S....|
-000003d0  6a 87 68 c4 7d 59 2c 44  46 bb b1 40 8e 0a 45 4e  |j.h.}Y,DF..@..EN|
-000003e0  b8 a1 ba 72 bb 71 f9 52  55 c7 44 cd b3 56 82 68  |...r.q.RU.D..V.h|
-000003f0  8c 57 39 58 0b 40 12 4f  5d a2 91 3a ab 68 55 19  |.W9X.@.O]..:.hU.|
-00000400  26 dc ed 30 16 03 03 00  14 52 f8 53 d9 fc a6 a3  |&..0.....R.S....|
-00000410  89 c4 5a 2d 66 46 17 16  c3 bb f9 3c ca           |..Z-fF.....<.|
+00000000  16 03 03 00 81 41 25 27  5b 76 24 a0 4f f0 bf ca  |.....A%'[v$.O...|
+00000010  c4 4f f8 7c c6 e8 2a d4  d1 ed f1 b8 34 84 d6 d5  |.O.|..*.....4...|
+00000020  93 20 70 7d 8e 75 c5 16  a8 ff 5c e6 de 16 ea 96  |. p}.u....\.....|
+00000030  3f 86 3b bd 6d fa 96 3d  27 18 34 b8 18 86 ee 65  |?.;.m..='.4....e|
+00000040  7f f2 cc 7a b9 f8 2e 5a  32 f3 16 e2 a2 27 fd 4b  |...z...Z2....'.K|
+00000050  31 19 e6 81 d9 ef 02 10  ac b6 55 d3 0b e2 b0 09  |1.........U.....|
+00000060  56 ea 50 5a 96 b3 ff 07  78 48 df 77 3f 15 c9 ff  |V.PZ....xH.w?...|
+00000070  a7 24 af 28 ec 99 1a c9  36 09 16 9c 7c 5a c0 85  |.$.(....6...|Z..|
+00000080  7c 93 e4 61 2e 5b 16 03  03 02 69 ef 17 31 d5 9c  ||..a.[....i..1..|
+00000090  bc 09 f9 b7 75 e2 c8 ea  93 6f b7 49 e3 0e af bb  |....u....o.I....|
+000000a0  84 d6 3b 20 e2 89 13 6f  7a d1 73 a7 cb d5 03 b2  |..; ...oz.s.....|
+000000b0  20 40 40 76 d9 5d 3b 23  cb 48 ba 3c 1b e7 5d de  | @@v.];#.H.<..].|
+000000c0  16 be 82 91 39 d0 b4 83  3e 4c b8 a0 66 56 47 6c  |....9...>L..fVGl|
+000000d0  08 03 b1 0f be 3f d3 5e  7e b4 40 db db 5b ce 61  |.....?.^~.@..[.a|
+000000e0  d9 dc 02 7d ea df ea 43  08 2c b0 1c af 76 8f d3  |...}...C.,...v..|
+000000f0  cd af 51 cd 17 df 70 58  90 bd 83 aa 4b e5 fe cd  |..Q...pX....K...|
+00000100  90 30 e0 b5 d0 95 49 c2  10 06 8c 5a dd a2 37 ad  |.0....I....Z..7.|
+00000110  d5 d1 0e 73 c7 92 a9 ab  67 51 da 9d a4 62 6d a6  |...s....gQ...bm.|
+00000120  d7 89 22 2b 97 59 ad 02  65 e9 1d 48 44 07 c9 c0  |.."+.Y..e..HD...|
+00000130  c4 1f 7f da 64 0c 35 19  16 b3 70 41 d8 61 c3 47  |....d.5...pA.a.G|
+00000140  59 4d c2 e6 07 86 55 92  b9 98 8e 5c 86 d2 d5 51  |YM....U....\...Q|
+00000150  6a 50 19 99 75 0a cf 6e  49 cc 8a 76 b5 2b 20 48  |jP..u..nI..v.+ H|
+00000160  2b 11 d4 54 a2 ea 98 ce  d8 56 22 c8 f8 eb e5 25  |+..T.....V"....%|
+00000170  c8 cf ec 86 95 09 51 7e  18 89 bb 8f d4 66 b8 44  |......Q~.....f.D|
+00000180  c2 78 f4 4d ad eb 2d 79  f8 f6 02 4f d2 35 d4 71  |.x.M..-y...O.5.q|
+00000190  b3 ae e6 7d f6 45 6c 99  07 57 3c 01 bb c1 fb f1  |...}.El..W<.....|
+000001a0  1a ac ba 92 b6 60 52 63  8b 21 eb bf 77 02 c6 29  |.....`Rc.!..w..)|
+000001b0  7f 10 f7 11 ac a2 90 a9  8b 47 da c1 2c 41 c9 da  |.........G..,A..|
+000001c0  3f 18 ab be f0 eb 20 98  80 c6 d2 14 9e 8e d3 41  |?..... ........A|
+000001d0  c3 37 ab 12 5b cc d0 25  bd af 16 49 4e 89 a1 92  |.7..[..%...IN...|
+000001e0  d1 09 49 59 dc cf f8 6c  73 02 cb 72 6d 28 6e 28  |..IY...ls..rm(n(|
+000001f0  c5 a8 84 20 e6 f8 1b ad  c1 6c 8f b0 30 b2 49 84  |... .....l..0.I.|
+00000200  22 42 7d ec e1 c7 ab 29  de 1c 84 1f cf 59 c6 80  |"B}....).....Y..|
+00000210  7e 13 13 d7 c5 e5 f2 e0  3b 9d 81 c9 3f 86 21 27  |~.......;...?.!'|
+00000220  d7 c8 45 c1 25 f6 19 8d  0a f6 e9 5a 9b d5 64 a1  |..E.%......Z..d.|
+00000230  e4 6d fe 6a cf d1 c3 1b  d4 ea d9 1f 6b dc f9 a7  |.m.j........k...|
+00000240  e9 d2 6c 31 19 db e1 f4  f8 82 6e 8b da fd b1 fd  |..l1......n.....|
+00000250  0a 56 84 73 db 25 5f bb  12 61 70 de 67 34 28 1c  |.V.s.%_..ap.g4(.|
+00000260  c3 e6 eb 81 c8 94 55 ca  52 25 e8 72 bf a1 c5 88  |......U.R%.r....|
+00000270  b8 ce 72 8d 64 6c 38 d9  19 07 f3 51 51 91 84 f2  |..r.dl8....QQ...|
+00000280  c4 76 7f 8b 57 09 71 94  38 aa f1 64 51 6f 62 50  |.v..W.q.8..dQobP|
+00000290  c8 50 68 82 b9 54 b1 28  54 99 21 26 7d 75 c7 c7  |.Ph..T.(T.!&}u..|
+000002a0  79 e7 65 93 72 a4 39 2d  4c ec ba b2 4c 92 ae ee  |y.e.r.9-L...L...|
+000002b0  34 a2 22 2f f9 b9 75 a9  27 77 63 2d ac 27 87 ce  |4."/..u.'wc-.'..|
+000002c0  ee 37 c0 c7 c1 b6 4c 13  d7 78 97 64 dc af ea 0d  |.7....L..x.d....|
+000002d0  7c 12 0e 7b 0b 26 77 01  e4 1c 24 e8 9f fc 19 2f  ||..{.&w...$..../|
+000002e0  46 a2 81 3d 0d c7 16 7e  49 25 b4 c1 0f 0a 71 05  |F..=...~I%....q.|
+000002f0  25 eb 53 e4 16 03 03 00  bc 0b 79 2d c6 0a 63 68  |%.S.......y-..ch|
+00000300  f0 21 37 d0 42 4a 0f 2f  7d 2f a0 7d 3d c3 94 c4  |.!7.BJ./}/.}=...|
+00000310  36 f5 a6 db e1 ad 0f 94  07 67 57 54 d4 57 86 50  |6........gWT.W.P|
+00000320  a2 e1 78 09 f2 e3 7b bc  6d 1b c0 fe 16 eb d3 ef  |..x...{.m.......|
+00000330  fb ec 22 44 ee 2f 78 99  84 e2 c1 4c f7 0d 4f bc  |.."D./x....L..O.|
+00000340  ca 57 be de 5f 52 08 33  b0 e1 1d 7b 45 9e 5d 17  |.W.._R.3...{E.].|
+00000350  41 2c 10 43 44 18 84 38  f3 0b 6a a1 76 bf 75 c9  |A,.CD..8..j.v.u.|
+00000360  56 b2 53 4c 98 39 c0 6f  30 13 96 8a 27 59 12 03  |V.SL.9.o0...'Y..|
+00000370  60 64 ce 28 54 c0 03 f4  c4 d1 df 94 e3 6e 43 61  |`d.(T........nCa|
+00000380  fa 43 40 e5 05 3b 26 dc  c4 41 bd 73 c3 9e a0 db  |.C@..;&..A.s....|
+00000390  fb c9 50 b4 4a d9 2d 71  cf e8 ff 3d 17 9e 29 35  |..P.J.-q...=..)5|
+000003a0  61 6c ab 11 ac 21 fa 90  6b 75 1f 0a 9d 30 3f 13  |al...!..ku...0?.|
+000003b0  fa c3 97 7a 74 16 03 03  00 4a 3d ca 3b 3d c8 6f  |...zt....J=.;=.o|
+000003c0  44 4e 53 3d 05 27 97 aa  bd 58 33 d6 ad 4a 34 71  |DNS=.'...X3..J4q|
+000003d0  22 d9 36 96 17 a5 ba 6b  b3 20 2e da 64 65 14 c7  |".6....k. ..de..|
+000003e0  6a c7 07 39 55 db bb ad  e2 49 84 09 5e 78 88 b5  |j..9U....I..^x..|
+000003f0  4b d5 23 fa 17 c5 f2 b8  2a c6 e5 1e 15 47 01 36  |K.#.....*....G.6|
+00000400  ef 7f 0a 14 16 03 03 00  14 28 e3 58 7e b9 36 d6  |.........(.X~.6.|
+00000410  ef 65 c8 bc fb 10 57 3d  48 70 7f 68 7d           |.e....W=Hp.h}|
 >>> Flow 9 (client to server)
-00000000  16 03 03 02 69 fe 0d 45  cb 57 12 fa 9e 10 d7 b3  |....i..E.W......|
-00000010  a5 dd 33 0e 39 41 77 63  8e 99 e0 5b b9 5e 94 0a  |..3.9Awc...[.^..|
-00000020  48 b2 6b e9 61 ab f2 74  6b 5e a3 f9 3f 9c 29 0b  |H.k.a..tk^..?.).|
-00000030  6b 34 29 92 d8 c8 2c 61  84 f2 3b 0f c2 5c e5 19  |k4)...,a..;..\..|
-00000040  6a f0 e2 03 e3 93 a6 1e  4e 87 79 6b 07 dc 18 d2  |j.......N.yk....|
-00000050  9a 25 be f3 d6 ab 2a be  f8 68 65 68 92 8a 80 04  |.%....*..heh....|
-00000060  26 eb 62 ae 6b bc 81 27  82 76 25 e0 6b ac 04 e9  |&.b.k..'.v%.k...|
-00000070  67 68 13 f6 7b 7e 24 c2  75 27 8a c9 3a 7a 2f aa  |gh..{~$.u'..:z/.|
-00000080  a2 37 d9 73 97 bc 4b 09  ba 1b 2c ba 08 85 c6 82  |.7.s..K...,.....|
-00000090  50 a3 e0 00 6e a8 7c 14  ab 38 ae c4 82 ee 05 4b  |P...n.|..8.....K|
-000000a0  9a c0 19 62 1e de ef 7f  8c a4 a0 0e 29 0f b4 09  |...b........)...|
-000000b0  f1 b9 39 ae 09 1b 6e 6f  ee 3d 31 72 70 09 51 44  |..9...no.=1rp.QD|
-000000c0  1c 33 64 6d ae 8d da a5  e0 7b a3 49 19 2c 3f dd  |.3dm.....{.I.,?.|
-000000d0  6b 1e d1 a7 bb 8a 13 8c  e9 aa 5f b3 fd 88 89 5a  |k........._....Z|
-000000e0  4a 30 dd d0 1e 6a 8c 8a  0d 35 82 01 64 c1 42 ff  |J0...j...5..d.B.|
-000000f0  60 ac 3d 62 bf 31 3e ab  42 7e b0 da 4a cc 9c d8  |`.=b.1>.B~..J...|
-00000100  0e 92 97 a2 40 48 48 ce  66 49 bd 1b 8a ee ed 46  |....@HH.fI.....F|
-00000110  18 98 b9 43 b8 76 e8 93  07 3c 38 6e c2 cd 9c ce  |...C.v...<8n....|
-00000120  e2 38 f0 d7 ee ad c7 4a  c4 ed 3b fd 2e f2 9b 43  |.8.....J..;....C|
-00000130  6c fe 75 d7 4d 61 2a c5  16 e2 3d af 98 5b 76 f5  |l.u.Ma*...=..[v.|
-00000140  3e 96 b9 81 b3 cb 0c 91  89 44 6e d6 66 c4 f2 dd  |>........Dn.f...|
-00000150  c9 21 09 91 95 f2 99 29  62 54 44 03 b0 fe 84 bb  |.!.....)bTD.....|
-00000160  96 86 c4 ca 6e 7f c9 f9  1a 80 38 42 7d 54 b3 6f  |....n.....8B}T.o|
-00000170  2a 2d c3 19 54 60 3f fb  00 95 65 6a 85 4b a2 8f  |*-..T`?...ej.K..|
-00000180  6a 3d 38 61 e9 36 c2 25  92 3b 53 f2 ea bb 60 42  |j=8a.6.%.;S...`B|
-00000190  ab 83 83 c0 2e 95 6d 5a  19 61 9f b3 29 ee b2 52  |......mZ.a..)..R|
-000001a0  5f 27 16 46 d9 ad 62 45  d5 81 9a 93 ef a1 4f e7  |_'.F..bE......O.|
-000001b0  0e e0 71 bf cd 49 68 e7  13 f1 71 59 8c f5 2d 05  |..q..Ih...qY..-.|
-000001c0  5d 65 c4 6e 2c 91 c5 d3  40 c4 2f df c8 f6 59 55  |]e.n,...@./...YU|
-000001d0  05 6b c1 b7 59 15 8e b8  85 1b 75 dd 44 9e b7 f3  |.k..Y.....u.D...|
-000001e0  00 73 bf c6 93 d4 43 27  bd 60 79 1a 28 93 2d 64  |.s....C'.`y.(.-d|
-000001f0  fb 2f 77 a6 79 22 54 f3  c3 3c 3f cd 4d ea 79 3b  |./w.y"T..<?.M.y;|
-00000200  aa 4c e6 86 55 8d e0 5c  ce 00 1e d4 fa ab bb de  |.L..U..\........|
-00000210  8f 41 95 15 d3 6a 21 02  cb 4a f5 b6 2d 8c da 99  |.A...j!..J..-...|
-00000220  93 1f 9f 81 cf 77 f8 01  0a ab 77 03 5c a3 bd 3a  |.....w....w.\..:|
-00000230  ba 07 51 17 50 06 c9 51  f8 f1 ec 3f 60 44 df 1b  |..Q.P..Q...?`D..|
-00000240  06 05 bd 8f 17 99 00 73  38 e5 bb fb 08 1b e7 ea  |.......s8.......|
-00000250  b5 36 e0 4e 67 d9 11 90  5e d9 8e 63 7b f9 03 4b  |.6.Ng...^..c{..K|
-00000260  ef cd 4d 2c d9 4b eb 8a  bb 62 85 03 16 e2 16 03  |..M,.K...b......|
-00000270  03 00 35 d1 39 57 66 1b  70 63 8f 6a b4 1d 5f 5e  |..5.9Wf.pc.j.._^|
-00000280  dd 31 7e 5b 0e e3 d5 98  90 8b 60 33 0c 10 7c 01  |.1~[......`3..|.|
-00000290  4c 40 88 e9 a3 8c 61 ab  dc 4a e2 ce 0a fc 56 7b  |L@....a..J....V{|
-000002a0  ef e3 19 60 62 18 97 7c  16 03 03 00 98 2f 65 76  |...`b..|...../ev|
-000002b0  15 2e 76 82 e8 70 6d c4  17 72 e7 30 9c 14 af d4  |..v..pm..r.0....|
-000002c0  0f 1e ec b5 5c 80 31 dc  15 fc 81 06 20 f1 e5 99  |....\.1..... ...|
-000002d0  67 c6 eb cc 77 57 2c 55  85 dc f9 9f 6f 19 7a d0  |g...wW,U....o.z.|
-000002e0  a0 45 17 b9 8c e4 19 46  ef dc 28 e1 e7 87 93 e0  |.E.....F..(.....|
-000002f0  c5 83 70 28 23 90 b9 c2  53 a3 67 d8 09 1f 47 0e  |..p(#...S.g...G.|
-00000300  a3 de bf a3 07 2d e7 3b  a5 e9 11 c4 30 59 fb cd  |.....-.;....0Y..|
-00000310  5d 6a d0 47 6f 43 a4 bd  2f 56 67 7d b2 c8 f5 2a  |]j.GoC../Vg}...*|
-00000320  9b ce ea 10 ec 83 f8 bc  87 19 c8 97 a9 ee 80 3c  |...............<|
-00000330  cb de 1a 22 60 ed 77 f7  57 5f 20 54 62 ca b0 e7  |..."`.w.W_ Tb...|
-00000340  75 a0 ba fc 32 14 03 03  00 11 86 a9 6a 14 1a 4c  |u...2.......j..L|
-00000350  1d 21 1f 3c c2 19 85 02  88 f5 f6 16 03 03 00 20  |.!.<........... |
-00000360  03 f9 fc ed cf 15 ed 86  d2 69 49 d7 e2 01 06 96  |.........iI.....|
-00000370  42 74 89 3f bf 98 56 0f  c1 1b 61 b6 36 3b ae 87  |Bt.?..V...a.6;..|
+00000000  16 03 03 02 69 d8 c1 81  7e a9 d7 70 97 62 c7 68  |....i...~..p.b.h|
+00000010  df 02 01 9d cc dc 38 d0  d6 bb 48 03 1d 0b be 73  |......8...H....s|
+00000020  b3 1a 88 91 a0 1b 55 91  51 a5 d7 54 58 c4 ea 50  |......U.Q..TX..P|
+00000030  e5 67 b1 60 78 b6 e2 7f  d7 6c b4 76 d7 24 fd af  |.g.`x....l.v.$..|
+00000040  f6 68 90 8c de 71 cd 15  4f d0 c8 f6 ba 89 ce 05  |.h...q..O.......|
+00000050  be 35 e8 9e 7a 8b 8d 0d  23 d4 5a bd 3a 9e d0 bf  |.5..z...#.Z.:...|
+00000060  80 08 f5 ad 7d 84 f1 8a  16 de 97 6b b2 75 8e 49  |....}......k.u.I|
+00000070  0f d7 8b 10 57 f7 21 1f  c0 87 de 06 c5 ae ae dd  |....W.!.........|
+00000080  9c 22 92 a1 6c c7 46 8d  e2 be 43 32 9c be 47 6b  |."..l.F...C2..Gk|
+00000090  4d 2a 60 f0 b6 3a 09 16  d6 16 a1 92 4a 2d 2d 72  |M*`..:......J--r|
+000000a0  00 8f 40 7c 3e a9 61 be  35 c8 f8 48 b4 1c 90 61  |..@|>.a.5..H...a|
+000000b0  90 c5 aa f8 ae aa d4 8a  15 74 b2 5d aa 24 cf 45  |.........t.].$.E|
+000000c0  ef 02 bd 29 b9 50 b4 fe  83 05 fa 4a a5 82 10 28  |...).P.....J...(|
+000000d0  b7 ab c3 ca c3 65 bb 51  a4 7c ac 57 03 78 28 e3  |.....e.Q.|.W.x(.|
+000000e0  91 9f c1 ce 02 08 70 84  8c 11 1f ae 35 a5 06 12  |......p.....5...|
+000000f0  f8 78 5b 38 0a 11 c8 1c  2d 1b 0c 21 66 d9 41 b2  |.x[8....-..!f.A.|
+00000100  ed 66 3c 47 f2 dc ab c1  59 7d 65 df bb 80 37 1c  |.f<G....Y}e...7.|
+00000110  5e 9b 41 e1 1d 5f b5 24  e4 77 61 3b e8 36 93 03  |^.A.._.$.wa;.6..|
+00000120  6d 87 17 e9 d7 77 35 b1  83 a3 b9 80 4d 40 20 82  |m....w5.....M@ .|
+00000130  94 36 53 94 ad 6b b3 ad  0a 70 fd 11 ce 81 56 ca  |.6S..k...p....V.|
+00000140  c2 5d 16 69 e3 59 7e 37  3b cd f3 54 1e b8 5e 1a  |.].i.Y~7;..T..^.|
+00000150  64 3f bf c6 ba ff fa b5  bf 4b c2 8e 5a 4d 43 1f  |d?.......K..ZMC.|
+00000160  8e 50 bc 7a 82 13 c7 25  aa b4 a8 97 45 49 12 25  |.P.z...%....EI.%|
+00000170  f5 4d 52 df 90 e5 74 0f  a0 d2 fd c3 6f bd 41 ed  |.MR...t.....o.A.|
+00000180  ff 78 e8 97 f2 e2 d1 5b  7c e6 27 01 16 27 1d b6  |.x.....[|.'..'..|
+00000190  8a cf c6 5b 8d b3 d8 8e  0c ee 2a d5 21 f6 4b d3  |...[......*.!.K.|
+000001a0  5a 74 7e 3d c6 fb 0e 35  97 de e7 52 c0 b2 c3 37  |Zt~=...5...R...7|
+000001b0  94 28 41 e0 3b 65 56 f1  4f 60 03 48 88 1d db fc  |.(A.;eV.O`.H....|
+000001c0  60 9f 33 e1 4d 37 eb 22  36 b2 76 ae 1c 3d 1c 5e  |`.3.M7."6.v..=.^|
+000001d0  3a c5 5b 00 eb 72 8b 54  ba 76 d1 71 77 5f 76 54  |:.[..r.T.v.qw_vT|
+000001e0  5f fd 0e d1 3a 50 ad b1  55 4a db 6d bf 2f 33 90  |_...:P..UJ.m./3.|
+000001f0  fc 42 de cd e4 a9 dd 11  25 d1 9f 56 1e 8a 2b 5c  |.B......%..V..+\|
+00000200  6c ed e7 51 84 42 6b ab  7d 77 b4 95 c3 75 b3 24  |l..Q.Bk.}w...u.$|
+00000210  ce 70 b0 e1 63 7f ec b0  ea 6a a4 a1 d5 e8 3e 96  |.p..c....j....>.|
+00000220  65 99 40 46 73 c8 e1 6e  86 65 92 bf 3d 92 a3 4f  |e.@Fs..n.e..=..O|
+00000230  37 6d bb 80 33 a5 7d aa  d3 a9 37 77 a6 4e 5b d6  |7m..3.}...7w.N[.|
+00000240  f3 f9 b2 42 75 18 1f 5a  58 f3 08 35 bc f4 2b 93  |...Bu..ZX..5..+.|
+00000250  62 0b 8a 83 f9 44 d0 e1  1a 44 b2 66 45 6f de b3  |b....D...D.fEo..|
+00000260  d2 ec 34 ac 15 89 76 b4  da dd 95 ca 44 5b 16 03  |..4...v.....D[..|
+00000270  03 00 35 39 e8 06 21 47  85 b5 53 96 03 0b 08 3b  |..59..!G..S....;|
+00000280  d2 9d 55 1f 23 4f 3a c0  be 4f e0 e0 0a f1 65 6f  |..U.#O:..O....eo|
+00000290  78 22 c4 10 6b d0 96 dc  04 78 e8 d3 95 f6 9a 78  |x"..k....x.....x|
+000002a0  09 f2 42 d3 79 57 99 c4  16 03 03 00 98 37 6b 75  |..B.yW.......7ku|
+000002b0  79 17 fa 67 7f 94 2e aa  88 61 91 97 dc 10 1e e6  |y..g.....a......|
+000002c0  6d 6d fa d5 64 17 f4 ec  ba 01 43 99 88 e2 a7 13  |mm..d.....C.....|
+000002d0  e0 9e 6a e9 97 c7 b3 ec  b9 c9 72 51 3d 01 eb c0  |..j.......rQ=...|
+000002e0  03 0f 08 48 90 27 36 6b  bd e7 0d 4e 41 6a ef 11  |...H.'6k...NAj..|
+000002f0  42 5b ae d1 16 ec 8f b7  47 a2 f5 b4 6a d4 32 bb  |B[......G...j.2.|
+00000300  0c cc 4f 2a e0 be 44 47  c8 77 09 f5 78 4b d6 ec  |..O*..DG.w..xK..|
+00000310  87 95 dc e1 74 75 54 af  45 bb 7a f5 2e f7 ac 3d  |....tuT.E.z....=|
+00000320  d1 b2 31 5a c0 24 c7 7c  25 36 62 a7 48 73 66 44  |..1Z.$.|%6b.HsfD|
+00000330  c1 78 47 f3 48 c5 a0 f7  66 3e 78 27 2c 3c dc 83  |.xG.H...f>x',<..|
+00000340  f5 6c e1 09 31 14 03 03  00 11 79 32 99 fd 2d 8d  |.l..1.....y2..-.|
+00000350  14 33 fd 1b 1b a8 3d 99  4b 0a b7 16 03 03 00 20  |.3....=.K...... |
+00000360  76 25 53 83 f2 c5 bf a6  fa 2e d3 5a 62 67 5b 1d  |v%S........Zbg[.|
+00000370  23 9a 9c b3 16 01 3f 6a  e9 4c ea e1 d4 d1 09 42  |#.....?j.L.....B|
 >>> Flow 10 (server to client)
-00000000  14 03 03 00 11 00 e4 ef  62 c1 c0 72 f3 98 4d 5a  |........b..r..MZ|
-00000010  6a c8 7e 29 92 b8 16 03  03 00 20 ff 7e fc cb b5  |j.~)...... .~...|
-00000020  07 5f ea 8a 89 2a 46 1b  c6 33 41 fe f9 f4 1e 3a  |._...*F..3A....:|
-00000030  9d 8b 1d 8f 9b 7b 89 07  b4 e8 59 17 03 03 00 19  |.....{....Y.....|
-00000040  a3 ba 0c 9b 54 cd 59 6a  e1 db 33 80 38 a9 95 a1  |....T.Yj..3.8...|
-00000050  95 5b a5 5f ad 3c d0 52  f7 16 03 03 00 14 e6 22  |.[._.<.R......."|
-00000060  84 a7 02 10 1e ee 58 88  a5 b8 e8 bf 0a 9b 61 46  |......X.......aF|
-00000070  0c ae                                             |..|
+00000000  14 03 03 00 11 a7 38 2a  4e 04 a5 b7 df d6 05 bb  |......8*N.......|
+00000010  b5 93 38 bc 9e 62 16 03  03 00 20 f3 d3 e1 7d 80  |..8..b.... ...}.|
+00000020  41 ce 05 99 92 c7 47 fe  b5 08 3b 78 9d ae b0 5f  |A.....G...;x..._|
+00000030  2c ed bd 0b 90 e0 94 9e  0b b0 a5 17 03 03 00 19  |,...............|
+00000040  27 f0 6a 55 af 3f c1 82  85 1a 6b 28 e1 cd dc 59  |'.jU.?....k(...Y|
+00000050  43 be c7 18 16 30 08 b2  9e 16 03 03 00 14 c1 c5  |C....0..........|
+00000060  64 ef 72 4f 6c 96 f1 f6  5b 70 29 e4 59 36 0a cd  |d.rOl...[p).Y6..|
+00000070  d2 a3                                             |..|
 >>> Flow 11 (client to server)
-00000000  15 03 03 00 12 7f 90 91  7b 93 4e 24 25 5e cb 35  |........{.N$%^.5|
-00000010  2c eb ee 29 6a b3 a3 15  03 03 00 12 3d b7 30 fe  |,..)j.......=.0.|
-00000020  63 90 c3 2d 17 a0 e1 ed  8d bb a4 f6 f6 17        |c..-..........|
+00000000  15 03 03 00 12 af 73 0e  40 39 dd 1e 04 99 3e 10  |......s.@9....>.|
+00000010  c9 62 b3 78 77 9b 56 15  03 03 00 12 25 8b 87 29  |.b.xw.V.....%..)|
+00000020  82 d0 9f 5e 9a 27 bd c1  bf b7 a2 f0 92 ac        |...^.'........|
index 3502977efa6472a5d8b3a5cf63547cb1f9fad897..f7a7668a8fbb043b4f8f5454db6afe7f30824715 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 9c d0 eb d6 42  |....Y...U......B|
-00000010  2e ff 6e 5a 19 33 6d 12  97 56 56 2b f5 1b 86 c8  |..nZ.3m..VV+....|
-00000020  38 83 59 37 ac 17 46 ed  73 53 43 20 e4 94 9b 71  |8.Y7..F.sSC ...q|
-00000030  f4 94 d9 d9 3a a1 e1 99  1e b4 a5 55 46 88 e0 0a  |....:......UF...|
-00000040  af 0a 0e ff 81 10 e2 e0  63 21 ae 2a cc a8 00 00  |........c!.*....|
+00000000  16 03 03 00 59 02 00 00  55 03 03 a3 55 d2 e2 bd  |....Y...U...U...|
+00000010  94 8f 04 51 26 1c a6 61  b1 ed 05 e2 39 44 33 05  |...Q&..a....9D3.|
+00000020  79 14 b7 1f 89 1e bb ba  53 0d 12 20 09 29 6d 26  |y.......S.. .)m&|
+00000030  04 70 4a 5d 01 90 f2 c6  28 df 11 6a 64 23 ec 9e  |.pJ]....(..jd#..|
+00000040  9f 2b 15 33 dc 88 26 35  3a b0 86 92 cc a8 00 00  |.+.3..&5:.......|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 59 0b 00 02 55 00  02 52 00 02 4f 30 82 02  |..Y...U..R..O0..|
 00000070  4b 30 82 01 b4 a0 03 02  01 02 02 09 00 e8 f0 9d  |K0..............|
 00000290  77 8d 0c 1c f1 0f a1 d8  40 83 61 c9 4c 72 2b 9d  |w.......@.a.Lr+.|
 000002a0  ae db 46 06 06 4d f4 c1  b3 3e c0 d1 bd 42 d4 db  |..F..M...>...B..|
 000002b0  fe 3d 13 60 84 5c 21 d3  3b e9 fa e7 16 03 03 00  |.=.`.\!.;.......|
-000002c0  ac 0c 00 00 a8 03 00 1d  20 9b 89 08 0d ea c2 d3  |........ .......|
-000002d0  4f 73 77 a0 e3 0e 1a 68  13 2c 5c a5 ec 39 75 1b  |Osw....h.,\..9u.|
-000002e0  c2 95 fe b8 fe 58 f4 bb  16 08 04 00 80 d4 e8 d3  |.....X..........|
-000002f0  d4 5b 1f ee ff 60 f5 86  b1 f4 06 c0 a8 ab 90 b0  |.[...`..........|
-00000300  26 15 d5 4e 3f d6 a5 e2  a3 3a e0 0f 9a 92 bd 96  |&..N?....:......|
-00000310  9d 98 15 f3 95 82 a9 5d  9f 1d 9b 4f 2e 77 58 40  |.......]...O.wX@|
-00000320  58 3d fd 8f a6 09 1c fa  61 77 2e 87 df e7 76 8b  |X=......aw....v.|
-00000330  bf f1 dd 29 f8 70 c0 6d  db e5 a0 55 92 77 44 75  |...).p.m...U.wDu|
-00000340  d9 95 a6 17 67 93 47 8e  1f 61 50 65 31 94 d3 79  |....g.G..aPe1..y|
-00000350  5f 25 a6 f0 3e 19 9a c8  ad b9 1a af 5b 50 2c 97  |_%..>.......[P,.|
-00000360  78 1e 71 3a e0 fa 7c 44  1e d1 32 56 4e 16 03 03  |x.q:..|D..2VN...|
+000002c0  ac 0c 00 00 a8 03 00 1d  20 43 6b 44 5b 79 c9 38  |........ CkD[y.8|
+000002d0  dc e4 ab fa 88 fa e6 06  89 b1 4e ff ab 8d d6 f7  |..........N.....|
+000002e0  21 b4 ff 9d a0 c8 54 cc  63 08 04 00 80 cd f4 d6  |!.....T.c.......|
+000002f0  c8 ad 03 e7 f0 e8 f4 c9  f0 e6 28 db cd 3b 7c bf  |..........(..;|.|
+00000300  05 af 3d fe c1 f9 f1 7a  ec 41 bf 1f a8 95 6d ee  |..=....z.A....m.|
+00000310  e6 92 cb c0 ff fd c1 ed  86 b0 59 45 3e 2d 1d 66  |..........YE>-.f|
+00000320  56 d1 9f e2 b7 79 ac aa  81 6d b0 42 36 96 80 4d  |V....y...m.B6..M|
+00000330  ca 36 29 1b 65 03 73 3f  85 ec 59 cb b4 a5 a0 c0  |.6).e.s?..Y.....|
+00000340  0c 16 ad e2 6b 35 3c ab  1e da 69 19 7d a2 63 a7  |....k5<...i.}.c.|
+00000350  69 2a d2 3f 12 17 bf 4c  ed 8a f7 75 fe ce d4 2b  |i*.?...L...u...+|
+00000360  4d 35 bf 65 d6 9e 01 69  a8 0a 73 26 34 16 03 03  |M5.e...i..s&4...|
 00000370  00 04 0e 00 00 00                                 |......|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 25 10 00 00  21 20 2f e5 7d a3 47 cd  |....%...! /.}.G.|
 00000010  62 43 15 28 da ac 5f bb  29 07 30 ff f6 84 af c4  |bC.(.._.).0.....|
 00000020  cf c2 ed 90 99 5f 58 cb  3b 74 14 03 03 00 01 01  |....._X.;t......|
-00000030  16 03 03 00 20 88 fe 97  82 bd a7 99 c6 a6 2f c1  |.... ........./.|
-00000040  1a a8 54 8c e5 c6 39 0a  6b 07 9b 1a 05 f4 fb e3  |..T...9.k.......|
-00000050  67 f5 c8 6e 17                                    |g..n.|
+00000030  16 03 03 00 20 b8 d8 22  20 8d 69 23 05 34 eb 69  |.... .." .i#.4.i|
+00000040  92 a0 a9 6c cd 94 3b 72  49 91 72 8e 65 79 ca 62  |...l..;rI.r.ey.b|
+00000050  14 cf da 2e b6                                    |.....|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 20 3b 6d ac 1c 8b  |.......... ;m...|
-00000010  1b 46 3a 4e 03 75 51 9e  99 6e 5a a8 4f 07 91 a3  |.F:N.uQ..nZ.O...|
-00000020  18 2c bf 88 92 17 e5 13  65 a3 6c                 |.,......e.l|
+00000000  14 03 03 00 01 01 16 03  03 00 20 31 25 d4 c7 92  |.......... 1%...|
+00000010  16 0b 92 2d a2 20 8b b2  c7 96 a6 b7 b6 b3 82 3a  |...-. .........:|
+00000020  4d a1 a8 96 29 fb 99 e9  ea 04 6c                 |M...).....l|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 16 c7 94 fc  be 3d 73 fd ec ce b2 f6  |.........=s.....|
-00000010  bf 17 bf 52 3e b4 98 39  43 c0 0a                 |...R>..9C..|
+00000000  17 03 03 00 16 8b 92 f3  f8 99 bf a3 7c c4 03 d8  |............|...|
+00000010  4d e7 1b ad 50 e1 99 17  33 68 e2                 |M...P...3h.|
 >>> Flow 6 (server to client)
-00000000  16 03 03 00 14 cf 01 f5  e6 eb 60 e3 49 c4 fb 84  |..........`.I...|
-00000010  e1 11 69 e1 91 c0 02 d2  e3                       |..i......|
+00000000  16 03 03 00 14 91 99 15  68 ae 92 52 bd 13 75 45  |........h..R..uE|
+00000010  6d a9 f0 2d ee f5 c3 9b  e7                       |m..-.....|
 >>> Flow 7 (client to server)
-00000000  15 03 03 00 12 4d 7f de  01 23 f7 3f 0d e6 1a f1  |.....M...#.?....|
-00000010  19 a2 cd 58 1a 25 f5 15  03 03 00 12 95 78 52 00  |...X.%.......xR.|
-00000020  65 aa 6d 77 5a 66 d5 95  c4 5a 9b 1b 05 b2        |e.mwZf...Z....|
+00000000  15 03 03 00 12 be 8b 4b  a6 a7 7a 62 45 32 ff db  |.......K..zbE2..|
+00000010  07 ad a0 1b 46 9d c9 15  03 03 00 12 16 da d4 86  |....F...........|
+00000020  4f c8 26 5a d0 34 82 fe  47 34 ae 31 db a7        |O.&Z.4..G4.1..|
index d12e263e15350afdac415e4d33d1b0246df3548d..8492ee94c4f97e27dac0c08afcc465225f6ec533 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 01 c6 02 00 01  c2 03 03 d8 a9 75 cc 9a  |.............u..|
-00000010  81 df 5a a0 3b ba 51 74  52 50 72 08 35 02 35 77  |..Z.;.QtRPr.5.5w|
-00000020  28 ff 44 e6 d9 c6 8b f8  54 67 b4 20 62 80 60 cc  |(.D.....Tg. b.`.|
-00000030  09 90 52 66 75 72 a2 c5  dc 8d 18 ce 9a d5 7e cd  |..Rfur........~.|
-00000040  a5 36 2a 2e 65 72 6f f0  dd b0 8c 14 cc a8 00 01  |.6*.ero.........|
+00000000  16 03 03 01 c6 02 00 01  c2 03 03 b0 59 eb bc ae  |............Y...|
+00000010  f3 42 03 d1 fe 2c 7d 6f  0e ff e4 0c 9e 13 00 b9  |.B...,}o........|
+00000020  46 99 e2 84 49 64 a9 05  05 8a fb 20 16 12 dc b7  |F...Id..... ....|
+00000030  e0 09 a2 a6 56 83 43 54  de 40 53 47 43 f0 2f c9  |....V.CT.@SGC./.|
+00000040  2d 92 5e a0 9d a3 6a c4  55 17 01 cb cc a8 00 01  |-.^...j.U.......|
 00000050  7a 00 12 01 69 01 67 00  75 00 a4 b9 09 90 b4 18  |z...i.g.u.......|
 00000060  58 14 87 bb 13 a2 cc 67  70 0a 3c 35 98 04 f9 1b  |X......gp.<5....|
 00000070  df b8 e3 77 cd 0e c8 0d  dc 10 00 00 01 47 97 99  |...w.........G..|
 00000400  1c f1 0f a1 d8 40 83 61  c9 4c 72 2b 9d ae db 46  |.....@.a.Lr+...F|
 00000410  06 06 4d f4 c1 b3 3e c0  d1 bd 42 d4 db fe 3d 13  |..M...>...B...=.|
 00000420  60 84 5c 21 d3 3b e9 fa  e7 16 03 03 00 ac 0c 00  |`.\!.;..........|
-00000430  00 a8 03 00 1d 20 cd 2a  10 ee 97 4a 83 7b 0e 6d  |..... .*...J.{.m|
-00000440  e7 00 5a ce bc d8 1c 57  fa f6 ec 52 0d 0f be 6d  |..Z....W...R...m|
-00000450  c8 5d 27 3c 8c 1b 08 04  00 80 a9 4c bb 3a 0a d7  |.]'<.......L.:..|
-00000460  db 72 3d 88 49 a6 0b f7  dc d5 e1 d0 07 e8 6c fa  |.r=.I.........l.|
-00000470  b0 5e 0b 13 27 29 6f 1f  1e b9 05 60 16 cc ea 7b  |.^..')o....`...{|
-00000480  46 d7 12 58 03 43 b0 fe  8e 7b 83 3b ee 11 78 8c  |F..X.C...{.;..x.|
-00000490  60 0f 9c 76 63 60 01 78  a0 9b 19 b9 32 99 a9 9d  |`..vc`.x....2...|
-000004a0  42 b8 1f f1 8b 87 07 32  fa 5e 74 d5 3e 5e ba 21  |B......2.^t.>^.!|
-000004b0  ff 63 b7 c6 68 bc b3 f9  52 1a ea 23 c7 f2 ec ff  |.c..h...R..#....|
-000004c0  d4 10 0d f8 76 2f bc 0d  e5 12 7f ee d3 8d 9e 6b  |....v/.........k|
-000004d0  5e 22 78 d6 fa 5e 6a 53  16 44 16 03 03 00 04 0e  |^"x..^jS.D......|
+00000430  00 a8 03 00 1d 20 4c 46  c9 9f ed 2e 81 0f 8c 4b  |..... LF.......K|
+00000440  bc 05 53 74 c6 c8 76 99  21 94 1b 8f 93 c6 64 ce  |..St..v.!.....d.|
+00000450  e9 9d 6b 1d 66 51 08 04  00 80 09 9e c2 21 89 93  |..k.fQ.......!..|
+00000460  1f c5 2e 2c fa 67 7b 42  23 e1 e0 67 5c 6d e9 1e  |...,.g{B#..g\m..|
+00000470  e8 a2 ac d7 cf f4 12 98  f6 e6 3d 51 0c 2c 29 ad  |..........=Q.,).|
+00000480  f8 8e 24 2a a3 99 2e f3  b2 a7 fe a9 6c e9 00 d8  |..$*........l...|
+00000490  6a 7f 41 12 84 a0 d6 19  38 b1 5a 13 b6 71 cf bd  |j.A.....8.Z..q..|
+000004a0  e2 6e 04 01 c8 cd 83 12  71 85 ae bc 94 b1 e4 4d  |.n......q......M|
+000004b0  a5 5f 9e a5 5d 95 76 fe  f5 d6 a9 f0 4c 07 c9 6e  |._..].v.....L..n|
+000004c0  fc 4a 56 2b 56 4e 9c ec  2c fe bc 9c 9e 57 f3 90  |.JV+VN..,....W..|
+000004d0  c6 6e 77 5a cf 8c 1a 15  cd 90 16 03 03 00 04 0e  |.nwZ............|
 000004e0  00 00 00                                          |...|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 25 10 00 00  21 20 2f e5 7d a3 47 cd  |....%...! /.}.G.|
 00000010  62 43 15 28 da ac 5f bb  29 07 30 ff f6 84 af c4  |bC.(.._.).0.....|
 00000020  cf c2 ed 90 99 5f 58 cb  3b 74 14 03 03 00 01 01  |....._X.;t......|
-00000030  16 03 03 00 20 5c 1a 1b  0e 7e 83 4f 9b f6 8e 9f  |.... \...~.O....|
-00000040  ca 95 86 c3 7b 60 73 d3  8d 3c 6d 18 6a eb 70 a3  |....{`s..<m.j.p.|
-00000050  d9 08 f7 77 a3                                    |...w.|
+00000030  16 03 03 00 20 19 bf ac  05 d4 bb 8a 6d 11 f4 98  |.... .......m...|
+00000040  0d af 78 57 49 74 5c 44  45 9e 2c 92 26 b9 10 b5  |..xWIt\DE.,.&...|
+00000050  6d 5f 24 bc a6                                    |m_$..|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 20 1f a2 50 dd c5  |.......... ..P..|
-00000010  ba 96 4a 63 e1 cc b6 45  77 09 c1 49 cb 5f eb 4b  |..Jc...Ew..I._.K|
-00000020  38 9b b1 40 1c af b1 a2  dc 7c ba                 |8..@.....|.|
+00000000  14 03 03 00 01 01 16 03  03 00 20 69 3a c4 9c ee  |.......... i:...|
+00000010  91 6b bc 33 39 82 64 c2  0a f0 a4 dd 85 16 3c ce  |.k.39.d.......<.|
+00000020  39 c4 98 37 77 47 1e c2  c6 d8 f6                 |9..7wG.....|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 16 e7 54 f6  bf 56 39 57 c4 b2 ac f2  |......T..V9W....|
-00000010  b1 f4 b1 2f ad ae d7 87  21 ff 1c 15 03 03 00 12  |.../....!.......|
-00000020  5d b6 56 77 55 99 b6 7b  a4 0b d8 8e 8d 93 b6 35  |].VwU..{.......5|
-00000030  ce 9a                                             |..|
+00000000  17 03 03 00 16 92 25 9b  97 11 08 71 63 b2 c1 35  |......%....qc..5|
+00000010  14 3b e7 15 f6 05 67 51  46 db ba 15 03 03 00 12  |.;....gQF.......|
+00000020  b2 53 a1 ec a8 cf 79 7d  f8 86 70 05 e5 81 a1 6c  |.S....y}..p....l|
+00000030  41 ab                                             |A.|
index d58a32f2b3732c7a0c7ad0d8a6954c12472f6955..3d3de611d09b095a48be87f2e14880d16b53e296 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 75 00 05 00 05  01 00 00 00 00 00 0a 00  |...u............|
 00000090  04 00 02 00 1d 00 0b 00  02 01 00 00 0d 00 1a 00  |................|
 000000a0  18 08 04 04 03 08 07 08  05 08 06 04 01 05 01 06  |................|
 000000e0  43 15 28 da ac 5f bb 29  07 30 ff f6 84 af c4 cf  |C.(.._.).0......|
 000000f0  c2 ed 90 99 5f 58 cb 3b  74                       |...._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 e0 c7 ce be 3a  |....Y...U......:|
-00000010  a6 34 5f b7 c5 ec f1 f3  09 df 4d db 39 60 71 93  |.4_.......M.9`q.|
-00000020  db 7c 30 e0 81 93 f0 19  57 6b 6b 20 9e 4b e2 1e  |.|0.....Wkk .K..|
-00000030  27 8d d3 f6 0c f3 3d bc  67 3e 79 33 fd c9 cc 55  |'.....=.g>y3...U|
-00000040  36 55 a5 aa 89 94 fe b2  51 cf 24 56 c0 2f 00 00  |6U......Q.$V./..|
+00000000  16 03 03 00 59 02 00 00  55 03 03 f7 79 97 18 3c  |....Y...U...y..<|
+00000010  fa 52 c6 d2 6b 1e de a5  60 da d5 e2 0b f6 23 a8  |.R..k...`.....#.|
+00000020  48 94 e8 1f fb b9 76 43  94 e8 98 20 31 a5 85 d5  |H.....vC... 1...|
+00000030  2f c4 93 b1 ae aa 50 bc  14 9e 57 79 18 85 cd ef  |/.....P...Wy....|
+00000040  b4 f0 42 c9 6c b1 86 c1  03 27 ca df c0 2f 00 00  |..B.l....'.../..|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 59 0b 00 02 55 00  02 52 00 02 4f 30 82 02  |..Y...U..R..O0..|
 00000070  4b 30 82 01 b4 a0 03 02  01 02 02 09 00 e8 f0 9d  |K0..............|
 00000290  77 8d 0c 1c f1 0f a1 d8  40 83 61 c9 4c 72 2b 9d  |w.......@.a.Lr+.|
 000002a0  ae db 46 06 06 4d f4 c1  b3 3e c0 d1 bd 42 d4 db  |..F..M...>...B..|
 000002b0  fe 3d 13 60 84 5c 21 d3  3b e9 fa e7 16 03 03 00  |.=.`.\!.;.......|
-000002c0  ac 0c 00 00 a8 03 00 1d  20 9b 73 58 2f 9a aa 8b  |........ .sX/...|
-000002d0  3e 80 1c b1 8e e5 d4 54  c2 d0 b1 94 16 86 e2 4b  |>......T.......K|
-000002e0  9c ab d7 ce 2c e5 26 20  04 08 04 00 80 d8 c0 18  |....,.& ........|
-000002f0  90 8e 06 d8 d6 4c af a1  ae 5e ca 4b a1 18 bb 31  |.....L...^.K...1|
-00000300  f5 3a 75 c3 d7 73 69 a7  e0 0f 8e f2 c5 92 0a bd  |.:u..si.........|
-00000310  7f 91 36 6c 01 c3 eb 08  9a 3b 25 2c bd 86 88 05  |..6l.....;%,....|
-00000320  64 e0 38 5b 75 01 10 1f  1b d5 34 09 04 2e 34 6d  |d.8[u.....4...4m|
-00000330  71 d2 6c b6 f3 7a 1e ed  a9 9d 28 60 13 fc 02 6f  |q.l..z....(`...o|
-00000340  f6 17 99 52 7b 19 60 e5  a6 11 d4 b3 4c 52 03 b5  |...R{.`.....LR..|
-00000350  3e 28 91 c6 66 87 25 df  10 c6 cf b9 5f 92 0e d7  |>(..f.%....._...|
-00000360  b6 19 f0 19 b9 f6 e9 e9  24 74 35 3b c6 16 03 03  |........$t5;....|
+000002c0  ac 0c 00 00 a8 03 00 1d  20 90 95 bd 82 cf 8a cc  |........ .......|
+000002d0  08 b4 09 09 8d 59 2d 03  7a bb 92 4a c4 5c 08 4d  |.....Y-.z..J.\.M|
+000002e0  42 a3 ba cb 9a 43 ae f0  22 08 04 00 80 a0 97 ac  |B....C..".......|
+000002f0  01 a5 c8 7b 4c 73 7e 70  7a 9a fc 9d 71 2f fe 67  |...{Ls~pz...q/.g|
+00000300  ca dd 6b 43 db 64 0f 64  52 e7 d3 5d 6d b2 7c 50  |..kC.d.dR..]m.|P|
+00000310  74 7e 80 d5 22 77 3f fb  c2 e8 dc 92 37 4f 1e 1e  |t~.."w?.....7O..|
+00000320  e7 13 f2 01 33 80 32 66  4f c2 17 8e ec 4f ed 4a  |....3.2fO....O.J|
+00000330  15 6c e8 86 ec df d5 46  6c a5 43 0d 40 fe a0 c8  |.l.....Fl.C.@...|
+00000340  65 b4 76 46 b8 36 2c da  87 7c 60 87 db 39 4c 2e  |e.vF.6,..|`..9L.|
+00000350  0f e4 72 32 11 26 99 7e  c8 7a c0 bc 9c a7 29 57  |..r2.&.~.z....)W|
+00000360  9d 27 37 4e ec c5 bb fd  a1 3c f3 66 63 16 03 03  |.'7N.....<.fc...|
 00000370  00 04 0e 00 00 00                                 |......|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 25 10 00 00  21 20 2f e5 7d a3 47 cd  |....%...! /.}.G.|
 00000010  62 43 15 28 da ac 5f bb  29 07 30 ff f6 84 af c4  |bC.(.._.).0.....|
 00000020  cf c2 ed 90 99 5f 58 cb  3b 74 14 03 03 00 01 01  |....._X.;t......|
-00000030  16 03 03 00 28 00 00 00  00 00 00 00 00 01 e4 5a  |....(..........Z|
-00000040  e9 dc dd 98 cd 5f d2 d2  eb 84 12 c9 96 ca 91 d7  |....._..........|
-00000050  ae f4 db 44 a4 37 f3 a3  b2 8d db ed 3d           |...D.7......=|
+00000030  16 03 03 00 28 00 00 00  00 00 00 00 00 81 b1 2c  |....(..........,|
+00000040  a2 3b 38 34 a6 66 57 02  e3 67 1b ee 73 95 50 de  |.;84.fW..g..s.P.|
+00000050  dd 5a fd 4e 0d ee b7 a6  46 1a 34 61 73           |.Z.N....F.4as|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 28 c2 2d 32 ba 46  |..........(.-2.F|
-00000010  27 8d 87 13 7f b9 49 04  64 2f 6e cc 32 81 f8 3c  |'.....I.d/n.2..<|
-00000020  7f 0f 19 13 5c 11 33 a1  05 5f 91 bc 97 30 64 84  |....\.3.._...0d.|
-00000030  57 69 90                                          |Wi.|
+00000000  14 03 03 00 01 01 16 03  03 00 28 2f a9 80 36 d8  |..........(/..6.|
+00000010  d0 74 e4 39 46 04 88 8e  91 ea fd 96 ed 1f 89 9f  |.t.9F...........|
+00000020  a4 e9 24 0e ca 48 2b 5c  5d f1 cc 57 ce 92 1a ad  |..$..H+\]..W....|
+00000030  b9 10 11                                          |...|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 fd 0f a5  |................|
-00000010  74 98 c4 98 ee 67 74 d4  c1 d4 fe d3 c7 e2 1b 2c  |t....gt........,|
-00000020  e5 3c be 15 03 03 00 1a  00 00 00 00 00 00 00 02  |.<..............|
-00000030  f8 d4 60 41 13 6a 9c e3  0e 56 e2 ab 96 45 7e 06  |..`A.j...V...E~.|
-00000040  87 63                                             |.c|
+00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 da be 68  |...............h|
+00000010  97 b4 a4 72 d0 ed 75 66  6a a9 6f 39 8a 08 a9 db  |...r..ufj.o9....|
+00000020  de 4d e1 15 03 03 00 1a  00 00 00 00 00 00 00 02  |.M..............|
+00000030  14 90 0e 1d 26 5c 18 c6  5c 93 66 c4 90 78 a8 91  |....&\..\.f..x..|
+00000040  cb fd                                             |..|
index 4273484ca710c86b4c1f5ddb809571af9fccb360..f8a733e3c29d50d5aff6357ee8470abfef52e491 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 7a 02 00 00  76 03 03 f7 30 f3 d1 e7  |....z...v...0...|
-00000010  eb 94 97 a2 c6 d5 be 74  e0 6c 08 80 2f ad 11 6b  |.......t.l../..k|
-00000020  b3 ce 22 59 06 a9 eb 41  9c 97 a8 20 00 00 00 00  |.."Y...A... ....|
+00000000  16 03 03 00 7a 02 00 00  76 03 03 f1 4c f4 16 24  |....z...v...L..$|
+00000010  e5 c6 b5 ce 72 08 3b 33  9f 1f 1f 80 2c 10 0b 34  |....r.;3....,..4|
+00000020  01 99 85 ba b0 3c 85 50  3d bf 73 20 00 00 00 00  |.....<.P=.s ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 01 00 00  |................|
-00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 c0  |..+.....3.$... .|
-00000060  47 7e ad a1 41 53 e5 25  ec 74 46 bc 9e 80 08 3b  |G~..AS.%.tF....;|
-00000070  0b f5 7e fb 71 1f 00 d5  4b 27 51 22 4a 5e 5f 14  |..~.q...K'Q"J^_.|
-00000080  03 03 00 01 01 17 03 03  00 17 e9 e8 56 00 26 9e  |............V.&.|
-00000090  92 60 84 6c 07 3d b1 ef  e4 63 51 ba 48 ee d7 fe  |.`.l.=...cQ.H...|
-000000a0  57 17 03 03 02 6d 2e d4  bb bf a2 e8 3b 84 47 2e  |W....m......;.G.|
-000000b0  22 66 c1 98 ea 11 6b a3  4d 1b 64 c0 02 32 76 9b  |"f....k.M.d..2v.|
-000000c0  29 8a 4a 96 68 5b d1 fd  a0 0f a6 9b 70 20 c7 08  |).J.h[......p ..|
-000000d0  7b 25 07 d1 54 8c b1 bb  4e ba 32 65 2c 1e 16 29  |{%..T...N.2e,..)|
-000000e0  e7 d2 df e3 84 60 e1 43  07 99 35 4d 95 7c 27 96  |.....`.C..5M.|'.|
-000000f0  be f4 bf 0a e9 3b 9d 60  7a 6e 34 82 1f 03 ca 17  |.....;.`zn4.....|
-00000100  ac d1 a1 b5 dc 3f 20 7b  42 f6 94 43 60 ff 3f 1b  |.....? {B..C`.?.|
-00000110  b1 2e 2d 71 55 07 fb 65  40 56 59 82 1e 31 83 c9  |..-qU..e@VY..1..|
-00000120  35 6c 28 ad c1 bd 88 55  1b b6 1e 89 af 64 7f 11  |5l(....U.....d..|
-00000130  53 80 3a 62 ef 34 a7 d0  ce 38 9b 19 d6 5f 78 0d  |S.:b.4...8..._x.|
-00000140  66 73 b2 bd b6 a6 f8 70  c8 40 f9 aa a2 86 f4 48  |fs.....p.@.....H|
-00000150  0d 6c 54 67 c6 3c 91 97  ff 94 4d 9a 01 d5 e1 c9  |.lTg.<....M.....|
-00000160  8f 27 d3 8d b3 72 cd 34  eb 7a 6d 48 84 f3 8b 84  |.'...r.4.zmH....|
-00000170  34 d2 68 bd 26 bc 6d e5  46 41 cc 86 d4 7a b6 31  |4.h.&.m.FA...z.1|
-00000180  05 b3 bc a4 fe e1 5c d4  eb 8b fe 64 0e be 89 c4  |......\....d....|
-00000190  ce e0 49 a0 ba 7a 83 b6  fb 31 17 42 fd b4 e3 59  |..I..z...1.B...Y|
-000001a0  48 df f6 a8 e4 5c d1 77  77 cb c2 31 85 8a 26 65  |H....\.ww..1..&e|
-000001b0  20 fa 05 90 ae 66 95 7a  75 4b bc 93 15 dd a0 13  | ....f.zuK......|
-000001c0  61 d5 99 fb b2 27 bd ec  fd 10 b5 d2 c7 18 ac b9  |a....'..........|
-000001d0  bd bc 35 72 d0 42 6c f7  5a e0 67 46 45 10 f7 50  |..5r.Bl.Z.gFE..P|
-000001e0  e4 14 47 ac 39 5a 05 38  b9 25 4a 43 fa 57 b2 51  |..G.9Z.8.%JC.W.Q|
-000001f0  b7 3e f7 ef d5 b5 de 2e  2f 5c d0 d7 00 23 ac 4b  |.>....../\...#.K|
-00000200  65 8d 6c f4 ab 6f ef 1e  c2 66 c5 b2 cb 1a 51 4c  |e.l..o...f....QL|
-00000210  ef 96 8f 28 65 2f 50 9c  91 1f 73 87 fc 81 db 90  |...(e/P...s.....|
-00000220  16 69 00 06 98 6b 00 33  41 e1 e6 12 89 cb c9 f3  |.i...k.3A.......|
-00000230  23 2c 28 83 00 ca 4f 42  f5 26 bc 94 39 3b 18 31  |#,(...OB.&..9;.1|
-00000240  41 a9 19 4a 60 e8 de 8f  1d d0 e8 96 77 c0 49 bd  |A..J`.......w.I.|
-00000250  a2 98 bd b1 0a 6f bd 27  79 1d c4 33 50 37 a8 eb  |.....o.'y..3P7..|
-00000260  a5 4e 59 87 58 cd f0 a0  34 4e 2b 9d ee 03 e4 8a  |.NY.X...4N+.....|
-00000270  24 94 86 11 e1 94 f0 2b  3e 27 9a 92 1c 17 d3 96  |$......+>'......|
-00000280  c0 71 ab ee 75 5f 99 ca  0e 42 65 5d ed 48 0c 7a  |.q..u_...Be].H.z|
-00000290  95 8a d9 da f7 60 ee de  46 f2 f4 7a d6 ce 38 41  |.....`..F..z..8A|
-000002a0  fa e8 1f 3e 77 be 02 53  0c 33 96 5b 0d 38 bb 08  |...>w..S.3.[.8..|
-000002b0  5e 92 1a 81 f1 be c7 9a  e2 02 80 09 3b b7 62 b0  |^...........;.b.|
-000002c0  7c a7 85 3a d9 52 34 23  4f a3 04 e7 35 98 9e 18  ||..:.R4#O...5...|
-000002d0  13 0b 71 12 6d a4 2e 11  bf 39 8c 94 ef 15 96 27  |..q.m....9.....'|
-000002e0  9e be 81 d9 55 5a 8b 14  c5 49 dd 6e 6e 7b 6b c2  |....UZ...I.nn{k.|
-000002f0  f3 7d ef 24 88 b9 eb a6  15 3e aa a8 3e eb 37 54  |.}.$.....>..>.7T|
-00000300  fc 86 9f 51 30 5f 9c a5  fc 7a af f6 1b a5 a4 27  |...Q0_...z.....'|
-00000310  51 78 f7 17 03 03 00 99  79 14 63 10 91 cd 73 f5  |Qx......y.c...s.|
-00000320  a8 62 c3 92 a3 04 c2 3d  58 5e d3 6e 93 eb 9b b1  |.b.....=X^.n....|
-00000330  11 f0 3c c6 96 9f c6 c8  9b de 2c d5 12 c2 bd d1  |..<.......,.....|
-00000340  2a 68 89 4a 07 1e 23 d2  45 ca a1 0f 92 71 b7 f7  |*h.J..#.E....q..|
-00000350  d0 2f 2a be d0 5e 0c 5d  13 8f b0 7f df b8 52 2e  |./*..^.]......R.|
-00000360  7a 5e c8 eb 84 06 46 81  d0 f7 09 18 52 fb ce fd  |z^....F.....R...|
-00000370  22 d8 74 71 e8 7d 41 5f  3a 5d e5 f9 bb e6 99 03  |".tq.}A_:]......|
-00000380  32 d1 58 e8 5a 58 d8 b2  39 61 01 33 72 7d d2 11  |2.X.ZX..9a.3r}..|
-00000390  8f f7 58 55 c8 f2 64 63  33 9b 78 36 bf 9b 8b 40  |..XU..dc3.x6...@|
-000003a0  8c ec 7b a2 bb 51 ed b1  fe 74 c2 c9 1f b4 2b cb  |..{..Q...t....+.|
-000003b0  fd 17 03 03 00 35 75 46  88 74 06 9b 5e 88 c2 0d  |.....5uF.t..^...|
-000003c0  fc 7d 29 bd 6c 1c 23 2f  06 3f 14 b1 55 e4 98 b1  |.}).l.#/.?..U...|
-000003d0  ed c3 9a ed ea be 29 60  15 ac 80 c7 a8 f7 9b ce  |......)`........|
-000003e0  f3 79 b3 be ad ff ab b4  a7 45 57                 |.y.......EW|
+00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 69  |..+.....3.$... i|
+00000060  94 3b 83 cd 1f 93 53 53  82 de 14 cb 76 2a 19 62  |.;....SS....v*.b|
+00000070  0f f8 9e d1 e3 e0 a9 d5  23 ac 07 64 53 27 4b 14  |........#..dS'K.|
+00000080  03 03 00 01 01 17 03 03  00 17 ef 24 2c ea 6f 05  |...........$,.o.|
+00000090  c2 07 7a d2 12 30 ce 01  f4 96 b8 dc e6 c2 27 02  |..z..0........'.|
+000000a0  bd 17 03 03 02 6d 99 2b  cb 79 43 01 66 24 eb f1  |.....m.+.yC.f$..|
+000000b0  14 d2 ea 1e 57 67 81 e3  a0 9c 99 1b 1f d5 f0 c7  |....Wg..........|
+000000c0  78 48 61 01 42 25 85 0b  cd a1 b1 75 3c 50 01 cc  |xHa.B%.....u<P..|
+000000d0  69 09 22 a5 fb db 43 76  2f 4e 34 4e 14 a3 e4 89  |i."...Cv/N4N....|
+000000e0  f7 d7 cd 66 da b3 1d fd  f0 98 60 18 41 09 a5 22  |...f......`.A.."|
+000000f0  6d c9 21 bc c3 cd 53 ca  c3 a5 d7 24 57 b4 f5 bc  |m.!...S....$W...|
+00000100  ec b1 48 70 12 55 a5 a6  01 10 68 0f c4 e5 de 89  |..Hp.U....h.....|
+00000110  f9 0d ab 48 92 d4 12 d7  75 77 c3 2f ae 2f 6f 58  |...H....uw././oX|
+00000120  2d 6e ad 72 43 dc ce 4b  c9 74 3d eb db da 37 2c  |-n.rC..K.t=...7,|
+00000130  1e a2 86 c4 b3 64 69 f6  84 ce 52 b5 32 c6 b9 c2  |.....di...R.2...|
+00000140  49 2d 08 f9 d4 9a 29 09  5b 71 09 81 a3 19 c2 4d  |I-....).[q.....M|
+00000150  8c 48 2c e3 c6 cb 81 d4  7f 10 b3 c8 2b 21 ad 83  |.H,.........+!..|
+00000160  97 d2 bd 11 90 39 1e f4  de 65 e2 e8 e8 c7 ce f9  |.....9...e......|
+00000170  6d ad b0 60 5c 4b 59 c4  96 ce b3 a1 83 b2 7c 71  |m..`\KY.......|q|
+00000180  74 e6 a9 a7 89 bf 8d 0d  6c 8d b5 04 33 38 ff 68  |t.......l...38.h|
+00000190  42 0e 84 da d2 b2 16 29  83 66 82 a9 2a d2 67 1b  |B......).f..*.g.|
+000001a0  18 a6 7d e3 f1 d3 f1 b4  cc 6c 14 e2 cd 2d 96 7b  |..}......l...-.{|
+000001b0  76 dd b0 1d 24 7f ea c0  14 24 d7 37 00 7c cd e3  |v...$....$.7.|..|
+000001c0  20 33 a4 3a 22 2a be 3e  e8 f8 7c 0d 3e 51 f7 6b  | 3.:"*.>..|.>Q.k|
+000001d0  ce f3 51 cf 7e ae 55 40  bb ab 0e 40 6b d9 8a 3b  |..Q.~.U@...@k..;|
+000001e0  d5 f2 1f 76 6a 05 9b 87  e2 3b db fa cc e8 93 8a  |...vj....;......|
+000001f0  d9 ba 2b 63 77 77 62 f1  22 ce 11 a9 26 b5 e8 a2  |..+cwwb."...&...|
+00000200  ec 3f 98 44 01 27 d7 e1  39 26 33 e3 86 00 60 f7  |.?.D.'..9&3...`.|
+00000210  a7 91 07 45 f8 3f 78 dc  88 71 30 26 0c f9 0d 51  |...E.?x..q0&...Q|
+00000220  2a c5 ce 33 ac b7 91 a9  74 2e 46 68 80 6e 62 cd  |*..3....t.Fh.nb.|
+00000230  2d 5e 43 fe bd d1 37 07  71 85 5d c7 38 17 50 3a  |-^C...7.q.].8.P:|
+00000240  1c 5e 9f cf 1e 3c 96 d0  26 5d 4c 82 78 a8 69 e7  |.^...<..&]L.x.i.|
+00000250  d3 9a 81 e5 85 66 c3 d9  74 a1 82 9d fb 24 81 13  |.....f..t....$..|
+00000260  0d ce cb 43 61 3c 3a a7  d1 80 7f 1d 41 d8 62 43  |...Ca<:.....A.bC|
+00000270  c6 08 5d 91 05 ed 2c 50  04 42 8c db 2a 11 61 96  |..]...,P.B..*.a.|
+00000280  9b d2 1d 40 af 83 ed 93  06 ba 65 22 0a a5 e8 a6  |...@......e"....|
+00000290  b9 4a 63 6f c0 ac da 72  10 24 c6 ed 08 86 c8 a1  |.Jco...r.$......|
+000002a0  92 5e d0 d8 8b 04 b7 43  50 0b 03 41 3f f9 96 16  |.^.....CP..A?...|
+000002b0  a3 c8 09 e8 ac 91 b2 45  d5 58 5f 41 05 7c b3 88  |.......E.X_A.|..|
+000002c0  7a 59 cd 1a 00 86 29 72  77 a5 19 43 32 79 fc d6  |zY....)rw..C2y..|
+000002d0  d7 e9 81 08 e3 d9 d9 56  39 59 7c 1e d3 10 3e a4  |.......V9Y|...>.|
+000002e0  c6 80 d3 8b 9b 36 51 c5  d3 14 64 a6 65 e2 1a 26  |.....6Q...d.e..&|
+000002f0  c4 a8 31 07 bb 58 8c 9b  d8 7d 86 fd 54 6c c9 ae  |..1..X...}..Tl..|
+00000300  7d 88 4b 13 0f 52 10 41  d6 be 01 32 f2 42 47 0f  |}.K..R.A...2.BG.|
+00000310  7a 8c 7e 17 03 03 00 99  8b ce c4 db 9c 9c 88 e3  |z.~.............|
+00000320  88 58 de 8f 10 e9 fb 4a  c7 26 96 60 48 84 2c b1  |.X.....J.&.`H.,.|
+00000330  2b 6c 35 70 8a d7 39 91  51 d7 3f db 81 f0 41 07  |+l5p..9.Q.?...A.|
+00000340  a2 c9 c1 74 76 62 58 f1  cb e2 50 48 57 bb 6e 3d  |...tvbX...PHW.n=|
+00000350  ee ee 4a 53 e7 3c 66 aa  e3 d9 c1 f1 74 1a 93 b9  |..JS.<f.....t...|
+00000360  44 90 f6 a5 a4 da f5 6b  75 01 38 52 8f 9c ab 01  |D......ku.8R....|
+00000370  78 88 a6 cc 65 15 61 a8  8c cc 14 59 07 ea 6f 25  |x...e.a....Y..o%|
+00000380  5c 86 89 16 eb e7 da 20  82 d7 96 e4 78 7a c3 36  |\...... ....xz.6|
+00000390  b3 5c e7 17 1b 07 30 a2  72 ca a2 f3 dc 7e 45 c9  |.\....0.r....~E.|
+000003a0  7f 94 f8 a1 7b bb 2a 30  d7 bc 51 03 fb e6 2a fa  |....{.*0..Q...*.|
+000003b0  17 17 03 03 00 35 c1 a0  76 b6 35 4b 5c 26 94 c6  |.....5..v.5K\&..|
+000003c0  ba b1 7b b1 13 00 f2 2c  17 ed ac ab 47 9a a1 8d  |..{....,....G...|
+000003d0  3a 1c 78 44 14 a1 04 31  3d eb 9a 8d bb 2f 73 46  |:.xD...1=..../sF|
+000003e0  cb 5c f6 86 81 fa 56 fb  39 8c 55                 |.\....V.9.U|
 >>> Flow 3 (client to server)
-00000000  14 03 03 00 01 01 17 03  03 00 35 b5 22 19 23 49  |..........5.".#I|
-00000010  48 33 a5 f3 b2 72 2b 31  ab 89 27 f9 eb 1b b7 b1  |H3...r+1..'.....|
-00000020  bc 2b 99 9e 73 24 42 c4  2a 68 2c 76 e1 45 61 09  |.+..s$B.*h,v.Ea.|
-00000030  18 c7 44 45 9a 05 86 4c  90 c1 41 c6 fd 6a c2 95  |..DE...L..A..j..|
-00000040  17 03 03 00 17 ee 18 4e  d9 94 15 50 a9 99 4a 82  |.......N...P..J.|
-00000050  10 13 26 7b 74 10 db ef  fe b8 96 f6 17 03 03 00  |..&{t...........|
-00000060  13 2a 4c 52 8d c3 c5 af  d0 cd 5a 7d 0d a5 59 90  |.*LR......Z}..Y.|
-00000070  ce 59 3b af                                       |.Y;.|
+00000000  14 03 03 00 01 01 17 03  03 00 35 97 2c 39 3a a5  |..........5.,9:.|
+00000010  32 33 e5 74 43 97 98 ef  ef 30 de 27 8b f7 b5 ab  |23.tC....0.'....|
+00000020  dd af 87 7c a5 5e 76 cf  50 2a 03 f8 94 a4 7a df  |...|.^v.P*....z.|
+00000030  14 0a 2d 39 57 3b 02 97  c5 d7 63 85 21 3f 55 27  |..-9W;....c.!?U'|
+00000040  17 03 03 00 17 7c b4 8b  82 f0 0a ec 6f fa 60 ef  |.....|......o.`.|
+00000050  4c 0a 1c 0b ad 99 c3 89  fb a4 40 2c 17 03 03 00  |L.........@,....|
+00000060  13 f2 d5 58 ba 6b ca e8  f4 14 4c 66 23 38 f2 e8  |...X.k....Lf#8..|
+00000070  ea a9 ba c1                                       |....|
index 7fecc79add77fbb112bcbf6c33e04341cf6d6d60..8ea3ed6788e5f3cb4b20720f944a7f68ee04ad05 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 7a 02 00 00  76 03 03 dd df 8d 85 da  |....z...v.......|
-00000010  3c 99 a3 0c 01 90 5f ec  b8 3d 28 ce e4 32 c0 e8  |<....._..=(..2..|
-00000020  fe 77 03 ad 0f e1 33 1f  dc 89 cb 20 00 00 00 00  |.w....3.... ....|
+00000000  16 03 03 00 7a 02 00 00  76 03 03 71 00 90 30 07  |....z...v..q..0.|
+00000010  24 01 ae 33 b2 e8 4f 1f  9a 2c 83 e5 7b 30 1e a2  |$..3..O..,..{0..|
+00000020  8e 4a d0 df d1 ec 23 b5  ba aa 75 20 00 00 00 00  |.J....#...u ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 02 00 00  |................|
-00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 03  |..+.....3.$... .|
-00000060  6b 91 90 36 f0 54 da 66  8e 47 9b 26 9f 9f ae 30  |k..6.T.f.G.&...0|
-00000070  69 9e a2 6a 70 fb ef b2  f1 76 2b 32 90 0e 63 14  |i..jp....v+2..c.|
-00000080  03 03 00 01 01 17 03 03  00 17 46 47 2e ae ea 9b  |..........FG....|
-00000090  78 7b 0c d4 74 e2 b5 bf  7b 64 da c3 d3 c9 55 7f  |x{..t...{d....U.|
-000000a0  e3 17 03 03 02 6d a8 c1  57 27 66 9d 16 f6 4f 1b  |.....m..W'f...O.|
-000000b0  17 b6 5d 8c 3c fe f5 d5  4a d3 c6 8d e2 a8 2d d0  |..].<...J.....-.|
-000000c0  01 8d db 18 e8 c8 69 74  eb 81 9e 97 20 01 60 d5  |......it.... .`.|
-000000d0  96 d1 8f 9c de 09 ff 1d  e7 45 97 97 36 fa 89 77  |.........E..6..w|
-000000e0  88 20 30 c6 5b 42 d6 0e  85 9a 11 43 60 a1 86 34  |. 0.[B.....C`..4|
-000000f0  22 47 25 23 a5 35 87 a9  74 5d fe eb c9 70 32 44  |"G%#.5..t]...p2D|
-00000100  17 60 55 99 7a 93 b5 92  8b 66 31 ce dc e0 39 f2  |.`U.z....f1...9.|
-00000110  6a b3 db 43 5d 3f ba e5  12 12 1f 0e 3c 35 3b 72  |j..C]?......<5;r|
-00000120  9f 9d 69 d5 d6 cb ac b5  9e f4 af f5 74 68 67 f4  |..i.........thg.|
-00000130  e9 5f a4 4a d7 27 5b a5  2a 39 b7 30 49 4d 64 bb  |._.J.'[.*9.0IMd.|
-00000140  5d 89 10 ff a6 2c 42 a1  4a 2a 0c 28 c6 cd 4a e8  |]....,B.J*.(..J.|
-00000150  7d 24 d0 75 ff 61 08 3f  3b 05 ec f3 d6 61 ed 43  |}$.u.a.?;....a.C|
-00000160  08 5e 07 1c f2 15 96 22  2a c0 3c 5f 04 d1 17 82  |.^....."*.<_....|
-00000170  ea ee ee c7 49 cc 3e e4  65 15 97 6e 6f 36 24 a9  |....I.>.e..no6$.|
-00000180  27 34 3a 75 dc 07 1e 4c  f1 29 d1 e3 22 31 7d 84  |'4:u...L.).."1}.|
-00000190  a8 2a 7f 37 03 ab 13 ae  15 e2 74 50 bd 54 5b 32  |.*.7......tP.T[2|
-000001a0  ea 75 10 ed 39 5c 69 90  f6 74 09 53 c1 ce 44 49  |.u..9\i..t.S..DI|
-000001b0  64 fb f2 c6 bd 93 b2 07  06 96 94 04 a5 9e ed 67  |d..............g|
-000001c0  10 cb 01 fc 85 45 d7 22  76 3c c6 2f 14 4c 31 e1  |.....E."v<./.L1.|
-000001d0  73 81 7b 8b 6b 54 d6 34  15 d2 eb d0 03 10 c7 3d  |s.{.kT.4.......=|
-000001e0  f5 07 48 cc 72 9b e9 48  ee 13 9f 80 b5 13 86 77  |..H.r..H.......w|
-000001f0  33 91 79 6f f2 13 17 68  ca 72 6b 0d 93 9a 20 30  |3.yo...h.rk... 0|
-00000200  70 c3 30 ab 13 7e 14 39  97 4b ce c5 3d 8b 03 7f  |p.0..~.9.K..=...|
-00000210  cd 4b 67 c4 c5 79 0c bb  cd ba 17 c5 d5 15 51 cb  |.Kg..y........Q.|
-00000220  ac b7 f7 19 43 ff f5 c4  09 8c 44 67 ca e6 a1 5f  |....C.....Dg..._|
-00000230  1d 27 29 63 f2 0d 75 6d  b7 62 52 c9 1d 8e 0e 3b  |.')c..um.bR....;|
-00000240  6c cb 04 3e f7 13 74 bb  03 35 2e 4e 41 9a b7 72  |l..>..t..5.NA..r|
-00000250  15 ed 02 79 c7 bc 38 b3  65 75 0a 8e 82 dc d4 79  |...y..8.eu.....y|
-00000260  1c 10 3f 78 8c be 78 b0  73 18 cc 52 1d 3b 91 66  |..?x..x.s..R.;.f|
-00000270  33 fe 63 b2 ec 19 92 44  8f 06 4e 20 85 94 5c b4  |3.c....D..N ..\.|
-00000280  ad 22 16 a0 b3 76 03 dc  62 e9 0c ac 8c e1 67 c9  |."...v..b.....g.|
-00000290  d8 6f 40 51 b5 39 9a 61  b6 63 e0 d5 60 6a 27 78  |.o@Q.9.a.c..`j'x|
-000002a0  62 ec 94 1c 75 2c 38 f2  a6 f2 f0 c4 8f 98 ad cc  |b...u,8.........|
-000002b0  2e ce 7d 13 76 f4 4f 94  78 3f 85 cf ea 52 c4 6e  |..}.v.O.x?...R.n|
-000002c0  16 65 f9 48 5e f9 0b 07  bc 3e 38 91 06 e1 b0 76  |.e.H^....>8....v|
-000002d0  82 60 25 03 36 9c 3e 5e  54 73 8d cf df 91 19 33  |.`%.6.>^Ts.....3|
-000002e0  a7 18 96 d4 86 ea 7c 00  88 e6 a3 fe ea a1 14 db  |......|.........|
-000002f0  ae da 07 ef 1e 6f 16 bb  ad fb c0 f4 60 2f 75 5c  |.....o......`/u\|
-00000300  a4 43 a0 fc 3c d6 5e 89  cf 6e 1a c6 de 61 65 34  |.C..<.^..n...ae4|
-00000310  03 e5 cd 17 03 03 00 99  0a f3 a2 45 fe 53 22 37  |...........E.S"7|
-00000320  cd 31 9d 67 31 56 f9 99  c2 d1 bc 6d 47 de 9a e7  |.1.g1V.....mG...|
-00000330  67 c0 89 84 ac bf 27 b5  32 f0 e9 a5 9d f2 e0 ad  |g.....'.2.......|
-00000340  fd 12 6a a4 5d 50 4c b9  ed f1 f4 0e c0 c0 6c c4  |..j.]PL.......l.|
-00000350  39 9b 10 02 fa 10 64 a6  8b af 9d 6e d9 40 6d 0c  |9.....d....n.@m.|
-00000360  b0 6c b8 8d d5 b0 14 f0  ed 85 d6 66 8f 6f 61 43  |.l.........f.oaC|
-00000370  49 dd 95 08 94 2e a8 a6  19 b9 7b 6b 99 09 af 4c  |I.........{k...L|
-00000380  5f 41 48 da 10 b6 cf ee  68 b6 6e 03 d7 29 93 8e  |_AH.....h.n..)..|
-00000390  1a ab d1 ad d4 bf 33 2a  53 87 92 05 d1 1a de c0  |......3*S.......|
-000003a0  aa ef b9 9c 4d 2d f6 b1  72 60 22 80 bb 46 24 75  |....M-..r`"..F$u|
-000003b0  35 17 03 03 00 45 46 9e  b3 7f d0 82 b6 ef 45 1f  |5....EF.......E.|
-000003c0  18 6d 3b b6 23 f5 c9 f4  54 e3 08 d0 8b 30 c7 31  |.m;.#...T....0.1|
-000003d0  af 98 26 69 b7 6e 08 1d  1f be 1a 7e 5b 97 91 28  |..&i.n.....~[..(|
-000003e0  fa b7 78 05 ee 3f a1 9e  a0 79 fc 45 51 4c 96 fb  |..x..?...y.EQL..|
-000003f0  03 46 24 7d fe ec a4 40  51 d6 73                 |.F$}...@Q.s|
+00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 06  |..+.....3.$... .|
+00000060  2a 26 bd 81 c2 90 9b 17  6e d0 b5 ab 72 e6 93 ce  |*&......n...r...|
+00000070  53 6d 8c 54 b5 a4 50 91  93 32 6e 88 e6 b2 69 14  |Sm.T..P..2n...i.|
+00000080  03 03 00 01 01 17 03 03  00 17 7d 11 37 f0 18 b1  |..........}.7...|
+00000090  53 55 38 bb 12 7c e8 b3  89 bc 35 fb 2a 36 d1 0f  |SU8..|....5.*6..|
+000000a0  3a 17 03 03 02 6d a0 fa  dc 8e ac a6 90 5a 20 0e  |:....m.......Z .|
+000000b0  ee 22 89 7b 69 5b c9 1a  a1 c6 43 b9 40 f6 85 78  |.".{i[....C.@..x|
+000000c0  61 0b 14 c6 e6 3b a9 ac  4c 7a 96 9b 7b 87 d0 ce  |a....;..Lz..{...|
+000000d0  42 cc 75 9d fc 06 44 3e  e8 12 3a 94 b7 de 86 c4  |B.u...D>..:.....|
+000000e0  b5 66 e1 f5 48 21 f7 f1  58 7f 23 6c 3f 76 a0 cb  |.f..H!..X.#l?v..|
+000000f0  a7 f6 72 34 07 fa c1 55  3e 61 cf 72 c4 6c f1 ca  |..r4...U>a.r.l..|
+00000100  dd dc ec 66 3d 7b f6 cf  53 3b 28 bd 27 1b aa a6  |...f={..S;(.'...|
+00000110  28 2a ab fa 48 a5 08 67  b5 49 c7 c7 5d f8 2c ec  |(*..H..g.I..].,.|
+00000120  83 af 58 33 42 6c c1 4c  94 17 7e 36 1c a9 48 34  |..X3Bl.L..~6..H4|
+00000130  5f 26 78 f6 69 88 3a a5  1b d1 76 ad 88 63 25 33  |_&x.i.:...v..c%3|
+00000140  0d e3 d0 34 6b 7f fc 96  2b 8d 22 6f 3f 21 8a 14  |...4k...+."o?!..|
+00000150  01 e0 5c 54 6c c3 b8 12  f9 17 f5 4c ce e0 bd 10  |..\Tl......L....|
+00000160  e7 e1 29 24 73 94 c2 5e  b0 ad d3 91 9e 87 ea 23  |..)$s..^.......#|
+00000170  4d fd 8f 12 ca 87 ff 2e  93 9f 16 a8 18 e1 66 8f  |M.............f.|
+00000180  50 76 15 cd 70 5c a2 1d  91 51 e5 54 13 5f 73 d3  |Pv..p\...Q.T._s.|
+00000190  b2 6e b1 27 80 0b 3d 64  d5 fa f3 a4 fb 77 33 cb  |.n.'..=d.....w3.|
+000001a0  ac 93 54 36 2d 71 c3 9e  dd 37 02 a9 9d b0 9b ac  |..T6-q...7......|
+000001b0  f8 c5 dc 43 9b d8 db c7  d0 fb cf 69 fa 62 e4 9d  |...C.......i.b..|
+000001c0  b7 04 f8 49 d3 a7 8d bd  cf 8a e3 4a 62 cb bb 29  |...I.......Jb..)|
+000001d0  b5 db 21 80 76 eb 28 67  34 1e 40 0b 83 83 19 10  |..!.v.(g4.@.....|
+000001e0  46 8f bd 78 d6 7c 05 c2  19 82 1c e8 7d 84 f2 79  |F..x.|......}..y|
+000001f0  c4 a6 e0 f7 7e df 70 7f  42 48 9f e4 99 03 7f 9e  |....~.p.BH......|
+00000200  e8 fd 75 c3 8a 55 55 8e  08 2e 62 28 a5 16 b7 11  |..u..UU...b(....|
+00000210  d8 9a 11 48 46 ad d3 ba  4f 91 c8 fd 72 d9 df 98  |...HF...O...r...|
+00000220  1a 59 51 55 af ab 73 b9  f3 bf fe 7d 55 7d 44 54  |.YQU..s....}U}DT|
+00000230  cd bb f3 eb 6e ff 5a 09  e9 b9 c1 66 97 8e a5 7c  |....n.Z....f...||
+00000240  89 4a 51 1d 8b e4 40 fb  97 ce ef 9d 7c 02 e4 db  |.JQ...@.....|...|
+00000250  f1 ca 01 d9 05 b4 de 10  23 33 92 ff 26 3b 09 8f  |........#3..&;..|
+00000260  11 7c 37 ad fb 58 ed 7a  10 08 fd df 98 dd d6 c5  |.|7..X.z........|
+00000270  b8 fd 59 37 21 1d 6e 27  8a 56 24 45 e7 64 61 0b  |..Y7!.n'.V$E.da.|
+00000280  20 2d bc 79 89 fa 6d 7a  06 77 61 0c 60 25 e2 79  | -.y..mz.wa.`%.y|
+00000290  6a 54 9e 5b 4b 33 68 17  da 63 ba a7 f9 ad 2c 84  |jT.[K3h..c....,.|
+000002a0  52 e9 27 85 71 74 d2 5f  c9 f8 8e 67 f7 47 58 f5  |R.'.qt._...g.GX.|
+000002b0  e4 72 a7 bd 1c 94 4b 4d  13 5a 62 69 d9 6f 3a 51  |.r....KM.Zbi.o:Q|
+000002c0  f0 18 90 e5 b6 21 23 97  70 74 93 ba 9b bc dc e4  |.....!#.pt......|
+000002d0  3d 9c 52 3f 93 f0 48 05  e8 50 d0 b4 98 92 7a 18  |=.R?..H..P....z.|
+000002e0  3f 39 ba f8 f7 ee 19 b0  ce ac d0 ab 9e 83 ee 0e  |?9..............|
+000002f0  5d 2a 72 74 a8 8b 4d de  6b a9 91 ad b4 a4 26 99  |]*rt..M.k.....&.|
+00000300  4e aa 6d 48 77 83 78 78  be 96 f1 17 d6 96 74 4a  |N.mHw.xx......tJ|
+00000310  80 d1 5b 17 03 03 00 99  d9 40 96 5c fb 5d 65 69  |..[......@.\.]ei|
+00000320  db 54 a8 f6 8c b7 d3 25  8d 2d c5 f1 40 5b f2 26  |.T.....%.-..@[.&|
+00000330  f3 86 9e 61 6a a5 b9 66  b1 27 b1 20 6b 2c 64 84  |...aj..f.'. k,d.|
+00000340  3f 48 24 5d d9 90 4b d1  ed 1b 0e 05 84 7f ad 0e  |?H$]..K.........|
+00000350  e6 75 f6 f9 33 90 73 7c  88 10 d7 e9 74 41 4b c3  |.u..3.s|....tAK.|
+00000360  19 8e e1 a8 a6 7c 3c 9a  bc 69 a7 e7 bb d6 af 98  |.....|<..i......|
+00000370  f1 49 53 14 95 80 d6 95  81 5a 5e 88 2c 29 70 df  |.IS......Z^.,)p.|
+00000380  b2 df fe f3 17 03 e7 de  af 12 57 c5 7a ef 70 eb  |..........W.z.p.|
+00000390  8a c6 c3 05 de 5b 15 af  5f 54 8c 7b 23 b7 e1 f1  |.....[.._T.{#...|
+000003a0  30 b1 ed 34 4c 59 f5 68  c2 50 e8 c3 83 78 1d 1f  |0..4LY.h.P...x..|
+000003b0  eb 17 03 03 00 45 1a d4  61 ba 4a a5 1e 02 80 04  |.....E..a.J.....|
+000003c0  2a 19 11 af 8c e9 bd ab  22 6b 75 41 a8 40 de 57  |*......."kuA.@.W|
+000003d0  54 8c dc 09 cc 57 76 82  27 5e 59 0c 30 f7 9d c4  |T....Wv.'^Y.0...|
+000003e0  fe 1c 09 f2 f4 5f e0 79  ac 02 06 80 f3 60 c4 92  |....._.y.....`..|
+000003f0  cd 6a df b6 46 7c de 90  8d bb 94                 |.j..F|.....|
 >>> Flow 3 (client to server)
-00000000  14 03 03 00 01 01 17 03  03 00 45 44 15 b9 ed d8  |..........ED....|
-00000010  10 2c 88 80 79 f3 38 a4  bc 42 9b 22 09 44 d9 19  |.,..y.8..B.".D..|
-00000020  e1 0a ec 15 aa d5 15 e9  19 6d b8 6b 71 63 86 ce  |.........m.kqc..|
-00000030  e7 16 0d 8e 3f 9a 3b 52  25 1e 96 f6 d9 d1 6c dd  |....?.;R%.....l.|
-00000040  e3 20 e9 97 f9 60 81 f5  4a b2 26 b5 d3 9e 84 46  |. ...`..J.&....F|
-00000050  17 03 03 00 17 de 4a e9  44 21 88 ef ce 78 35 6d  |......J.D!...x5m|
-00000060  b2 e4 78 47 39 8d 1f fd  9b 2d a4 47 17 03 03 00  |..xG9....-.G....|
-00000070  13 98 f9 1c 9c d4 b1 42  f7 e7 a1 9b 6d b1 b1 cb  |.......B....m...|
-00000080  86 e3 c2 27                                       |...'|
+00000000  14 03 03 00 01 01 17 03  03 00 45 8c 37 d5 7e 3e  |..........E.7.~>|
+00000010  c4 24 64 8b fa fc 8d 03  a7 92 34 35 c3 2c f2 54  |.$d.......45.,.T|
+00000020  43 06 5d 8a c9 c0 e8 7d  22 d3 99 58 01 0e 44 aa  |C.]....}"..X..D.|
+00000030  3c 26 eb 68 45 14 cd bf  6c 61 bb 31 91 9d b4 57  |<&.hE...la.1...W|
+00000040  42 79 14 8c 67 c6 65 52  15 07 c8 f3 c3 9f 23 ef  |By..g.eR......#.|
+00000050  17 03 03 00 17 21 51 dd  67 e4 be f8 7c 7b 84 0d  |.....!Q.g...|{..|
+00000060  78 3c 7f ac 50 f8 34 7b  fb 38 09 d0 17 03 03 00  |x<..P.4{.8......|
+00000070  13 35 1a 52 9d de 4a 74  1f 01 70 de 05 c5 c3 b9  |.5.R..Jt..p.....|
+00000080  e6 de 9c 0f                                       |....|
index 0ac9b36933c49e95fb4373376454be2542b586d5..1d8da269de76a544dd977f859b9b0e6efa72f67a 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 8f 00 05 00 05  01 00 00 00 00 00 0a 00  |................|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 00000100  bb 29 07 30 ff f6 84 af  c4 cf c2 ed 90 99 5f 58  |.).0.........._X|
 00000110  cb 3b 74                                          |.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 7a 02 00 00  76 03 03 23 c5 c4 0c 4a  |....z...v..#...J|
-00000010  d2 5f 0b f6 ea 21 7a d1  a0 7d 21 26 b5 a3 94 ca  |._...!z..}!&....|
-00000020  91 6c 13 58 60 4f 39 cc  1a f7 c0 20 00 00 00 00  |.l.X`O9.... ....|
+00000000  16 03 03 00 7a 02 00 00  76 03 03 c2 91 70 7a 7a  |....z...v....pzz|
+00000010  d4 c9 46 7a e9 44 d1 c0  92 a6 0a 43 34 08 b2 ce  |..Fz.D.....C4...|
+00000020  14 99 8f 6c f7 37 fb a1  28 00 ae 20 00 00 00 00  |...l.7..(.. ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 01 00 00  |................|
-00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 f9  |..+.....3.$... .|
-00000060  64 7e 54 8f 64 ec 3d 7c  17 f1 96 3c 44 ca cd d7  |d~T.d.=|...<D...|
-00000070  3d 92 02 06 5a f8 ab dc  f3 50 fe 5c ab 04 6b 14  |=...Z....P.\..k.|
-00000080  03 03 00 01 01 17 03 03  00 24 9f 15 ee 1e 43 26  |.........$....C&|
-00000090  31 53 01 8b a0 a7 e9 ac  96 51 a7 bc fe 46 6c 60  |1S.......Q...Fl`|
-000000a0  d1 8b c4 a9 34 cd 93 13  51 50 e9 02 f9 ce 17 03  |....4...QP......|
-000000b0  03 02 6d c3 ad 14 a8 d3  81 87 26 7d a0 60 57 2c  |..m.......&}.`W,|
-000000c0  d2 65 f5 a5 fc a8 c4 dd  2e e2 04 57 1f 94 a4 4a  |.e.........W...J|
-000000d0  3a 43 92 f4 f5 58 e9 11  d7 b1 62 0d d1 f4 d5 43  |:C...X....b....C|
-000000e0  4a c8 fa d9 28 18 ca 74  1a b2 39 e2 9b 95 40 0e  |J...(..t..9...@.|
-000000f0  63 ed 11 52 9b 61 36 0c  c3 a6 7b de 4d 68 48 55  |c..R.a6...{.MhHU|
-00000100  e2 05 e8 59 e1 df 51 08  06 a8 09 a0 d5 e7 14 e9  |...Y..Q.........|
-00000110  13 c6 a4 6d ff 7b b0 98  50 ef 81 1b 64 6f 44 c1  |...m.{..P...doD.|
-00000120  cd da 85 a0 80 0c da 54  90 8e a1 7d 4b 1d 16 fc  |.......T...}K...|
-00000130  40 ba e3 25 e3 c2 52 29  7a 23 50 2a 43 3f 7e 32  |@..%..R)z#P*C?~2|
-00000140  73 e0 5a a5 3f 09 b0 3a  b8 90 8b 36 06 ac fc ef  |s.Z.?..:...6....|
-00000150  e8 9c ba f3 fb 8e 2d ab  b3 c6 f4 d0 1d eb 7b 20  |......-.......{ |
-00000160  2b 68 1f e9 25 49 c9 2a  45 6e 2b a5 00 12 54 b2  |+h..%I.*En+...T.|
-00000170  a7 16 2f 00 72 d4 ed 7d  ea 7e cb b1 0a 03 c6 3b  |../.r..}.~.....;|
-00000180  b8 fe 97 59 6a b4 07 d3  2c b1 cc ca e8 46 24 97  |...Yj...,....F$.|
-00000190  d2 b8 a5 8e 7d 6f 78 7f  bd ee 7d 5a f6 ec 07 50  |....}ox...}Z...P|
-000001a0  00 c4 63 33 03 e5 09 44  c3 68 61 ec 5b 52 f8 67  |..c3...D.ha.[R.g|
-000001b0  66 60 fd 68 fe d7 b7 df  96 2c 1b 00 93 89 24 58  |f`.h.....,....$X|
-000001c0  20 2d 0a c1 c4 80 fc 03  8c 16 d1 83 11 a9 e7 70  | -.............p|
-000001d0  69 3f cf c2 dc 90 40 70  1a 1e d9 8e 36 02 61 57  |i?....@p....6.aW|
-000001e0  49 60 2d ba 59 76 fb 26  50 c8 db 82 b3 62 e5 d7  |I`-.Yv.&P....b..|
-000001f0  fb c6 91 9b 99 6e d2 d7  e1 8a da ec 87 e9 d8 71  |.....n.........q|
-00000200  3a 01 01 c9 9c da 3c 81  67 bc fb 30 0c 81 31 62  |:.....<.g..0..1b|
-00000210  c2 ff 1f ee db 27 e2 07  59 51 fb e2 64 89 e5 0e  |.....'..YQ..d...|
-00000220  0a 37 06 07 8a 96 34 b9  53 8d 0a ed 60 02 cb f5  |.7....4.S...`...|
-00000230  af b2 9c 77 27 2a 23 69  5f 58 cc 46 32 ab 76 df  |...w'*#i_X.F2.v.|
-00000240  1b c1 17 98 6e fb 9e 15  e0 7f e1 00 75 6d b2 cf  |....n.......um..|
-00000250  ce 6e dd 6c 00 b6 81 14  bb 06 60 b4 47 07 2a cf  |.n.l......`.G.*.|
-00000260  dc 87 72 07 7e 1d 76 fc  17 14 8a d7 5c 32 9b d2  |..r.~.v.....\2..|
-00000270  c6 45 24 d5 d0 ea a4 c6  b5 6e 63 fc c7 12 0c a7  |.E$......nc.....|
-00000280  0a 73 70 89 ce 3d 1f aa  d5 ad ba bc 16 e8 15 80  |.sp..=..........|
-00000290  14 16 84 f6 06 38 23 b7  21 ec 27 50 a8 76 cf 0c  |.....8#.!.'P.v..|
-000002a0  4f 58 f7 57 7f b3 bd 55  0c f4 53 6e 9f f4 f2 12  |OX.W...U..Sn....|
-000002b0  5b c4 e7 68 9c 17 8b 76  88 1e 42 1b 32 e0 81 4d  |[..h...v..B.2..M|
-000002c0  ce 16 73 59 74 bd 56 be  fd fe 42 21 07 bd f4 e9  |..sYt.V...B!....|
-000002d0  ff 83 f3 97 a8 9e d4 c6  3c 6f 43 9d 0b 3c dc 35  |........<oC..<.5|
-000002e0  29 e4 bd b1 75 a4 70 30  8d bd fa 25 74 6c 11 ea  |)...u.p0...%tl..|
-000002f0  44 38 b5 8f f9 7a 71 c6  f8 ea c7 2c 23 d2 29 6d  |D8...zq....,#.)m|
-00000300  dc 8f e5 f7 c6 80 3b 8d  47 da 19 da 28 26 26 e6  |......;.G...(&&.|
-00000310  0f 83 d5 e9 33 42 0b 21  f4 1c 48 c0 19 ed e6 84  |....3B.!..H.....|
-00000320  17 03 03 00 99 d6 56 fb  52 63 57 c0 61 ec 30 04  |......V.RcW.a.0.|
-00000330  0a ee 10 39 7b e4 6a 38  8b 29 9a 6c 40 88 1d a1  |...9{.j8.).l@...|
-00000340  8b 53 2b fe 47 66 75 70  5b 03 33 fc ca e6 4f 8d  |.S+.Gfup[.3...O.|
-00000350  f1 40 63 c2 24 97 b4 c8  dd b1 20 27 e0 28 03 7a  |.@c.$..... '.(.z|
-00000360  f1 cd b3 df 8a 93 39 fa  b9 f9 0e 62 4c 47 24 69  |......9....bLG$i|
-00000370  9a f3 a5 7b 0d 14 33 00  c3 ab ae 4a 46 c2 40 42  |...{..3....JF.@B|
-00000380  d7 36 c1 74 7a c6 1a 42  d2 e0 fe e6 4b 5c 96 1a  |.6.tz..B....K\..|
-00000390  24 05 13 2c ad aa 25 02  ae 1b 3a 87 a7 60 1c d4  |$..,..%...:..`..|
-000003a0  98 53 ee 33 e9 36 37 d0  97 c2 e9 2d b9 a0 ac 4f  |.S.3.67....-...O|
-000003b0  c8 82 d8 a4 28 2e e4 db  a1 8f 71 cb ee 28 17 03  |....(.....q..(..|
-000003c0  03 00 35 5d 41 7c b0 af  b5 49 e8 dc 8a 7f c8 1f  |..5]A|...I......|
-000003d0  af 70 8b c4 35 7b 7b 57  3a 49 f2 ef 75 4c 27 39  |.p..5{{W:I..uL'9|
-000003e0  bf a6 45 fd 9c 64 b2 6e  7c c0 d3 c0 c7 a6 25 2f  |..E..d.n|.....%/|
-000003f0  f7 48 6d 7c a4 33 ad 61                           |.Hm|.3.a|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 03 00 00  |................|
+00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 60  |..+.....3.$... `|
+00000060  96 62 c2 30 4e ae b6 89  f2 06 e0 4e 8e 32 27 04  |.b.0N......N.2'.|
+00000070  b5 74 80 d8 c3 f5 76 7d  0e 0e e1 8d bc 2c 2c 14  |.t....v}.....,,.|
+00000080  03 03 00 01 01 17 03 03  00 24 45 c7 50 3e a9 63  |.........$E.P>.c|
+00000090  24 0b e9 80 3f 59 bb be  23 8a 5d 46 eb ee 17 9c  |$...?Y..#.]F....|
+000000a0  70 6f 52 1f 18 f3 9f 72  d6 35 44 55 91 d2 17 03  |poR....r.5DU....|
+000000b0  03 02 6d c2 c0 1f 53 2a  0c 3c 7f 08 c3 cb 53 4e  |..m...S*.<....SN|
+000000c0  b2 f5 b3 2d a5 10 e1 97  00 89 67 db 4e df ad 75  |...-......g.N..u|
+000000d0  94 b4 56 c4 8a a3 49 41  43 a1 3f aa 9b 8e e1 8d  |..V...IAC.?.....|
+000000e0  4c 9c 36 f6 80 da 4e 7f  00 10 c0 81 3e 45 1b a0  |L.6...N.....>E..|
+000000f0  b7 7f 2c bd eb 2a 8b c4  e6 fa c8 b3 59 28 f6 b8  |..,..*......Y(..|
+00000100  0a 93 cb b3 bf 28 e7 1a  ae a0 f5 ff 3a 42 f5 64  |.....(......:B.d|
+00000110  92 2c dd c2 24 77 2f a6  7e 23 63 3f 24 16 b3 d5  |.,..$w/.~#c?$...|
+00000120  b7 df 3f 30 23 a4 aa c9  14 78 6c f2 82 45 52 df  |..?0#....xl..ER.|
+00000130  cf a1 1d 35 fd 2a 30 89  14 38 5a 23 b1 63 2c c1  |...5.*0..8Z#.c,.|
+00000140  6d 6b 07 d0 41 38 4f 4c  87 d3 bd f1 ec ed 29 52  |mk..A8OL......)R|
+00000150  3d c7 74 3d e9 d3 ce 47  1c 24 d5 78 19 c9 5e 01  |=.t=...G.$.x..^.|
+00000160  66 a0 f1 8f ea a6 c1 e4  b4 e0 c2 2e d7 d6 64 36  |f.............d6|
+00000170  c9 bc d1 27 33 6f 26 a8  c6 aa 0d bc ae f9 2e bc  |...'3o&.........|
+00000180  f1 a7 82 42 09 83 62 88  c0 9f 20 95 a9 38 50 b4  |...B..b... ..8P.|
+00000190  55 d6 e9 f4 c6 a1 e6 67  a9 5f e4 15 97 44 13 ef  |U......g._...D..|
+000001a0  d3 50 8b 61 38 5e 89 75  b1 cf 6a 6f 0c c5 26 13  |.P.a8^.u..jo..&.|
+000001b0  2c 5a 26 c9 81 98 88 cd  ec 8c 2c 99 a0 ff 55 8f  |,Z&.......,...U.|
+000001c0  3f 9b c3 3b 52 d0 a3 3a  f9 b8 f0 17 81 53 00 f3  |?..;R..:.....S..|
+000001d0  ef 72 b3 4e b9 65 28 8f  a2 48 dc dd 6b 16 61 c3  |.r.N.e(..H..k.a.|
+000001e0  4e 0e c0 1c ac 8c 40 28  27 63 66 c7 74 40 8d 93  |N.....@('cf.t@..|
+000001f0  71 e9 f6 3f d8 8d 5d c6  28 11 4f ac 55 6f 80 1b  |q..?..].(.O.Uo..|
+00000200  2e 84 05 94 e0 4f e7 63  62 65 c7 52 99 49 2f 5d  |.....O.cbe.R.I/]|
+00000210  b4 99 d3 c3 fa b9 f5 83  aa 28 2e 9d ce af 72 7f  |.........(....r.|
+00000220  57 ea 81 f3 bf b5 d7 93  3a 1f a0 83 4d 8a 91 85  |W.......:...M...|
+00000230  fe b7 a1 b3 cb 1d b1 85  9b bb 36 1b 12 9f ed 13  |..........6.....|
+00000240  09 55 31 bd ee 61 06 57  b4 07 4d c6 1e fa b9 7f  |.U1..a.W..M.....|
+00000250  c7 b6 60 70 92 b7 9a ff  80 7d da 7f 2a 62 89 be  |..`p.....}..*b..|
+00000260  79 43 d3 ae 9c f1 00 6d  68 6c a3 f6 48 6e e0 48  |yC.....mhl..Hn.H|
+00000270  97 0f 5c 44 43 9f a8 88  27 96 fc 53 a0 e1 f2 7a  |..\DC...'..S...z|
+00000280  a6 a7 d9 96 2e 3d c4 e0  d9 18 79 ec 83 c2 9b da  |.....=....y.....|
+00000290  0b d4 8b 87 c5 98 f5 8b  e7 e3 d1 bd 2b 2b 42 e2  |............++B.|
+000002a0  4b 3e 64 88 4b 72 d0 35  cc c3 e6 68 c6 f6 4f 23  |K>d.Kr.5...h..O#|
+000002b0  39 a7 94 8d f3 e6 bd cd  d5 e9 8c 53 83 a7 87 09  |9..........S....|
+000002c0  15 fe ea eb 2e 56 da 6b  d9 5b b7 b1 c5 c4 ba 65  |.....V.k.[.....e|
+000002d0  39 89 16 f5 f6 4e e6 3a  63 34 1b 5d f5 fa 6b 8d  |9....N.:c4.]..k.|
+000002e0  c3 49 07 88 12 ca 18 c5  50 da 74 44 c0 c0 33 bd  |.I......P.tD..3.|
+000002f0  2e 45 94 af e1 40 90 00  11 2d 08 7b fc e4 3b f0  |.E...@...-.{..;.|
+00000300  94 fd 5a 0c 3a f9 76 df  3b 5e a3 0d 0f e7 2d df  |..Z.:.v.;^....-.|
+00000310  fd e9 ce 45 5a 13 36 a6  18 ae 46 30 00 fc d5 e3  |...EZ.6...F0....|
+00000320  17 03 03 00 99 0e 35 b6  91 ad cd a6 62 6e 79 12  |......5.....bny.|
+00000330  53 d5 f0 78 72 c5 dd 94  00 e3 75 2c 11 a3 72 f6  |S..xr.....u,..r.|
+00000340  b7 b3 5e d9 51 79 d5 a9  1e 21 2f df 0d 53 9a c8  |..^.Qy...!/..S..|
+00000350  43 a9 58 e2 a9 3d 9a b4  b4 72 bb 62 65 4b 83 f8  |C.X..=...r.beK..|
+00000360  cd 1b 58 e0 69 d9 87 3b  8d 05 42 e1 22 23 e9 5b  |..X.i..;..B."#.[|
+00000370  3a 5a 38 17 17 fb 3a 56  de fc 56 f8 77 12 31 4a  |:Z8...:V..V.w.1J|
+00000380  c5 38 ec 69 72 54 e5 63  2a a0 1e b4 7d 86 43 29  |.8.irT.c*...}.C)|
+00000390  21 ba 56 c2 d9 1b 9f a4  c1 02 f3 83 c1 9a 56 69  |!.V...........Vi|
+000003a0  5c 9e 5f ae 94 9d 6f 03  ec 75 7a 19 98 cd a9 dd  |\._...o..uz.....|
+000003b0  4a 01 41 72 2e 60 9f ca  4c d2 27 d9 0f 4f 17 03  |J.Ar.`..L.'..O..|
+000003c0  03 00 35 5d 61 3c 07 70  2f 35 ba d0 93 44 16 bd  |..5]a<.p/5...D..|
+000003d0  73 4b a0 fb 05 52 6a cc  5a 2e f2 94 d6 77 98 03  |sK...Rj.Z....w..|
+000003e0  c3 2e 8e a9 d1 38 14 d2  cd e6 e3 b6 ad ec d6 a0  |.....8..........|
+000003f0  cf b0 58 5f 8f d3 43 4b                           |..X_..CK|
 >>> Flow 3 (client to server)
-00000000  14 03 03 00 01 01 17 03  03 00 35 3e e7 50 e1 d1  |..........5>.P..|
-00000010  4d 9f 84 fe ca 83 c4 3b  a6 86 45 c2 7e e7 af 00  |M......;..E.~...|
-00000020  db e6 23 3c 06 b8 a3 1e  36 2e ab 45 7e d8 07 8c  |..#<....6..E~...|
-00000030  66 bf 5a 0f ff e6 3f 09  a4 d3 cf 74 1c d6 cf c7  |f.Z...?....t....|
-00000040  17 03 03 00 17 4c db af  a7 f3 73 b3 84 b9 a7 d1  |.....L....s.....|
-00000050  1c 2f cb 27 d8 ba 2c c6  84 48 88 18 17 03 03 00  |./.'..,..H......|
-00000060  13 a3 41 6f fb da f5 5a  4d 85 0c e0 ff 3a fb 91  |..Ao...ZM....:..|
-00000070  e2 5e ab 96                                       |.^..|
+00000000  14 03 03 00 01 01 17 03  03 00 35 3d 0a fd 33 39  |..........5=..39|
+00000010  b6 94 43 53 ae ee 3f 4e  c6 2d a2 3a f0 ef 94 7d  |..CS..?N.-.:...}|
+00000020  32 0a b6 90 cd a1 6f 29  88 ff 3c 91 c1 e5 e5 ae  |2.....o)..<.....|
+00000030  b7 a0 0b b3 c0 e6 37 9d  06 8b d8 ae 06 c0 0e 7b  |......7........{|
+00000040  17 03 03 00 17 c2 a1 82  db df fa 54 28 79 a0 0c  |...........T(y..|
+00000050  97 8c 82 ee 22 c9 b9 35  32 7a 21 4b 17 03 03 00  |...."..52z!K....|
+00000060  13 87 2b f8 38 81 df fa  e5 2e ff e2 d2 51 3e bc  |..+.8........Q>.|
+00000070  dd d3 e8 62                                       |...b|
index 6d7b508fd34c4c724c81efefa2122a148bfb82be..69749f05d3d44779b8d797aec2f335426689f856 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 7a 02 00 00  76 03 03 43 b1 e8 d9 c3  |....z...v..C....|
-00000010  22 a0 a3 08 df 7f 37 34  7a fe 7a 47 98 ee ed 51  |".....74z.zG...Q|
-00000020  c2 ae 5c c6 b1 43 3d ff  f7 91 68 20 00 00 00 00  |..\..C=...h ....|
+00000000  16 03 03 00 7a 02 00 00  76 03 03 39 b2 74 80 d8  |....z...v..9.t..|
+00000010  49 72 79 63 9b 7b da d7  cf b4 29 20 f8 80 ed d9  |Iryc.{....) ....|
+00000020  66 09 65 22 b6 27 16 c5  a7 6f 8b 20 00 00 00 00  |f.e".'...o. ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 03 00 00  |................|
-00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 63  |..+.....3.$... c|
-00000060  0f 66 ec 2d fa 67 d4 eb  94 47 8d 88 0b eb ed ec  |.f.-.g...G......|
-00000070  5b ac 22 f7 46 85 c5 1c  2b 5e e8 57 e2 d3 6f 14  |[.".F...+^.W..o.|
-00000080  03 03 00 01 01 17 03 03  00 17 d0 f8 1f 06 59 8d  |..............Y.|
-00000090  a0 40 21 8f 3e 36 3b 1d  6a 6e f7 77 44 fb b3 8e  |.@!.>6;.jn.wD...|
-000000a0  e2 17 03 03 02 6d 22 6b  63 ae 47 fd 66 f9 95 f6  |.....m"kc.G.f...|
-000000b0  63 ea e8 16 61 a3 64 82  39 82 76 1c 2c 04 9b 29  |c...a.d.9.v.,..)|
-000000c0  0f 8a ff 77 9b e6 2c ce  04 09 5f 91 f3 b6 2e 8d  |...w..,..._.....|
-000000d0  be 42 94 7e 5a 28 4b 9f  e9 7b 38 0a 3c de 90 77  |.B.~Z(K..{8.<..w|
-000000e0  c1 bf 97 bf 35 6c 77 98  4b 38 b4 8d 7f 1f 4b c0  |....5lw.K8....K.|
-000000f0  23 c5 73 08 90 fa 21 5c  cd cb 84 5b 0e 89 86 ce  |#.s...!\...[....|
-00000100  83 78 d5 1c 2b b9 b1 24  45 ad ab 9c 68 9f c2 28  |.x..+..$E...h..(|
-00000110  40 d6 c2 ac a2 0c 86 cd  75 92 43 d5 22 3f 61 9d  |@.......u.C."?a.|
-00000120  e8 56 b8 7c 71 db 25 cc  2e 74 52 74 da 6b d4 a1  |.V.|q.%..tRt.k..|
-00000130  2c 32 d2 d8 9c 74 41 9d  78 98 94 3b 87 99 8e 17  |,2...tA.x..;....|
-00000140  df df d6 c3 6d ef 58 13  5c 1e 20 2d ed 77 bd 5c  |....m.X.\. -.w.\|
-00000150  d6 5c 9a 6d 0f 19 77 e1  4f 79 b0 ed 9d 0b f5 e8  |.\.m..w.Oy......|
-00000160  42 d0 f4 90 88 97 a9 84  af 92 3c 41 fe fd 67 6e  |B.........<A..gn|
-00000170  33 77 8e 02 83 b4 6f c0  14 d2 ee 38 79 ca 45 61  |3w....o....8y.Ea|
-00000180  59 05 3b 76 4b ef 55 b9  18 43 9f c4 42 02 31 8e  |Y.;vK.U..C..B.1.|
-00000190  88 c1 b6 0b 5d c4 20 59  91 57 f3 81 b9 d0 ec 25  |....]. Y.W.....%|
-000001a0  26 72 37 e0 e0 c8 34 83  58 fe 15 bd aa 4d 49 f8  |&r7...4.X....MI.|
-000001b0  ba 8f 1d 8d 37 9c 18 88  cd 69 23 00 93 0f 64 e0  |....7....i#...d.|
-000001c0  ed 0d a7 a0 fc bd f3 7d  0b b0 50 6b cd e6 25 b8  |.......}..Pk..%.|
-000001d0  50 3a bf 37 d7 18 60 a7  de ba c7 ff b7 26 8a 20  |P:.7..`......&. |
-000001e0  ad d3 f9 5a 5f 61 37 2f  b0 9b d6 2a 4c 39 08 34  |...Z_a7/...*L9.4|
-000001f0  31 15 19 1e 72 d3 fc 72  63 0e d5 71 04 82 b3 80  |1...r..rc..q....|
-00000200  ec aa 51 0f 73 5f 2c dd  42 fd 40 b8 e3 1d 9e 31  |..Q.s_,.B.@....1|
-00000210  13 01 3b 6b 88 f2 52 17  fa 0b 9d 45 1e f2 f0 c1  |..;k..R....E....|
-00000220  5b 3f 14 23 41 e7 a2 2e  fa e4 9b 01 9b a4 99 43  |[?.#A..........C|
-00000230  32 85 fc c9 30 2a 5d ca  2a fa c5 7f 81 89 31 02  |2...0*].*.....1.|
-00000240  0a c6 89 f0 98 1b 92 08  96 d0 90 c7 18 b0 d4 e9  |................|
-00000250  5d 29 71 3b c6 2f c5 ff  2c be db f8 ef 56 d6 e0  |])q;./..,....V..|
-00000260  9b a6 21 b1 92 b1 58 26  e9 e2 3b 97 1b 95 b2 ba  |..!...X&..;.....|
-00000270  62 66 a5 df a1 a8 82 25  1e ae 85 98 94 d7 96 c5  |bf.....%........|
-00000280  3b 30 4c bd 04 23 45 3d  86 c9 7e 0e 47 5b 5f 14  |;0L..#E=..~.G[_.|
-00000290  b5 c5 29 31 1e cd a4 e0  6a b2 78 51 f0 7b b2 21  |..)1....j.xQ.{.!|
-000002a0  1f 10 0d 0d 7f 01 f1 06  4a 87 7d 4a 90 63 59 f3  |........J.}J.cY.|
-000002b0  6d 16 0f 07 9e 00 3a d2  c7 01 37 cc 39 6e 07 6e  |m.....:...7.9n.n|
-000002c0  9e 64 df 47 65 04 4c 72  59 ad 3b 3e 52 8e e4 b6  |.d.Ge.LrY.;>R...|
-000002d0  fc ba 9c f0 82 13 ba 25  11 c7 5d 38 00 cf 83 14  |.......%..]8....|
-000002e0  30 a9 72 48 d1 e8 4e 1b  ed 04 ed cf b7 5b 2e 72  |0.rH..N......[.r|
-000002f0  1c a2 03 ae 60 54 d6 cf  2f fb 11 a3 b1 8d d6 47  |....`T../......G|
-00000300  e8 9f 96 08 90 ae 3c 3c  c0 8c d8 c4 ef 30 18 ea  |......<<.....0..|
-00000310  2a 1a 15 17 03 03 00 99  85 b3 e4 18 6f 8d 34 c7  |*...........o.4.|
-00000320  3d 66 49 b8 f6 f5 aa 7a  e1 ca ba cb 48 53 15 bb  |=fI....z....HS..|
-00000330  e9 ec 74 91 c3 b5 d3 6b  bc 84 81 d8 e1 a4 31 62  |..t....k......1b|
-00000340  d5 19 6d 2f 15 4c f3 8a  3b ec 41 12 89 be d3 cc  |..m/.L..;.A.....|
-00000350  ab 08 59 a7 79 5d 77 14  ce b1 98 b4 ce 71 7b ad  |..Y.y]w......q{.|
-00000360  ba 41 3a 7f 9a f8 23 5c  c6 fb b5 7b cc eb 0e 7a  |.A:...#\...{...z|
-00000370  ee af 3d ff 4d 03 ba c2  2a af ac fd b5 e8 5b 43  |..=.M...*.....[C|
-00000380  3e 37 ef 84 3d 66 af 3c  8e 1d 0d 36 bd df 25 dc  |>7..=f.<...6..%.|
-00000390  74 89 9c e6 da 18 c4 c8  b5 6c 3c 4c a6 ac 10 28  |t........l<L...(|
-000003a0  67 c0 a7 02 6c d4 8c a1  ca 66 ec 30 65 a6 af f7  |g...l....f.0e...|
-000003b0  e3 17 03 03 00 35 46 33  9b 78 59 93 b5 3d 99 22  |.....5F3.xY..=."|
-000003c0  56 3b 26 82 9c d4 08 36  5a 07 c6 d7 5b 4f c8 d9  |V;&....6Z...[O..|
-000003d0  32 8b cd f1 e7 81 58 a8  98 b6 61 f6 9e 75 0c 52  |2.....X...a..u.R|
-000003e0  5a a1 e8 b1 97 8c 94 52  82 5e e8                 |Z......R.^.|
+00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 42  |..+.....3.$... B|
+00000060  80 fb 4a d3 49 53 a5 9f  f6 da ca 64 f8 5d 2c f5  |..J.IS.....d.],.|
+00000070  45 4d f1 a5 ec c3 c6 fc  d2 ff 56 b1 63 53 1a 14  |EM........V.cS..|
+00000080  03 03 00 01 01 17 03 03  00 17 f8 d8 e1 1a e0 c8  |................|
+00000090  75 f9 40 90 da 16 a0 41  4f 8c 23 e7 47 43 89 cf  |u.@....AO.#.GC..|
+000000a0  d4 17 03 03 02 6d d6 23  1d c6 c0 d4 5e a3 fe 2b  |.....m.#....^..+|
+000000b0  03 04 6c 88 d1 4a ac 9b  dd 90 e5 18 c5 35 9c 4a  |..l..J.......5.J|
+000000c0  f3 c4 64 e2 c2 40 62 fb  68 b3 22 37 9f f4 eb ae  |..d..@b.h."7....|
+000000d0  45 d9 a8 be f4 1e 89 16  88 b5 10 e3 5c 2e 42 15  |E...........\.B.|
+000000e0  34 24 f3 bd dd 73 6d 6b  d1 db 3e 69 b0 0a 54 e6  |4$...smk..>i..T.|
+000000f0  b7 2c b7 80 86 93 91 d5  26 02 77 bf 10 38 ee 40  |.,......&.w..8.@|
+00000100  22 4d 3f 67 02 6b f8 1c  4a ad 2b c7 f6 19 d4 36  |"M?g.k..J.+....6|
+00000110  9b ff c4 08 73 e1 48 0a  a6 e8 80 3b 88 8a c2 e8  |....s.H....;....|
+00000120  c6 4a ae da a1 4f 3b 9e  fb 80 3b 78 ca 80 42 00  |.J...O;...;x..B.|
+00000130  a4 5c 9d a0 6c 63 a7 66  e6 26 b7 14 d8 8b ba 1a  |.\..lc.f.&......|
+00000140  4b 13 81 3c e4 76 4e ac  6c 2f b4 71 e9 dc c4 c8  |K..<.vN.l/.q....|
+00000150  ef f0 61 22 f4 6b 83 ae  d8 d0 a7 c6 d9 ea 95 85  |..a".k..........|
+00000160  77 90 0f 22 a0 50 cb ff  50 a5 98 ee de e4 89 f3  |w..".P..P.......|
+00000170  20 f2 63 a2 45 3a 48 33  d5 b9 ff 5e f8 7d c5 2d  | .c.E:H3...^.}.-|
+00000180  b9 9c b2 65 bf d5 13 36  46 a5 96 9f f4 de 7c 1c  |...e...6F.....|.|
+00000190  78 3f 1a 0a 62 14 13 8e  55 7e cd 47 87 1b 7e a8  |x?..b...U~.G..~.|
+000001a0  7f 03 ec 1c d3 72 eb e5  94 d9 9d 95 d6 f5 ad 2c  |.....r.........,|
+000001b0  e9 7d 0f 2c ea 7b 1e 8e  d7 b4 f1 5d 12 be d7 cf  |.}.,.{.....]....|
+000001c0  b7 43 89 65 e9 04 0e f8  b4 b4 4d 9c 9c 42 3c 50  |.C.e......M..B<P|
+000001d0  a7 91 d0 7f c0 de fb 99  08 ce 5c fd 67 3a cb 1a  |..........\.g:..|
+000001e0  d3 1a 4c a2 2e 7d 73 01  2b 5f bb a2 86 7d 0e e0  |..L..}s.+_...}..|
+000001f0  a1 c9 06 c0 4a 0a f6 c6  c4 b5 53 51 3e 2f f4 60  |....J.....SQ>/.`|
+00000200  1d 41 55 9d c4 88 f3 76  4f 92 b5 03 98 23 6b c4  |.AU....vO....#k.|
+00000210  c3 62 bd 12 dd 3a bc 37  d0 18 64 c6 e1 2c cb 62  |.b...:.7..d..,.b|
+00000220  f6 d3 24 35 47 e7 cf 15  d3 53 9d ac 3f 97 48 c1  |..$5G....S..?.H.|
+00000230  b8 d3 a3 2c 9f cd 2b 72  bc bd a6 8a b1 54 48 7b  |...,..+r.....TH{|
+00000240  e0 b7 a2 2e 46 04 cc e5  29 1d 73 c7 67 f8 f0 d8  |....F...).s.g...|
+00000250  e0 88 f0 7b 11 ff e1 1d  95 6c 85 c4 08 72 3e 94  |...{.....l...r>.|
+00000260  92 4b 8a 58 62 04 10 83  7c 5e 65 20 a7 5d 6d 16  |.K.Xb...|^e .]m.|
+00000270  30 64 fc aa 7f 8f 06 ed  4e 3c 86 c8 10 92 fb 0d  |0d......N<......|
+00000280  7b 81 10 07 cf 30 7f 6b  11 63 60 2a 61 92 cb 74  |{....0.k.c`*a..t|
+00000290  82 a4 04 cf 23 43 21 55  45 2a 29 93 42 0f 0c f6  |....#C!UE*).B...|
+000002a0  9b 14 b5 96 09 25 1b bc  b0 7b 72 e2 6f b8 55 74  |.....%...{r.o.Ut|
+000002b0  00 bb 1c 7c b1 9b 58 63  97 bb 6d c5 fb a4 da 24  |...|..Xc..m....$|
+000002c0  1e b2 97 18 75 ab 8b a2  77 50 38 4d f8 a0 39 58  |....u...wP8M..9X|
+000002d0  8c 2d 3e ba 27 03 e9 51  87 0a 95 e0 08 40 5d e6  |.->.'..Q.....@].|
+000002e0  6a dd 10 1d 6d 8c 32 88  a8 32 ee dd 44 9c 9b b0  |j...m.2..2..D...|
+000002f0  6f f5 4b 08 60 9d 83 1e  ab 83 c0 92 10 c7 aa 90  |o.K.`...........|
+00000300  d2 b2 61 5e 12 b5 e8 ea  a7 68 59 17 a4 f4 15 f7  |..a^.....hY.....|
+00000310  dc 10 81 17 03 03 00 99  8a 61 79 8f 33 51 7b a9  |.........ay.3Q{.|
+00000320  ce 3f 82 2b bb da 40 2e  73 c8 d9 6e 7d 72 ba 94  |.?.+..@.s..n}r..|
+00000330  7d ad fb b7 ba 9c 74 00  0b c9 1d b6 8d 54 b9 48  |}.....t......T.H|
+00000340  eb 49 78 c3 1a 75 b8 16  22 5d 50 f5 4a 81 59 d3  |.Ix..u.."]P.J.Y.|
+00000350  38 79 38 c1 35 11 55 69  6b d2 86 3c 0f 12 26 57  |8y8.5.Uik..<..&W|
+00000360  f5 84 d7 dd 74 61 6f b8  08 66 e9 3c f7 43 29 a5  |....tao..f.<.C).|
+00000370  94 9e ab af 68 04 c1 6a  ae 9d 12 2d 57 e9 ff 30  |....h..j...-W..0|
+00000380  7d 80 35 65 cc df c8 65  0b a1 f9 6d 6b a5 0b df  |}.5e...e...mk...|
+00000390  0c 1a 04 0a 00 8f ac 2b  29 60 92 4e 91 d3 42 25  |.......+)`.N..B%|
+000003a0  b4 a5 0a 1a 5f 83 ec 9a  f0 0a 2c 6d 65 00 24 d3  |...._.....,me.$.|
+000003b0  e1 17 03 03 00 35 e4 72  aa 9e 6c a8 93 7b e4 49  |.....5.r..l..{.I|
+000003c0  1e 23 7c 50 18 59 00 08  3b f1 c1 5f 20 ba 51 56  |.#|P.Y..;.._ .QV|
+000003d0  fe bb 93 99 52 e6 5e 6d  26 cc 60 11 c2 a1 c8 18  |....R.^m&.`.....|
+000003e0  2e 72 bd ee 36 ca 41 25  73 f2 30                 |.r..6.A%s.0|
 >>> Flow 3 (client to server)
-00000000  14 03 03 00 01 01 17 03  03 00 35 55 88 37 f3 ee  |..........5U.7..|
-00000010  c5 1b 20 ac fe bc a3 f8  c9 59 3f 5f c0 81 40 8f  |.. ......Y?_..@.|
-00000020  1e a9 44 c8 10 16 69 8a  76 45 17 51 06 9e f0 55  |..D...i.vE.Q...U|
-00000030  a2 f2 56 98 7d a1 4d 95  5a c3 1f 51 cf 31 20 ca  |..V.}.M.Z..Q.1 .|
-00000040  17 03 03 00 17 81 2a 8e  32 29 ec 9b 92 c3 fd 98  |......*.2)......|
-00000050  64 aa 47 2a a5 0c d6 77  7f b1 8f 12 17 03 03 00  |d.G*...w........|
-00000060  13 60 8c fb 98 e1 03 b6  20 c8 45 4e d9 4b a8 17  |.`...... .EN.K..|
-00000070  10 79 5f b6                                       |.y_.|
+00000000  14 03 03 00 01 01 17 03  03 00 35 b6 c3 b9 b1 52  |..........5....R|
+00000010  88 d2 78 2b ec 1c 63 e8  d5 08 0e 4e d6 51 b9 02  |..x+..c....N.Q..|
+00000020  ba cc a8 ca b6 da 45 a9  7c 1a 18 39 47 84 db 34  |......E.|..9G..4|
+00000030  d6 05 6f e5 16 19 57 6f  65 0b 7a e7 37 b5 d3 28  |..o...Woe.z.7..(|
+00000040  17 03 03 00 17 dc b8 e2  1c aa b8 f5 cb b6 fd ba  |................|
+00000050  29 34 73 bb c6 e0 3a fc  3e fb d3 01 17 03 03 00  |)4s...:.>.......|
+00000060  13 eb 66 ab 47 38 1b 01  96 6c 59 46 c2 ad bf 2d  |..f.G8...lYF...-|
+00000070  36 22 97 19                                       |6"..|
index c8e95c85dfc1d8a2373f693f131acd7d26a148d8..251e339306f535d63c685d00647659d8811f75e0 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 7a 02 00 00  76 03 03 98 9a 92 3f c6  |....z...v.....?.|
-00000010  67 f5 96 5b 2f 5e 70 89  2d f6 1e ce 6f 6a e5 91  |g..[/^p.-...oj..|
-00000020  4b 4b 6f 98 cc f7 78 4a  b1 54 4a 20 00 00 00 00  |KKo...xJ.TJ ....|
+00000000  16 03 03 00 7a 02 00 00  76 03 03 ce 38 98 c9 b7  |....z...v...8...|
+00000010  f8 67 af 0d 29 52 88 a4  d0 c2 a8 10 c4 8e 80 26  |.g..)R.........&|
+00000020  43 84 0e 60 06 ce f0 b7  b1 cd 29 20 00 00 00 00  |C..`......) ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 01 00 00  |................|
-00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 58  |..+.....3.$... X|
-00000060  96 37 c3 41 35 73 13 21  fc 31 e3 09 33 48 15 be  |.7.A5s.!.1..3H..|
-00000070  31 fb 57 61 b2 c9 60 31  2d 68 83 d5 7c d1 3a 14  |1.Wa..`1-h..|.:.|
-00000080  03 03 00 01 01 17 03 03  00 17 1d ce 7d b7 ca e3  |............}...|
-00000090  10 82 cb f6 1d 52 61 41  29 57 e3 7e e5 88 5c 47  |.....RaA)W.~..\G|
-000000a0  16 17 03 03 00 42 1b 49  e1 4a d7 73 57 cd e9 b7  |.....B.I.J.sW...|
-000000b0  e2 47 d3 74 21 6a 14 1d  1b 8d f5 aa 4c 1b f8 61  |.G.t!j......L..a|
-000000c0  8c 3a e4 2e 9d ff 3f 7d  b2 4d 79 6e 1d 02 05 ce  |.:....?}.Myn....|
-000000d0  c3 ad e6 f9 2b 2b dd 75  3b 6f 3e 0b 29 07 09 74  |....++.u;o>.)..t|
-000000e0  d1 37 68 9b 8a b6 8d 2b  17 03 03 02 6d d1 1b 9f  |.7h....+....m...|
-000000f0  75 ba cf 2d 10 4b f0 4e  09 58 fa ff 06 e8 c9 d5  |u..-.K.N.X......|
-00000100  a0 51 c8 d4 6f b2 c5 c1  d5 f3 ff 12 1f 43 d8 74  |.Q..o........C.t|
-00000110  33 d9 9b e5 f3 34 26 0e  89 dc 00 54 67 17 d2 f3  |3....4&....Tg...|
-00000120  c9 9e be f8 4c 77 8a 63  b1 64 5a b4 d7 57 d2 89  |....Lw.c.dZ..W..|
-00000130  ce 68 d1 f7 93 01 6c 36  b7 c9 4d 50 d0 4b df 5e  |.h....l6..MP.K.^|
-00000140  8a bb 6c d9 54 57 9b b9  c9 ec d8 49 c7 51 3c e5  |..l.TW.....I.Q<.|
-00000150  7b fb 48 0f fd 1b dd 0f  57 d3 a8 ee f6 51 ba 78  |{.H.....W....Q.x|
-00000160  c0 60 f1 d9 c1 d2 65 b4  a7 98 99 fb 64 83 4c 2c  |.`....e.....d.L,|
-00000170  a6 e9 19 ef 0e 88 68 f8  21 a4 2b bd 95 e9 52 d5  |......h.!.+...R.|
-00000180  fb 12 d3 36 06 a2 13 f9  e2 35 6a 06 dd 49 d9 42  |...6.....5j..I.B|
-00000190  89 d9 f0 24 5c 36 b8 6d  95 35 21 b3 9c 3b ee 08  |...$\6.m.5!..;..|
-000001a0  06 06 4d aa 74 eb fc 1b  c1 fd cf 07 24 74 44 2d  |..M.t.......$tD-|
-000001b0  54 d5 c5 d3 4e c4 eb 09  6e 90 8f 3d c0 c5 1c 21  |T...N...n..=...!|
-000001c0  7c 32 1b bc 4b 85 2b f0  b0 f5 cd 61 3d dd 31 03  ||2..K.+....a=.1.|
-000001d0  5e e0 5e 06 1a 37 61 1a  58 fa ed e8 cf 0c 4f da  |^.^..7a.X.....O.|
-000001e0  73 69 42 3a f4 ed dc ad  e5 e7 9b fd 54 16 77 85  |siB:........T.w.|
-000001f0  ae 84 41 10 be 84 ad 28  ef e6 13 2a e9 9f 9f 2f  |..A....(...*.../|
-00000200  c5 d0 65 c6 f5 58 b3 39  9b 5e 07 ba 95 be 5e 75  |..e..X.9.^....^u|
-00000210  68 17 ba 9d 2a 69 6d b8  ed d4 4b 6a ce 30 b1 82  |h...*im...Kj.0..|
-00000220  ae ec 68 9a 26 13 6b 05  38 0f 38 c9 94 01 d0 0b  |..h.&.k.8.8.....|
-00000230  7b bb ca 70 86 6c e4 f1  eb 81 05 25 33 c0 3e e3  |{..p.l.....%3.>.|
-00000240  2a 25 8e 32 eb d5 03 c7  c4 d8 22 22 ef 99 5a a3  |*%.2......""..Z.|
-00000250  01 6a b5 65 9a 55 6e fb  84 83 aa 43 ae 4a 3e da  |.j.e.Un....C.J>.|
-00000260  40 7e 09 e1 3b 15 ad 33  66 5a 3d 30 62 72 86 54  |@~..;..3fZ=0br.T|
-00000270  cd a2 6a bf 82 61 17 87  84 c5 3f f3 1e 86 a2 b1  |..j..a....?.....|
-00000280  2c 1a f9 ba 8c a2 21 5b  93 b2 16 b4 81 ae 7d 98  |,.....![......}.|
-00000290  d6 db 0a 56 14 c9 f7 48  c1 c7 3c 7e 63 8e bc 50  |...V...H..<~c..P|
-000002a0  6a 64 e1 1d 04 ba d3 cc  6a 61 60 4b d2 97 d5 ba  |jd......ja`K....|
-000002b0  23 1a 69 76 86 db 96 39  04 f6 ec e9 96 79 6a 25  |#.iv...9.....yj%|
-000002c0  ff 39 dd 19 08 34 4d c3  f6 7c 91 f2 6b 3a e1 0f  |.9...4M..|..k:..|
-000002d0  66 6d 14 5d 82 21 0b e3  e0 c3 f1 a1 70 e1 2c bc  |fm.].!......p.,.|
-000002e0  fb 54 aa 85 3c a0 7c 9a  35 00 e2 a1 4f 83 3e f1  |.T..<.|.5...O.>.|
-000002f0  64 83 ab c5 e6 31 c7 00  eb 36 f1 bc 41 f3 eb d4  |d....1...6..A...|
-00000300  97 30 4d 7f d2 d1 e7 1a  9e a2 53 31 35 6a 16 d1  |.0M.......S15j..|
-00000310  65 be d7 d3 93 2a be d2  27 dc 1b 8c 09 16 30 d4  |e....*..'.....0.|
-00000320  cb eb e0 bb 42 50 ff 59  c3 81 81 36 88 09 c2 23  |....BP.Y...6...#|
-00000330  dc dd 80 63 bb 78 19 6b  6a 70 4b b5 17 bf ed 6c  |...c.x.kjpK....l|
-00000340  58 f1 15 a9 16 66 c8 45  f5 5f 99 05 b1 3b be e6  |X....f.E._...;..|
-00000350  66 d7 45 df 19 16 9d c7  dd 4d 17 03 03 00 99 38  |f.E......M.....8|
-00000360  70 9e 16 94 07 67 7c ce  90 67 99 46 5e d9 61 b5  |p....g|..g.F^.a.|
-00000370  9b b8 31 fc cc 80 a3 07  30 c9 f5 f9 90 fb e2 0d  |..1.....0.......|
-00000380  dc 93 ab de 38 25 83 f8  77 0c 94 53 75 68 c7 71  |....8%..w..Suh.q|
-00000390  72 6f 61 77 a7 d7 c7 ed  5c d3 08 18 9f 64 f4 6e  |roaw....\....d.n|
-000003a0  30 dc 05 b1 65 11 79 08  66 34 8c 06 99 a9 00 26  |0...e.y.f4.....&|
-000003b0  86 2c e4 b5 6d cf db b1  03 f0 d0 c5 c0 f5 50 04  |.,..m.........P.|
-000003c0  f7 27 97 3e 31 19 aa a8  58 c4 78 43 a9 e3 76 0d  |.'.>1...X.xC..v.|
-000003d0  98 88 20 07 11 4c d6 8a  66 31 72 2e ed 47 66 71  |.. ..L..f1r..Gfq|
-000003e0  9a 3e 9c 0d 1c 17 df ab  6a 52 b4 43 a6 c2 64 30  |.>......jR.C..d0|
-000003f0  45 08 b8 de 59 be 3a f9  17 03 03 00 35 94 9b 02  |E...Y.:.....5...|
-00000400  47 a6 e3 55 9f 95 8a 8d  35 3b bb 56 ec 10 ab dd  |G..U....5;.V....|
-00000410  a3 ca fe ad bf 25 90 76  c4 15 a0 c0 73 d5 96 96  |.....%.v....s...|
-00000420  44 bc ba e9 09 f5 8e e7  e7 7d db f2 e7 9f 99 d2  |D........}......|
-00000430  dc e7                                             |..|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 03 00 00  |................|
+00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 aa  |..+.....3.$... .|
+00000060  00 03 6d 16 04 54 48 55  4d f9 04 e8 29 ca 9c 5d  |..m..THUM...)..]|
+00000070  14 94 a2 7a 2e 0a 4e 75  12 2d 63 cf 19 81 21 14  |...z..Nu.-c...!.|
+00000080  03 03 00 01 01 17 03 03  00 17 7b 90 e1 af 77 ca  |..........{...w.|
+00000090  a1 3b a6 e0 9f ea 4b f6  3f 45 a0 78 1c fb af 51  |.;....K.?E.x...Q|
+000000a0  30 17 03 03 00 42 ff 27  8b 9c fd 65 d7 b1 d4 43  |0....B.'...e...C|
+000000b0  eb 8f c3 ca b4 57 be 35  35 75 35 cf 43 73 d6 14  |.....W.55u5.Cs..|
+000000c0  7e 2d b4 f8 31 60 1b 35  2a 38 91 32 40 8b f0 ab  |~-..1`.5*8.2@...|
+000000d0  a8 b0 dc 2b db b9 63 92  28 dc f2 c2 95 d3 4a 63  |...+..c.(.....Jc|
+000000e0  69 e7 58 0c e5 9c d5 22  17 03 03 02 6d 7c 70 9b  |i.X...."....m|p.|
+000000f0  e1 81 3a 0d 6e 7f 5c 30  2e 09 1d 82 ac 48 a6 7e  |..:.n.\0.....H.~|
+00000100  03 ce d0 ce e2 e8 9e 8b  2b ee af 1a b1 6a 3a 27  |........+....j:'|
+00000110  04 53 73 d2 d4 28 68 19  96 3a 3d 89 df 2c e3 2b  |.Ss..(h..:=..,.+|
+00000120  45 c8 5e 60 42 b0 4d f2  9c 8a 8d 83 f6 97 e0 b0  |E.^`B.M.........|
+00000130  02 39 37 46 2b 07 28 8b  e8 d8 c2 e3 ba 58 9b dc  |.97F+.(......X..|
+00000140  62 c4 e6 cb b4 97 f0 67  2b b3 40 4b 64 3e 73 3f  |b......g+.@Kd>s?|
+00000150  a1 1f 6e fe 7f ba af 7d  bd c4 7c 37 60 c0 94 d6  |..n....}..|7`...|
+00000160  bc 14 70 a9 95 a6 b7 88  9d 50 cf 9f 36 0c 38 c4  |..p......P..6.8.|
+00000170  97 ba ea 43 16 e8 fd 72  22 3c 09 4a 97 1c 97 70  |...C...r"<.J...p|
+00000180  88 6d d4 f3 9d b9 5a f3  67 f5 7b da 3e ed 1a 66  |.m....Z.g.{.>..f|
+00000190  4c 62 50 ff cd 92 08 d8  5c 2e 11 de ea 44 16 91  |LbP.....\....D..|
+000001a0  3e 44 d7 8c dd 2a b4 c7  2b 4d 40 a2 f9 7e 49 a9  |>D...*..+M@..~I.|
+000001b0  d8 51 a1 27 b3 34 75 59  04 04 cd 52 d6 37 34 e6  |.Q.'.4uY...R.74.|
+000001c0  41 32 36 45 c0 65 fb 5c  e2 21 77 7f 35 db 9d 34  |A26E.e.\.!w.5..4|
+000001d0  0d 6e 9d a7 9e 00 ec e3  3e 9c 50 50 13 5b ad b9  |.n......>.PP.[..|
+000001e0  b3 47 44 f8 9b 12 ab 50  7f a7 df 35 c5 d6 78 3c  |.GD....P...5..x<|
+000001f0  c1 04 41 db 99 18 cd 8c  05 3f 08 ae 2b 41 c9 46  |..A......?..+A.F|
+00000200  16 9a e3 a9 5b d3 9c 00  56 0e e2 d1 da 6d 6b 20  |....[...V....mk |
+00000210  65 1b 55 1f 4f b1 eb 94  c6 48 e3 50 d6 14 c5 62  |e.U.O....H.P...b|
+00000220  5e fc d2 cf df f4 68 90  c9 bb 80 54 f3 f3 a3 78  |^.....h....T...x|
+00000230  af 1f 6f ef e1 d5 64 24  04 e5 d4 59 bc 4d 7b a0  |..o...d$...Y.M{.|
+00000240  1a 23 e1 81 b7 c4 bb 52  86 f4 2a 85 d2 d0 7a ed  |.#.....R..*...z.|
+00000250  c0 5d 27 07 4b df 52 c4  ea c8 c9 9c f0 48 35 71  |.]'.K.R......H5q|
+00000260  bd 04 65 65 47 e3 21 88  ff 08 6c 6a f3 6c dd 81  |..eeG.!...lj.l..|
+00000270  3f 50 21 66 34 49 07 a0  e0 6d 80 54 77 8b 27 81  |?P!f4I...m.Tw.'.|
+00000280  4f b9 59 60 0a b0 c7 00  6a 7b 26 33 f6 5e ad 37  |O.Y`....j{&3.^.7|
+00000290  bf ea 87 e4 3c e7 b8 20  b0 89 88 ac 5a a4 af f7  |....<.. ....Z...|
+000002a0  23 3c 0a d0 ab 74 fc 49  d2 e5 51 a7 a5 4e 21 5f  |#<...t.I..Q..N!_|
+000002b0  90 9a 65 36 9f e1 e3 9e  3d 67 d6 93 f1 b8 f0 4b  |..e6....=g.....K|
+000002c0  c6 d8 ca 50 fb cc 92 ab  47 b5 8c 21 02 4a ee 42  |...P....G..!.J.B|
+000002d0  35 a3 52 41 04 94 19 cd  23 c6 33 b0 84 0d 88 97  |5.RA....#.3.....|
+000002e0  5a e0 3e 4c 6d 99 ec 6d  11 3f 19 e7 77 60 3b de  |Z.>Lm..m.?..w`;.|
+000002f0  6d 04 b8 ab bc 83 4f 51  a5 ba 56 56 d6 e3 ff 0e  |m.....OQ..VV....|
+00000300  d5 4b 75 29 6a f9 4b c6  ef fd 62 25 89 76 f1 fd  |.Ku)j.K...b%.v..|
+00000310  84 3f e9 93 63 cf eb 47  85 b1 aa a2 4c 94 6b 99  |.?..c..G....L.k.|
+00000320  98 6e 1a 19 85 0b 90 d2  9f 0f ec d4 36 1e 22 a0  |.n..........6.".|
+00000330  4e 7f a1 ae 90 15 68 8a  48 c5 06 01 aa b9 56 cb  |N.....h.H.....V.|
+00000340  e0 62 53 d8 96 56 61 1d  81 96 b8 66 ae 94 c8 5f  |.bS..Va....f..._|
+00000350  86 47 fe ca 27 8d 7f 8e  f8 74 17 03 03 00 99 ac  |.G..'....t......|
+00000360  2b 09 0b 44 a5 33 27 19  86 59 ca 75 5c df 59 fc  |+..D.3'..Y.u\.Y.|
+00000370  34 57 08 11 4f d8 1a c6  7c 76 d5 0a 36 91 f2 3a  |4W..O...|v..6..:|
+00000380  d1 96 58 64 29 3a d1 05  e3 cb 6f ea 92 4a f6 3b  |..Xd):....o..J.;|
+00000390  54 4c 16 41 99 6e 0f e9  c3 9a ac a3 59 ee fa c9  |TL.A.n......Y...|
+000003a0  4d 58 ae 23 58 58 b5 b5  d6 6a dd b4 0c 24 bf e1  |MX.#XX...j...$..|
+000003b0  d4 16 53 f2 2d e1 78 d0  ea 70 59 ac a3 e4 e4 6f  |..S.-.x..pY....o|
+000003c0  65 93 28 ad e1 64 83 11  05 42 a3 a0 11 d5 f2 af  |e.(..d...B......|
+000003d0  7e 03 93 80 82 48 e0 84  2e 1c 50 98 65 22 49 f1  |~....H....P.e"I.|
+000003e0  df 41 03 83 b2 5c 1c 56  cb b7 f3 72 04 d6 09 cf  |.A...\.V...r....|
+000003f0  f9 3a 5d e8 35 80 b6 a2  17 03 03 00 35 b4 b5 c3  |.:].5.......5...|
+00000400  43 78 3d e8 eb 66 7d 1c  36 8e a1 9f 26 ab 5a aa  |Cx=..f}.6...&.Z.|
+00000410  63 b6 2f 7a a5 f6 7d 89  1e 5d c5 a1 bf b4 3b 4a  |c./z..}..]....;J|
+00000420  89 1f 96 74 e3 c4 d8 72  57 a5 c7 99 a9 f3 77 16  |...t...rW.....w.|
+00000430  f3 25                                             |.%|
 >>> Flow 3 (client to server)
-00000000  14 03 03 00 01 01 17 03  03 02 1e 64 ba 97 ba 8d  |...........d....|
-00000010  3f 1b d5 5b c5 2e e5 b9  10 01 37 c9 5c e5 ed 39  |?..[......7.\..9|
-00000020  7f 9c 8b f8 ef 50 64 5e  30 05 16 ac 80 51 96 78  |.....Pd^0....Q.x|
-00000030  2a 50 0f 1e d8 76 ab fd  bd 7f 3b 17 7e 1d e9 f5  |*P...v....;.~...|
-00000040  03 76 1b 66 3d 15 dc f3  65 a2 aa a9 23 89 09 e9  |.v.f=...e...#...|
-00000050  dc de a6 27 fc 21 d9 97  d4 08 05 9a 1c 49 8c ee  |...'.!.......I..|
-00000060  fc bd f1 9f e2 4e 3a e3  ee 07 39 d0 34 05 cb 18  |.....N:...9.4...|
-00000070  83 2b 68 45 df 84 4b b2  c3 79 42 73 b9 f1 1c f2  |.+hE..K..yBs....|
-00000080  5f d9 5c f5 7c 4e 86 5e  97 78 ea 0a fa e7 60 68  |_.\.|N.^.x....`h|
-00000090  80 c3 17 5f e7 92 9d 6e  9a 92 37 84 92 4b 83 9c  |..._...n..7..K..|
-000000a0  fa 4c 2a 82 23 eb 67 d0  b2 cc 9e 59 8f 2c e7 bc  |.L*.#.g....Y.,..|
-000000b0  b3 4f 2a 0c 93 bf 17 b8  48 70 5e 0a 85 92 6d 2a  |.O*.....Hp^...m*|
-000000c0  ac 81 9e cd 2c 59 fc a7  e3 5b 82 d5 e3 f5 cd c2  |....,Y...[......|
-000000d0  8a 68 b8 e9 36 e2 08 0b  f7 09 9c 17 95 a3 5e 3d  |.h..6.........^=|
-000000e0  ef 7c c6 5c fe 32 9e 9d  31 c9 b7 76 5a 71 c3 d7  |.|.\.2..1..vZq..|
-000000f0  cd e3 c6 70 e5 2f 07 df  1d b4 34 56 0b ed 52 13  |...p./....4V..R.|
-00000100  bc b2 ac 66 0c 84 b0 2e  32 93 08 f2 04 91 8e e3  |...f....2.......|
-00000110  7b 7f 22 2a a9 04 50 5c  78 f1 06 c5 fd 2c 4c 77  |{."*..P\x....,Lw|
-00000120  a9 17 b5 a8 42 6d f2 0e  87 32 d3 7f be 9e 1d 09  |....Bm...2......|
-00000130  50 10 25 9d f1 a5 25 c3  c2 be 0d 8d 8e 96 5e 1c  |P.%...%.......^.|
-00000140  83 06 45 bc f0 5b 6f b5  0a 02 2a cc ce ac 7e 62  |..E..[o...*...~b|
-00000150  f0 b1 89 25 30 bc 12 d2  da f9 1d d0 46 55 97 4c  |...%0.......FU.L|
-00000160  09 39 e1 a5 1f 4d e1 aa  bd 6f 1f 0d 79 4a aa 49  |.9...M...o..yJ.I|
-00000170  73 25 dc a5 bd f7 2b 64  3c 84 ed b0 ef 13 c5 6c  |s%....+d<......l|
-00000180  16 8b 27 bf a5 3d 15 f2  4a 3b 53 ad ba e9 9e 2a  |..'..=..J;S....*|
-00000190  6d f2 44 5c 66 69 04 94  27 99 08 8e c2 7e c6 69  |m.D\fi..'....~.i|
-000001a0  f7 65 1d 0b a5 8c 35 52  0b f1 bd 59 ca d1 bf 44  |.e....5R...Y...D|
-000001b0  47 b0 7b f8 3b a0 84 55  73 c2 83 bb 9d e0 bc ed  |G.{.;..Us.......|
-000001c0  60 07 32 ce 71 b3 60 12  ef ca 28 bb 6c fb bb c7  |`.2.q.`...(.l...|
-000001d0  3e eb 05 65 a5 26 1a 6c  40 c8 b4 4e 31 12 a0 96  |>..e.&.l@..N1...|
-000001e0  19 66 86 f5 1e f8 bd 6d  f4 2e 98 60 fe ff 22 1e  |.f.....m...`..".|
-000001f0  a9 27 49 87 77 7d b4 5d  ea f8 bc 3a 10 15 84 8c  |.'I.w}.]...:....|
-00000200  cd aa 2c e8 94 93 a5 ee  db 7a d8 96 e9 d5 68 e9  |..,......z....h.|
-00000210  34 68 40 5b dd 18 dc f0  ef b7 17 72 fd 06 70 d1  |4h@[.......r..p.|
-00000220  b6 89 ae 66 40 40 f7 61  0b 17 03 03 00 a4 26 c1  |...f@@.a......&.|
-00000230  3c d9 6c 83 52 e3 5e 64  46 7f 12 1d 3d c7 7d 0f  |<.l.R.^dF...=.}.|
-00000240  a9 8f d3 45 f5 81 46 16  24 c6 c3 7e 5f e4 25 be  |...E..F.$..~_.%.|
-00000250  00 33 7a 1c 35 d4 5c 64  54 56 08 66 4d 2f 68 15  |.3z.5.\dTV.fM/h.|
-00000260  1b 71 d9 aa c9 9e e0 cc  d2 73 a9 99 41 9b 08 1f  |.q.......s..A...|
-00000270  d4 41 de e5 4f 1f 30 65  61 02 8e 6f 79 d7 47 86  |.A..O.0ea..oy.G.|
-00000280  2f e6 0e 65 9e 06 e8 98  d1 fe bc 89 b4 bc f4 9b  |/..e............|
-00000290  70 02 06 e4 9d 37 dd 1b  63 b6 06 62 1a c7 45 30  |p....7..c..b..E0|
-000002a0  9d 08 64 35 8b 96 88 9a  1e 58 2f d0 ef 44 39 04  |..d5.....X/..D9.|
-000002b0  3c bf e2 e6 c4 73 de f9  b0 10 ed 56 eb 04 bd 4e  |<....s.....V...N|
-000002c0  89 38 50 3b e7 e5 12 7c  8e 74 b2 a5 79 2d 88 7b  |.8P;...|.t..y-.{|
-000002d0  e5 1b 17 03 03 00 35 42  b2 61 24 4c 38 b5 d1 42  |......5B.a$L8..B|
-000002e0  93 12 66 c5 be 3c f0 b1  b2 6b 86 07 99 7d f3 e4  |..f..<...k...}..|
-000002f0  74 2b 43 98 38 df 70 7a  e5 f7 67 cf c3 08 23 19  |t+C.8.pz..g...#.|
-00000300  4a cf 06 26 fe 56 4a 97  4a 82 70 09 17 03 03 00  |J..&.VJ.J.p.....|
-00000310  17 9b 3f bb 09 7d 4f c9  05 42 f7 d1 a7 59 0c a7  |..?..}O..B...Y..|
-00000320  c6 9b 36 e1 46 ad 9b 89  17 03 03 00 13 ae a5 51  |..6.F..........Q|
-00000330  76 d8 3a 77 a8 a0 38 70  bf be c8 fb ff fe 53 09  |v.:w..8p......S.|
+00000000  14 03 03 00 01 01 17 03  03 02 1e 2e 1c 18 ac 6e  |...............n|
+00000010  bd d7 35 f8 21 6f 36 d7  13 94 53 3b 56 5d 03 8e  |..5.!o6...S;V]..|
+00000020  2d 92 fa cb 17 d3 75 55  13 84 9c aa be f7 34 9e  |-.....uU......4.|
+00000030  35 67 9b 90 bc 76 5d 65  c0 23 b0 04 d0 ba 15 b5  |5g...v]e.#......|
+00000040  30 70 4d 8d d2 38 73 0a  3a 58 c3 bc da a4 f5 ae  |0pM..8s.:X......|
+00000050  05 ee 0c 06 bd 06 fe ab  1b 31 cf 4d 46 63 cc ee  |.........1.MFc..|
+00000060  8f 8a 0d e9 32 50 4d a0  f6 f2 ce c5 be 41 c2 16  |....2PM......A..|
+00000070  a7 c3 b3 8a 5c 27 4a fd  37 2d 32 d9 76 25 27 12  |....\'J.7-2.v%'.|
+00000080  03 b9 e7 ef bc c8 59 e1  16 80 dc b2 16 ae 05 b6  |......Y.........|
+00000090  cf 8e 99 0d f8 ed 5a b1  bb c1 05 d5 35 fe fd 2d  |......Z.....5..-|
+000000a0  97 c6 19 d8 2d 1a a9 30  d1 4a 6d 27 45 93 5f 5d  |....-..0.Jm'E._]|
+000000b0  45 f4 98 a8 d8 88 27 8f  f2 ad 1e 24 6e c8 8f 12  |E.....'....$n...|
+000000c0  f7 32 b5 3d 3c e3 e0 32  56 4e 80 a8 5f 27 f0 d0  |.2.=<..2VN.._'..|
+000000d0  a1 c2 d0 22 2d 3a 36 0f  bd 7b 94 9f ca 8d c1 ea  |..."-:6..{......|
+000000e0  c6 1f d8 87 4a 75 bd 3e  0f ae 2f e1 78 ae 3f 00  |....Ju.>../.x.?.|
+000000f0  f4 3a 82 dd ec 3f 61 43  bf 4b f8 01 a3 32 df 13  |.:...?aC.K...2..|
+00000100  61 45 ca bb e0 9a 17 85  45 90 c6 fb 5d 79 1b 58  |aE......E...]y.X|
+00000110  54 ca 84 e9 a9 11 c4 74  82 f7 da e4 b3 4f 05 a1  |T......t.....O..|
+00000120  23 72 9f 63 b8 4c 55 e6  da 33 b9 1c b0 fe 28 72  |#r.c.LU..3....(r|
+00000130  f0 02 b6 ec 70 ae 27 d4  21 51 32 56 32 4e e7 7d  |....p.'.!Q2V2N.}|
+00000140  b8 0d 75 25 45 5c 68 83  4f e3 3e 8a 87 7c 06 81  |..u%E\h.O.>..|..|
+00000150  ac ff 23 44 0e bd e7 0a  76 64 45 c4 04 df 35 db  |..#D....vdE...5.|
+00000160  ab 8a 38 87 f5 e5 35 75  7a 92 85 3d 14 9e aa 19  |..8...5uz..=....|
+00000170  4d 94 25 8f c0 c3 37 ca  63 f3 dd 48 4a 6a 6b f5  |M.%...7.c..HJjk.|
+00000180  fa 52 67 30 ab ff 56 9f  58 bd cd 66 d4 83 85 d8  |.Rg0..V.X..f....|
+00000190  85 6c 6d 3c 56 e5 17 75  fc dc a7 3d ed 18 a1 3b  |.lm<V..u...=...;|
+000001a0  6c e6 54 95 75 38 77 77  90 34 81 cb 1c cb e9 04  |l.T.u8ww.4......|
+000001b0  c8 d2 12 04 36 a8 9b f6  9b 6a 81 8d f5 b1 e2 ca  |....6....j......|
+000001c0  31 37 27 f2 84 bd 5c 3a  1c 6c 64 83 35 94 89 ee  |17'...\:.ld.5...|
+000001d0  08 42 1d 05 52 67 e6 4d  7f bb d2 21 82 8c 15 6b  |.B..Rg.M...!...k|
+000001e0  e9 f9 6d bc b3 1f 5a df  b8 55 aa 9d f6 aa d2 7c  |..m...Z..U.....||
+000001f0  41 76 3b 1b b2 f5 b8 49  32 be bb f8 0e d3 74 be  |Av;....I2.....t.|
+00000200  eb 0d 9b e2 57 b6 ec e5  61 d7 09 80 a8 63 b4 cf  |....W...a....c..|
+00000210  bb 0a 14 9d 39 1c 08 58  22 c4 ae d5 4f 42 97 14  |....9..X"...OB..|
+00000220  71 e1 c0 a5 5e 8e 2f 89  27 17 03 03 00 a3 f0 96  |q...^./.'.......|
+00000230  d3 9e 8c 19 84 9a 42 d3  84 64 a6 89 40 6f d6 c9  |......B..d..@o..|
+00000240  50 90 bb 9d 16 90 9d fb  aa 85 28 ab 25 63 78 a9  |P.........(.%cx.|
+00000250  dd dc 35 03 73 08 26 2b  30 53 84 f8 74 66 f2 6f  |..5.s.&+0S..tf.o|
+00000260  d7 0a f0 e2 c4 10 a4 46  cf 77 ea cb b7 b7 a9 81  |.......F.w......|
+00000270  5f 09 4a 6a a5 16 a4 79  dc b0 c9 ae 5a ff 2a 7b  |_.Jj...y....Z.*{|
+00000280  3f bd 7a 15 b3 02 ad 3e  90 37 46 51 71 fc 6d d0  |?.z....>.7FQq.m.|
+00000290  9f 38 42 95 1a 88 ac 5f  83 a1 8a 59 59 62 cc 4a  |.8B...._...YYb.J|
+000002a0  57 d2 3e 1e 7e 1d c0 4d  41 23 85 5f 92 f4 63 16  |W.>.~..MA#._..c.|
+000002b0  df df 6e 3d d7 c1 e6 21  22 0f e1 13 82 29 a6 e3  |..n=...!"....)..|
+000002c0  f8 8c a4 a3 72 1d 61 c1  2a 9d a8 2d 13 8a 4f 87  |....r.a.*..-..O.|
+000002d0  91 17 03 03 00 35 9d 35  c8 ac 1e c6 46 8d e1 42  |.....5.5....F..B|
+000002e0  68 e5 79 77 64 15 e2 13  c0 70 1a 47 59 d0 1e c3  |h.ywd....p.GY...|
+000002f0  68 f7 5a fe 11 a2 3d e4  6e 2c b5 7d ea 98 e7 75  |h.Z...=.n,.}...u|
+00000300  7c 54 a4 35 9b 1f c9 ba  72 b1 94 17 03 03 00 17  ||T.5....r.......|
+00000310  a3 81 17 ac 97 a9 f0 91  b5 7a 04 38 ff fd 8e d3  |.........z.8....|
+00000320  d8 7b c4 40 7e d3 ea 17  03 03 00 13 a8 b1 06 94  |.{.@~...........|
+00000330  90 83 62 d5 be a8 23 d5  8b af 77 0d 90 13 98     |..b...#...w....|
index 26f76bc1b120eab6a8153f390e73b8cccccfe752..689c28750bf678fa7878d8ae380bf942ba15917c 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 7a 02 00 00  76 03 03 a5 5b a0 2c f5  |....z...v...[.,.|
-00000010  57 cc 49 88 64 7d ea 7c  ee 61 cf fc 94 9f d4 5c  |W.I.d}.|.a.....\|
-00000020  bb 83 80 5a f5 7c a3 fc  0a c8 61 20 00 00 00 00  |...Z.|....a ....|
+00000000  16 03 03 00 7a 02 00 00  76 03 03 4e 4c 01 f1 4e  |....z...v..NL..N|
+00000010  49 97 ec eb df ce 50 4d  1c 9c d0 35 92 10 97 0a  |I.....PM...5....|
+00000020  dd fb a8 4f 39 c6 14 21  d6 42 ac 20 00 00 00 00  |...O9..!.B. ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 01 00 00  |................|
-00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 fe  |..+.....3.$... .|
-00000060  e1 43 bd 10 b3 f6 3b 4d  7c 46 8f a3 bc 7d 08 08  |.C....;M|F...}..|
-00000070  22 ed aa 9b 7b 89 f3 87  13 7e fe 6c b0 db 3f 14  |"...{....~.l..?.|
-00000080  03 03 00 01 01 17 03 03  00 17 2b ce 52 22 34 c5  |..........+.R"4.|
-00000090  d9 2c ae d0 23 4d 0c 6e  b4 f0 c8 58 11 22 54 bb  |.,..#M.n...X."T.|
-000000a0  15 17 03 03 00 42 96 b4  72 be f0 6b d3 b0 82 7c  |.....B..r..k...||
-000000b0  dc d2 67 69 2c d4 40 a1  7a 3d 9a 39 a5 29 ca 64  |..gi,.@.z=.9.).d|
-000000c0  c5 0b d2 ba 7c c3 73 e2  93 0d 44 e3 64 ce ec b2  |....|.s...D.d...|
-000000d0  90 ae e2 df 18 f8 f5 93  5f 91 80 c2 b4 00 e7 de  |........_.......|
-000000e0  f5 3f 4d c8 de 4c 5f f0  17 03 03 02 6d c6 df 33  |.?M..L_.....m..3|
-000000f0  1e 12 40 02 7f 46 67 d8  4b 98 d7 5e f7 0a bf dc  |..@..Fg.K..^....|
-00000100  fe 3c 7f 00 2d 74 31 cb  10 35 e2 eb 16 11 d1 2f  |.<..-t1..5...../|
-00000110  10 bf 8c 4d 37 c7 1b f6  23 a3 3e 68 87 1a 50 53  |...M7...#.>h..PS|
-00000120  64 7c 0d fd 0d 06 32 93  17 85 da e0 d4 86 2c 5f  |d|....2.......,_|
-00000130  0a 91 9a fd 00 87 f1 f4  fc 18 22 a1 2e 21 44 7d  |.........."..!D}|
-00000140  6c ca 2c 0d f2 38 15 d1  9d 86 9b 67 b6 b4 06 6d  |l.,..8.....g...m|
-00000150  30 07 a8 b1 b8 7a 5d 1d  17 d0 c5 1a 40 a3 42 b5  |0....z].....@.B.|
-00000160  dc 56 c8 ec c3 c3 4e ff  5f 7c ce 27 fa a6 82 2a  |.V....N._|.'...*|
-00000170  b9 85 47 4e 0b d1 84 17  92 a6 42 86 9a 65 1c a9  |..GN......B..e..|
-00000180  45 be af a7 95 03 0b db  84 fa 5d 1b 7e 57 72 40  |E.........].~Wr@|
-00000190  ab a3 9e 46 50 3f c7 03  94 9a 4a 02 bd 9a 90 1c  |...FP?....J.....|
-000001a0  42 c9 98 e9 81 cd e8 73  a6 82 42 20 24 89 d5 8d  |B......s..B $...|
-000001b0  48 20 df d4 f4 d2 15 e4  c0 28 ee d8 2a 1b ad b8  |H .......(..*...|
-000001c0  1d a4 86 e1 b4 89 97 e8  36 63 aa 9c f4 7e 65 c6  |........6c...~e.|
-000001d0  12 86 41 54 b3 4a 79 9f  48 33 fc fc 0d f5 14 47  |..AT.Jy.H3.....G|
-000001e0  ba ae d3 20 64 37 f1 cd  9e 1b cc b2 27 68 e6 f2  |... d7......'h..|
-000001f0  95 0c 29 59 f2 15 2e 97  60 f3 8d 1b b1 65 cd 4f  |..)Y....`....e.O|
-00000200  0d a5 0a 34 59 63 20 f0  71 e6 d5 13 f2 4e dc 73  |...4Yc .q....N.s|
-00000210  5b 1a 36 d7 6a aa b0 30  f4 ff 68 ad f5 5e f0 12  |[.6.j..0..h..^..|
-00000220  0c 34 a8 4d 91 03 8e 4a  30 07 23 49 41 7a fe 19  |.4.M...J0.#IAz..|
-00000230  62 5b 6a a0 4d d5 54 a1  1f 45 91 86 b3 a1 c3 32  |b[j.M.T..E.....2|
-00000240  62 79 a8 93 b3 d4 43 0c  a8 12 10 4f f5 53 c3 3b  |by....C....O.S.;|
-00000250  d9 73 ef 42 be 1d f5 70  fd 9f ca 54 20 3a 33 c9  |.s.B...p...T :3.|
-00000260  f6 e8 55 13 b3 ab 45 c8  bb 5c 6b b9 39 a9 04 ac  |..U...E..\k.9...|
-00000270  1c 3c 5a aa b7 91 2c 0c  f6 74 ea 6b 2d e2 9a 3c  |.<Z...,..t.k-..<|
-00000280  d0 30 d8 14 e5 8c bf 06  2c d3 89 2e 0d ad df c5  |.0......,.......|
-00000290  5b 6d fa 8f 0c 64 cc 40  04 12 97 ab ab ff be d8  |[m...d.@........|
-000002a0  a6 fc 78 1d d4 18 90 bf  b4 8e ce 09 40 8c dd 8a  |..x.........@...|
-000002b0  a8 cc 86 ce 6d a8 0c f8  79 66 f6 0b 46 2b 0d 4c  |....m...yf..F+.L|
-000002c0  73 14 dd cd 2c 56 77 f7  1f 4d 85 d0 1c 16 da 26  |s...,Vw..M.....&|
-000002d0  b0 65 39 31 b5 cd f3 7a  80 52 96 6d 81 1e 65 98  |.e91...z.R.m..e.|
-000002e0  b2 a3 12 22 52 68 c5 59  19 a1 9a be 80 5c 25 57  |..."Rh.Y.....\%W|
-000002f0  9b 60 e9 95 28 4b 77 a0  70 ce 4b 5b 70 37 0a e3  |.`..(Kw.p.K[p7..|
-00000300  7e 2c c7 0e 1c 6b 3a 54  2c 0d b3 53 0c f4 12 66  |~,...k:T,..S...f|
-00000310  c6 17 04 88 f5 12 58 d8  2c 70 54 85 2b 71 ee 98  |......X.,pT.+q..|
-00000320  75 8d e4 57 7c 96 a2 44  12 77 f0 6d 8a 12 89 b3  |u..W|..D.w.m....|
-00000330  8b 85 bf 33 d9 ee de 24  b5 7d d5 cb 0d d4 9b bf  |...3...$.}......|
-00000340  c6 e3 27 44 f2 35 35 09  00 86 eb 8b 34 c4 c4 6a  |..'D.55.....4..j|
-00000350  fe 95 e9 80 58 4f 3e 99  24 f8 17 03 03 00 99 de  |....XO>.$.......|
-00000360  1b f5 7a dc 63 8d 5e 75  de 72 cf 41 ca 75 ab d9  |..z.c.^u.r.A.u..|
-00000370  55 b0 b5 81 a9 6c a9 f6  1d ea 66 dd dd 86 f5 03  |U....l....f.....|
-00000380  12 08 9d b4 07 48 eb 8b  45 f1 35 b1 31 bd 5d f3  |.....H..E.5.1.].|
-00000390  e2 34 73 9a e5 87 b7 8b  0b 8b ab 7e 05 db 56 db  |.4s........~..V.|
-000003a0  4f 4c 52 1a 3b 5d 4c 53  b1 49 40 81 5e 73 af 26  |OLR.;]LS.I@.^s.&|
-000003b0  21 e6 e3 5c 4a a6 f6 07  56 de f5 76 5c 67 d8 d5  |!..\J...V..v\g..|
-000003c0  eb f3 6a fb 6d b7 00 bc  6b 28 c9 63 4d 58 76 97  |..j.m...k(.cMXv.|
-000003d0  aa 51 2b f3 03 9c 70 3b  3e b2 a4 16 a0 a0 e0 43  |.Q+...p;>......C|
-000003e0  77 da 88 2d 48 3b 07 e2  8d a6 e2 80 85 68 ac dc  |w..-H;.......h..|
-000003f0  ce 66 2f 97 20 9e 4e 33  17 03 03 00 35 f6 ce 98  |.f/. .N3....5...|
-00000400  8b 01 f5 75 8e 98 42 02  b1 b8 90 f3 08 96 e8 5a  |...u..B........Z|
-00000410  d4 7c ef d1 62 1e b3 36  39 d9 b2 59 1f 1f cc 74  |.|..b..69..Y...t|
-00000420  f2 a8 62 11 00 28 31 fa  d9 5a 27 10 7b 93 ff de  |..b..(1..Z'.{...|
-00000430  a0 ec                                             |..|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 03 00 00  |................|
+00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 c1  |..+.....3.$... .|
+00000060  c2 ca 32 aa 48 d8 52 bc  c8 23 6d 98 18 3e 15 b6  |..2.H.R..#m..>..|
+00000070  0b 25 db f9 6f a7 e1 75  95 a1 46 d3 47 4a 0e 14  |.%..o..u..F.GJ..|
+00000080  03 03 00 01 01 17 03 03  00 17 87 10 92 da b4 9a  |................|
+00000090  03 a5 0f 73 e6 93 cb 71  1d 58 6e 5d 27 eb ee b6  |...s...q.Xn]'...|
+000000a0  c7 17 03 03 00 42 89 8d  57 16 95 5b f0 98 ad c7  |.....B..W..[....|
+000000b0  d7 94 ba 4d 7e 88 b9 8d  13 26 a6 6c 81 90 a6 1e  |...M~....&.l....|
+000000c0  2b 4e 91 70 e2 da 9d a2  0d 6f 9b 5b ee 69 58 a1  |+N.p.....o.[.iX.|
+000000d0  4c c3 59 57 28 62 b3 ed  26 15 79 db 01 8c 88 e3  |L.YW(b..&.y.....|
+000000e0  63 1f bc b0 01 c9 82 ca  17 03 03 02 6d e5 d6 77  |c...........m..w|
+000000f0  4e d3 af c3 5e 01 e9 1b  31 63 a4 84 d3 cc 2d f8  |N...^...1c....-.|
+00000100  5d 73 f9 3e 83 03 c5 c5  cd 95 00 7b f2 b5 79 fa  |]s.>.......{..y.|
+00000110  47 e5 07 89 a9 22 49 7a  7e 7e 6e d2 3b 68 e8 9c  |G...."Iz~~n.;h..|
+00000120  40 1c 86 2a 48 ee 59 8e  1c 04 8b 91 20 68 65 31  |@..*H.Y..... he1|
+00000130  e7 76 dc 6c 5a ce cb 32  d3 e8 71 7f 93 08 b5 01  |.v.lZ..2..q.....|
+00000140  84 0a b4 ec 80 68 69 9b  b3 4a 4a 4d 56 16 eb 42  |.....hi..JJMV..B|
+00000150  29 93 4d b4 76 f6 e0 15  fe 25 b1 cb 5a da 22 4b  |).M.v....%..Z."K|
+00000160  88 4c ec 66 48 09 e1 d1  0f 3e 3a ad 65 d7 d7 85  |.L.fH....>:.e...|
+00000170  1d cb 35 2c 84 60 ec a1  6d f1 60 cf c6 c7 82 1a  |..5,.`..m.`.....|
+00000180  7c 91 40 2e 3e 88 1f ff  79 2e 6e 97 c5 45 9f e1  ||.@.>...y.n..E..|
+00000190  bf 33 ad 65 df f3 ce 1a  d7 57 7e db f2 28 79 a9  |.3.e.....W~..(y.|
+000001a0  9e 4f 9e 8a ce 02 5a 18  bb f1 ac 72 5b 3f 4c 6b  |.O....Z....r[?Lk|
+000001b0  97 14 14 f9 82 8a 4f 99  21 98 db af 3e 08 ab 4f  |......O.!...>..O|
+000001c0  d8 3f f6 cc da 76 77 eb  02 39 0a 00 23 a5 e0 92  |.?...vw..9..#...|
+000001d0  01 10 3f 76 ab 1a 38 8e  f9 a1 d0 25 c3 9d 50 a4  |..?v..8....%..P.|
+000001e0  ef a5 8c f8 5d bc d9 fd  dd 25 cd 42 38 52 d1 cd  |....]....%.B8R..|
+000001f0  d2 1b fc ba 7d 8b bd 82  05 23 c3 9d 02 ff 1b 4e  |....}....#.....N|
+00000200  08 e1 f3 7c 35 15 0f e8  0e b7 8a e5 4a 2b da 45  |...|5.......J+.E|
+00000210  4a 72 9a 32 7e 55 52 65  d2 a8 32 90 53 bf 25 29  |Jr.2~URe..2.S.%)|
+00000220  1e 8d d7 a3 22 d6 40 19  95 58 a8 37 af a8 52 e7  |....".@..X.7..R.|
+00000230  79 b9 4e 61 d8 f0 7d d2  69 25 99 28 3f 31 f6 b2  |y.Na..}.i%.(?1..|
+00000240  44 65 1f 9c 41 08 17 c9  01 5d 20 ea ab fe 06 64  |De..A....] ....d|
+00000250  9a f4 d0 24 e0 b5 88 0a  2b 96 e9 71 11 a8 49 b4  |...$....+..q..I.|
+00000260  40 62 1b 45 15 47 cb a5  fc 4f 07 58 2b ef d4 5d  |@b.E.G...O.X+..]|
+00000270  df 40 38 6c 6e ca 63 c5  95 2d 79 26 86 ff 33 02  |.@8ln.c..-y&..3.|
+00000280  da 5a 85 0c 8f 7f 58 ba  ea 88 cf bc 51 92 12 86  |.Z....X.....Q...|
+00000290  f1 c1 f9 0a d0 6e cc b4  2b 16 98 ad f8 11 ad 63  |.....n..+......c|
+000002a0  82 d7 4e ea a5 ee 78 a2  9a 35 b6 b3 d9 24 cf 66  |..N...x..5...$.f|
+000002b0  03 d2 25 1f 15 37 c7 b5  8e bb 0a 40 0f 28 c2 16  |..%..7.....@.(..|
+000002c0  90 a4 61 9e dd fd b5 ad  97 39 0d 66 e7 fa 5b e2  |..a......9.f..[.|
+000002d0  c2 ef 44 5d 44 07 d6 c3  ed e2 89 6e 4c ed 79 42  |..D]D......nL.yB|
+000002e0  86 3b f4 94 0c 82 5e 52  ce 00 ab 5c 20 b4 18 db  |.;....^R...\ ...|
+000002f0  c9 fe 8b be 8d da e9 86  13 62 6b 8d 0d 57 c8 fe  |.........bk..W..|
+00000300  a6 4b 82 52 d5 d8 05 18  2f a0 43 d6 c8 89 fb e7  |.K.R..../.C.....|
+00000310  72 17 61 89 36 5b e0 aa  4d 6c 20 ee 68 db 32 e4  |r.a.6[..Ml .h.2.|
+00000320  97 9f 18 26 7c 1a cd e8  b9 05 ae fd 86 bf 0e 47  |...&|..........G|
+00000330  09 06 bd de 2d b9 50 6a  0c a6 27 04 5e aa e0 ce  |....-.Pj..'.^...|
+00000340  e7 cf 98 f9 7e 7d b9 4d  77 9a 88 3a d4 41 07 cc  |....~}.Mw..:.A..|
+00000350  87 b6 41 53 8b 8c 79 8e  07 b9 17 03 03 00 99 0b  |..AS..y.........|
+00000360  63 4e d8 79 d7 11 f2 46  00 6c 5d d2 9e 49 df 7e  |cN.y...F.l]..I.~|
+00000370  f2 96 1a 68 9d 6a 05 dc  61 45 47 a4 18 5c 65 04  |...h.j..aEG..\e.|
+00000380  00 38 d1 25 0c ff a3 a2  c0 c2 82 7f b1 1b a1 c6  |.8.%............|
+00000390  7b ac fb 71 48 b6 e4 e2  7b c4 d0 44 8e 22 d6 91  |{..qH...{..D."..|
+000003a0  99 87 a2 88 3d bb b4 80  13 57 2a 6a b0 2d 52 16  |....=....W*j.-R.|
+000003b0  d3 f2 e4 cd d0 79 9a 31  ce 68 65 b3 61 67 a0 b9  |.....y.1.he.ag..|
+000003c0  1e 6b 9f 73 dc 46 be 5e  df d7 c2 30 d5 60 b5 e5  |.k.s.F.^...0.`..|
+000003d0  60 cc 10 ae 9a f9 b6 9a  fd 14 b9 1e b7 3c 1d 3e  |`............<.>|
+000003e0  34 a6 49 d2 48 f7 24 56  29 c9 98 f1 33 b1 e5 5e  |4.I.H.$V)...3..^|
+000003f0  2c 7b bb 5f b6 53 6a c8  17 03 03 00 35 d9 af 32  |,{._.Sj.....5..2|
+00000400  1f a5 09 3f 8a 10 df a7  34 9b f8 ec 07 81 80 73  |...?....4......s|
+00000410  dc ba 09 fc 40 e4 1e df  f6 de 02 54 3c 7d ea 49  |....@......T<}.I|
+00000420  91 16 72 70 8e 1a 21 76  c6 00 0e 03 9f 0a 82 fe  |..rp..!v........|
+00000430  4c 18                                             |L.|
 >>> Flow 3 (client to server)
-00000000  14 03 03 00 01 01 17 03  03 01 50 57 2a 94 d7 c1  |..........PW*...|
-00000010  40 42 d3 aa e3 d8 b3 e4  13 ff 51 ee 8a 52 9d 9c  |@B........Q..R..|
-00000020  c4 a4 40 91 72 0f c9 4e  fe 56 22 89 ea fb 6d 05  |..@.r..N.V"...m.|
-00000030  a2 96 97 4b fa ef ec 13  b6 13 3b 69 6c 65 c0 74  |...K......;ile.t|
-00000040  e5 54 df a4 97 50 f7 85  a1 c7 fb 52 84 56 98 16  |.T...P.....R.V..|
-00000050  52 b6 eb 5a d0 72 6e 65  98 81 bb f5 2a 4c ed 1a  |R..Z.rne....*L..|
-00000060  90 e1 01 a6 2b eb e0 1d  06 ba 8a d4 47 45 90 f0  |....+.......GE..|
-00000070  91 bd c4 d7 54 ba 44 30  78 42 15 42 74 59 1c c7  |....T.D0xB.BtY..|
-00000080  56 34 39 64 8e f8 0a 0f  2b 35 0f 06 97 34 3e 5e  |V49d....+5...4>^|
-00000090  00 00 5a f0 07 0a f5 66  46 86 94 8c 0b 62 1c fd  |..Z....fF....b..|
-000000a0  cc cf fd 5d 06 96 1e 21  9e 20 d5 07 5f 5a 00 9f  |...]...!. .._Z..|
-000000b0  6f 80 36 5e aa 56 d0 07  00 20 08 55 48 fe 6c a1  |o.6^.V... .UH.l.|
-000000c0  b1 22 f3 94 54 7e 7e d5  e9 f0 71 69 01 fc bd 14  |."..T~~...qi....|
-000000d0  a1 de 38 e4 b4 02 88 3e  66 77 3b f7 aa cd 57 a3  |..8....>fw;...W.|
-000000e0  cf 6a 40 7d 93 75 79 3b  95 07 33 69 b2 8d 2a 37  |.j@}.uy;..3i..*7|
-000000f0  94 d3 8d d5 b5 8a f0 94  8d 1e b4 9e 02 4f 7d 83  |.............O}.|
-00000100  05 c6 c7 c8 a0 74 f1 88  f7 68 bf 4b e4 18 3b 6f  |.....t...h.K..;o|
-00000110  0c 6c a6 e7 75 50 b9 f6  68 2e 05 67 a3 47 df 22  |.l..uP..h..g.G."|
-00000120  fa ae c1 4f a8 3d f3 bb  dc 66 c3 b6 98 b7 8c 5b  |...O.=...f.....[|
-00000130  48 51 57 d7 43 b2 13 25  9e d5 82 6c 70 5c 42 53  |HQW.C..%...lp\BS|
-00000140  a9 e8 8a 12 26 cd 3a f8  f8 e5 97 84 55 89 09 d4  |....&.:.....U...|
-00000150  d4 20 40 d7 2d 6f 66 36  63 f6 53 17 03 03 00 59  |. @.-of6c.S....Y|
-00000160  2f f6 22 ce f3 86 f8 ee  b1 f6 49 de c8 bf 91 9c  |/.".......I.....|
-00000170  bc 2f fa 75 af 51 bc ee  b7 a5 a9 82 35 3b 83 9d  |./.u.Q......5;..|
-00000180  3d 9f 57 10 07 4b af 01  66 f0 39 dd f0 4a a7 90  |=.W..K..f.9..J..|
-00000190  f3 6c 28 97 80 0d a5 74  2d 22 a3 81 cd 64 2b 1a  |.l(....t-"...d+.|
-000001a0  d1 4e 2d 9e 8e 69 38 f8  11 9c 17 1f e6 c9 01 4e  |.N-..i8........N|
-000001b0  48 1f 80 43 26 d4 5a 82  30 17 03 03 00 35 e9 25  |H..C&.Z.0....5.%|
-000001c0  b9 01 8e 0d 51 be 9d d1  b4 2b 0a ee 36 69 85 1a  |....Q....+..6i..|
-000001d0  10 a8 ff 36 e7 21 b7 f2  54 75 ca 07 52 88 48 d0  |...6.!..Tu..R.H.|
-000001e0  ad 67 0b 92 52 70 fa 14  bc 7e 1d 43 f0 a2 7b df  |.g..Rp...~.C..{.|
-000001f0  ac 0c 19 17 03 03 00 17  98 76 d7 52 06 90 ef 00  |.........v.R....|
-00000200  21 5e ec ed 0e 35 77 ef  5c f1 32 58 33 0f 06 17  |!^...5w.\.2X3...|
-00000210  03 03 00 13 05 fb b3 c3  4d b5 a4 9c 52 ea bc d2  |........M...R...|
-00000220  86 08 26 b8 df 5c 4c                              |..&..\L|
+00000000  14 03 03 00 01 01 17 03  03 01 50 1d 6e 16 0d 4e  |..........P.n..N|
+00000010  c0 a2 41 c3 a2 84 c9 80  c0 f0 ef c0 5d 3a 3b f2  |..A.........]:;.|
+00000020  bf 1c 9e 79 d7 d3 94 0b  41 2d bc 50 eb 0f 60 f4  |...y....A-.P..`.|
+00000030  bd cd f6 03 22 7b 68 68  44 34 c9 0f 23 ca 76 6f  |...."{hhD4..#.vo|
+00000040  f2 97 38 07 43 56 7e b7  ce 67 68 67 37 34 d0 f7  |..8.CV~..ghg74..|
+00000050  c5 92 fd 65 98 b8 7e 5f  48 a8 a3 aa a8 96 65 b5  |...e..~_H.....e.|
+00000060  48 be 91 99 67 0a 37 c7  31 b4 43 ba 26 bb 87 98  |H...g.7.1.C.&...|
+00000070  3c 55 e4 63 b0 33 ca ee  0a a5 fe 36 88 ef cf f0  |<U.c.3.....6....|
+00000080  ab 6b 7d e8 f6 1f 14 12  49 f7 14 b7 12 bb d8 1e  |.k}.....I.......|
+00000090  e0 be ed 56 75 b9 ab 8a  20 75 d9 6f 45 2d 71 b3  |...Vu... u.oE-q.|
+000000a0  2f b7 cd 9c c5 16 ed 37  0e 08 15 a5 49 18 7c 13  |/......7....I.|.|
+000000b0  8e 0b 66 01 b1 8c 1d 89  d4 91 9e 5a 6b 94 f6 fa  |..f........Zk...|
+000000c0  7b a8 14 1c a7 20 55 c5  e4 0e 9d e0 5b d6 d4 b7  |{.... U.....[...|
+000000d0  1d 93 2b 7c 25 46 28 11  06 57 a3 cb 2f 4b 39 cf  |..+|%F(..W../K9.|
+000000e0  61 be 60 9a fd f1 6e e1  a2 a7 20 f2 fd 50 a2 d2  |a.`...n... ..P..|
+000000f0  17 db 16 4f 3f 8c 20 e4  4d 56 37 3b c2 42 17 cc  |...O?. .MV7;.B..|
+00000100  5d 99 06 fc 18 0d 1a 88  e8 f9 6f cf 7d 2e 57 73  |].........o.}.Ws|
+00000110  85 47 ed d0 2d b3 9a 05  cf 0c 7d e6 ed 29 95 f4  |.G..-.....}..)..|
+00000120  d5 e0 96 6a 1d 67 3e 5f  43 9f b5 f6 66 f5 84 63  |...j.g>_C...f..c|
+00000130  bd 42 a6 f8 ef 38 42 8a  d8 28 dc 55 e5 88 03 76  |.B...8B..(.U...v|
+00000140  96 ba 89 35 63 7e 6c da  39 d8 9a 27 04 ab d5 0e  |...5c~l.9..'....|
+00000150  48 89 cc 81 25 44 61 16  2c b2 69 17 03 03 00 59  |H...%Da.,.i....Y|
+00000160  81 8f 94 30 8d fc 47 13  7e 84 06 9b 4a 85 2c bb  |...0..G.~...J.,.|
+00000170  b3 a0 0d 4f 50 6a cb 0b  9b 40 ef cc 84 70 1f 69  |...OPj...@...p.i|
+00000180  b9 3e a6 c4 ba 66 eb a9  6f 78 83 7f d4 1f d8 c4  |.>...f..ox......|
+00000190  b0 f6 9b 03 29 7f b1 f8  60 40 0b 28 91 32 2c 03  |....)...`@.(.2,.|
+000001a0  aa 9e 7b fb 99 c2 11 51  1f a7 81 69 16 39 f4 52  |..{....Q...i.9.R|
+000001b0  ca d8 d0 f3 87 6f 58 ab  9a 17 03 03 00 35 de 03  |.....oX......5..|
+000001c0  88 61 50 5c 08 88 77 28  6a 1d 28 44 3d 49 8b 79  |.aP\..w(j.(D=I.y|
+000001d0  d1 a2 13 67 95 0f 7c 18  fe e2 e0 07 f1 ce b9 be  |...g..|.........|
+000001e0  79 aa 40 d6 cf 66 53 ac  15 ae 2a 14 a9 63 98 55  |y.@..fS...*..c.U|
+000001f0  96 16 6f 17 03 03 00 17  a8 ac 17 c5 eb d9 8e 77  |..o............w|
+00000200  9e 4b e0 20 c6 0c 34 b6  c3 ab c4 b6 8b b2 77 17  |.K. ..4.......w.|
+00000210  03 03 00 13 58 d4 7b 8f  ca 20 41 e3 3f d1 ae cf  |....X.{.. A.?...|
+00000220  3d e1 86 91 c0 a1 08                              |=......|
index 09de5cca834b7592538144d43e1ebe99f35bc208..8e361eaf4f2f2da6beeec8165e886c6d294ce106 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 7a 02 00 00  76 03 03 cc a2 2d 09 42  |....z...v....-.B|
-00000010  f0 11 87 04 64 83 e4 d8  80 a5 0f 88 69 ae f1 d2  |....d.......i...|
-00000020  12 05 d2 08 75 15 86 b7  d8 69 e7 20 00 00 00 00  |....u....i. ....|
+00000000  16 03 03 00 7a 02 00 00  76 03 03 30 0a c5 df b0  |....z...v..0....|
+00000010  90 3a 48 4b 20 f1 89 62  be 1f 1b 64 c2 7e 69 25  |.:HK ..b...d.~i%|
+00000020  9f b7 f9 2c 86 e7 40 e7  e8 10 fa 20 00 00 00 00  |...,..@.... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 01 00 00  |................|
-00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 c9  |..+.....3.$... .|
-00000060  b4 93 8b 5b b0 ae 93 4a  01 26 0c fb db 3f 53 0b  |...[...J.&...?S.|
-00000070  04 ca 65 63 3f d7 d9 f9  fc ca ea 4c f2 08 3c 14  |..ec?......L..<.|
-00000080  03 03 00 01 01 17 03 03  00 17 85 f6 ff f8 58 7f  |..............X.|
-00000090  2a d9 e0 12 82 d6 31 64  29 70 05 24 0f 17 1e 9f  |*.....1d)p.$....|
-000000a0  dc 17 03 03 00 42 16 7b  d5 fa a6 30 94 8e a0 a7  |.....B.{...0....|
-000000b0  24 59 b9 3d 85 b0 2f d9  25 c6 5a b5 7f 51 ca 54  |$Y.=../.%.Z..Q.T|
-000000c0  4a f7 f0 72 bb dd 5e 70  14 6d 46 3f b3 86 6f c1  |J..r..^p.mF?..o.|
-000000d0  a4 5f 6d ba 97 f3 38 c0  24 4a 9f de 7b b9 49 12  |._m...8.$J..{.I.|
-000000e0  71 02 f8 bc bc 65 5a ea  17 03 03 02 22 f9 92 7e  |q....eZ....."..~|
-000000f0  34 eb b3 a4 03 8e ec 48  30 a0 9b ac a6 7b b3 a5  |4......H0....{..|
-00000100  d0 4a 89 2c 92 6a c6 04  de b2 86 72 0a f1 97 61  |.J.,.j.....r...a|
-00000110  da 70 ef 25 5a a3 f1 b3  3d 78 f1 ec 2b 8f 34 2b  |.p.%Z...=x..+.4+|
-00000120  c9 94 e7 d2 9e 2f 09 5d  7a e3 2e fc 6e e1 ef 80  |...../.]z...n...|
-00000130  e6 0c e9 3e 07 bb b7 0e  74 0c e8 19 fe 7f d8 d0  |...>....t.......|
-00000140  fa 70 03 c1 31 c2 76 51  c3 d0 ed a6 a1 0d 20 74  |.p..1.vQ...... t|
-00000150  86 15 99 51 71 f8 3d 8e  1c 8c a8 19 0a 9c ac 4a  |...Qq.=........J|
-00000160  ab 0e e6 cc 52 a0 a8 ca  d9 71 54 aa 2c 8b 6f 5b  |....R....qT.,.o[|
-00000170  f9 46 07 0d 86 40 d9 54  33 8e de 54 a5 c2 6e 36  |.F...@.T3..T..n6|
-00000180  14 0e e3 52 78 05 56 90  98 2c e1 ec 26 f6 bd 6a  |...Rx.V..,..&..j|
-00000190  e5 0b 31 e1 a4 2a 2a 96  1b d6 57 87 ac a8 07 71  |..1..**...W....q|
-000001a0  83 d9 70 1e 5e 63 9b d1  01 83 e7 c9 c8 1c 5a 34  |..p.^c........Z4|
-000001b0  05 c0 7b da 1c ca 5f 99  49 9a 04 da c9 1c 9b ed  |..{..._.I.......|
-000001c0  b4 af 9d ff 36 71 1b 3a  00 e8 6a c4 6e 47 d9 4a  |....6q.:..j.nG.J|
-000001d0  64 f5 c1 07 ab 19 c8 65  a3 33 26 99 be 53 c3 86  |d......e.3&..S..|
-000001e0  97 10 ef c1 54 8e 69 6c  b1 29 aa 7d c1 63 67 ba  |....T.il.).}.cg.|
-000001f0  d7 72 7c 74 83 58 bd 5a  a8 a8 5f 49 38 ee 1e 34  |.r|t.X.Z.._I8..4|
-00000200  c8 98 19 73 97 2d 76 e6  d7 0d 15 75 a0 98 1f 15  |...s.-v....u....|
-00000210  c9 b8 3d 3f cb 92 a1 39  4b 91 ca e0 d2 0e 38 c2  |..=?...9K.....8.|
-00000220  20 eb f2 b5 04 64 fa d8  e2 d7 2f ba 88 7e f4 37  | ....d..../..~.7|
-00000230  c1 68 c4 2f c9 54 a1 21  5d 4b e7 67 3b 2e 6a 06  |.h./.T.!]K.g;.j.|
-00000240  55 ba d4 8d fe 0e b1 b7  2d cf c2 82 ed 27 3d 5b  |U.......-....'=[|
-00000250  9b 3b 28 a9 d4 c4 3c a0  45 b1 77 37 8b f8 7e f0  |.;(...<.E.w7..~.|
-00000260  51 90 fe 7a 74 14 ac f7  59 8b ed be 79 b0 4b 89  |Q..zt...Y...y.K.|
-00000270  d9 0c 39 fe 45 9d 15 0c  a6 96 26 0d b2 29 b0 a4  |..9.E.....&..)..|
-00000280  29 62 df 4b c0 a0 05 f1  e8 8b 16 af ea 42 8b 58  |)b.K.........B.X|
-00000290  5a ae f6 28 d8 40 09 d1  1e 21 b3 c7 a8 e2 30 4a  |Z..(.@...!....0J|
-000002a0  27 e6 c4 ba ff 62 91 7b  ab 64 18 65 02 e2 10 68  |'....b.{.d.e...h|
-000002b0  87 35 c2 09 5b 23 a4 eb  96 19 a7 1e 75 85 6e 17  |.5..[#......u.n.|
-000002c0  0e bc 11 1a f5 49 05 92  f7 0e e4 c7 85 da 4e 26  |.....I........N&|
-000002d0  5b de f2 dc 36 fb dc dd  c6 42 23 0c a7 de 8d ad  |[...6....B#.....|
-000002e0  f5 2a 8b ff b4 5d c6 ca  ec e3 83 a4 1e 23 3a 2d  |.*...].......#:-|
-000002f0  1a 52 51 11 f5 3b 93 47  89 c8 fc 21 b0 a3 4f b3  |.RQ..;.G...!..O.|
-00000300  6e d2 83 ca 20 75 fc 43  43 e5 1d 5d 57 c9 7c 17  |n... u.CC..]W.|.|
-00000310  03 03 00 a4 dc 79 73 47  d4 f5 72 c9 12 46 ed 3c  |.....ysG..r..F.<|
-00000320  d0 61 20 81 a9 ad 64 f3  f1 77 7f f1 74 09 67 80  |.a ...d..w..t.g.|
-00000330  c1 08 07 9c 50 b8 7d f5  70 f5 c6 a1 5f ba 37 78  |....P.}.p..._.7x|
-00000340  58 37 e3 f4 3f 03 1d 69  6f af 2f 2b 8b 10 95 5a  |X7..?..io./+...Z|
-00000350  be a1 5c b8 42 61 65 5a  27 35 f6 b4 57 3d 3a 6b  |..\.BaeZ'5..W=:k|
-00000360  f4 e9 90 88 7b e3 7c bf  be 51 19 0e 51 53 cd 10  |....{.|..Q..QS..|
-00000370  2c 70 76 9e d1 32 28 8f  c4 6c 01 2c 46 8f 4d 14  |,pv..2(..l.,F.M.|
-00000380  21 a2 63 39 44 b3 03 0d  a3 9d a0 c8 f4 cf 5d 7e  |!.c9D.........]~|
-00000390  d2 17 05 ee 9c 5c 1a 2e  43 dc 3f 6d d9 f2 54 5d  |.....\..C.?m..T]|
-000003a0  64 ff d2 1c 21 73 66 b1  2c 21 9d 3f bf fe f8 a5  |d...!sf.,!.?....|
-000003b0  79 54 fe 8a d5 3d 5f f6  17 03 03 00 35 0f 01 eb  |yT...=_.....5...|
-000003c0  f8 46 f8 07 7a 06 69 45  e2 47 4d b0 eb 9c 82 8b  |.F..z.iE.GM.....|
-000003d0  5d d0 59 66 d1 b5 a2 7b  b2 f0 72 6f 34 8b 2c 05  |].Yf...{..ro4.,.|
-000003e0  84 53 1c 7b 24 d8 f0 cd  a3 46 d1 ed 08 22 bb e6  |.S.{$....F..."..|
-000003f0  38 98                                             |8.|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 03 00 00  |................|
+00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 94  |..+.....3.$... .|
+00000060  e8 ab 87 65 c8 dd 6f ee  b4 d6 0b bb fd 18 9a 2d  |...e..o........-|
+00000070  e4 bc c6 20 98 09 71 65  7d 54 35 73 22 99 1b 14  |... ..qe}T5s"...|
+00000080  03 03 00 01 01 17 03 03  00 17 37 b7 eb eb a2 9f  |..........7.....|
+00000090  7f 00 8c 9d a9 50 7c 0c  15 31 63 71 45 7a 3d ee  |.....P|..1cqEz=.|
+000000a0  5e 17 03 03 00 42 9f 23  07 cf d0 bc e8 bb 95 01  |^....B.#........|
+000000b0  37 94 18 2e 05 02 8a eb  0a 37 10 79 51 a9 d4 43  |7........7.yQ..C|
+000000c0  18 18 e6 00 9d 68 ff 74  f3 9c 19 bf 5e 51 0c 47  |.....h.t....^Q.G|
+000000d0  61 35 8c b2 58 5f 32 bc  88 c4 fb 5a 22 61 14 98  |a5..X_2....Z"a..|
+000000e0  28 26 8c 75 9d 1d 19 05  17 03 03 02 22 d2 2c 1a  |(&.u........".,.|
+000000f0  e5 58 0d d7 0b c4 66 b2  06 90 bc 92 0f 05 34 5d  |.X....f.......4]|
+00000100  2b 20 26 02 cc ac 90 40  a0 f1 5f 0e b9 99 7c 0f  |+ &....@.._...|.|
+00000110  c9 3e 60 0b 39 ec 6c 94  3a d4 f7 b7 49 5e c7 6e  |.>`.9.l.:...I^.n|
+00000120  df 3b cc 33 cb 32 41 53  dd 09 8e 91 97 d2 e0 06  |.;.3.2AS........|
+00000130  5e 0c 4c 49 46 18 83 fc  ac b4 f8 76 2d 18 ee 0b  |^.LIF......v-...|
+00000140  b6 4a b9 aa eb ee db 7a  aa 6d 04 84 ed 8e 15 bc  |.J.....z.m......|
+00000150  bf 6f a1 29 bc 0b 9f ba  05 a5 42 82 fd 1c 30 c9  |.o.)......B...0.|
+00000160  20 df 8e ba 28 ab 0b a2  42 09 5e e8 c1 61 d2 25  | ...(...B.^..a.%|
+00000170  fc 05 53 62 91 45 29 54  60 31 b8 4f 01 9c 7b 6a  |..Sb.E)T`1.O..{j|
+00000180  04 27 df bc e0 a0 3d b3  80 73 22 ca 9b 41 be b6  |.'....=..s"..A..|
+00000190  09 22 67 1e 54 52 ce 14  b5 56 7a ca 3f a8 3e 01  |."g.TR...Vz.?.>.|
+000001a0  d2 e4 36 18 87 f6 08 19  55 d2 ba 3c a3 c5 11 84  |..6.....U..<....|
+000001b0  62 2a 09 c6 67 de cd ab  66 12 dd 0a 23 77 18 b7  |b*..g...f...#w..|
+000001c0  73 c1 29 61 52 32 95 eb  a0 db 72 ae b7 ff 2a b2  |s.)aR2....r...*.|
+000001d0  08 f6 d7 69 32 c2 f8 8b  e1 40 a9 d0 fe 11 64 a2  |...i2....@....d.|
+000001e0  a2 dd a7 e6 a6 dd 5d 79  49 df bb c0 83 da 56 7a  |......]yI.....Vz|
+000001f0  a5 22 8e 60 df 89 48 e0  e2 e9 5f d5 fe dd ba 34  |.".`..H..._....4|
+00000200  ad 91 52 d8 2f 7e a4 73  50 e8 b7 83 e2 d9 5e 05  |..R./~.sP.....^.|
+00000210  96 08 e4 d4 bb 01 39 99  aa 1d fd 74 1b dc ca c2  |......9....t....|
+00000220  8f bb b8 bf c4 eb 00 6f  cc 70 eb 7c c7 29 e4 64  |.......o.p.|.).d|
+00000230  8c 76 a7 b5 79 ea b6 96  fe eb 8f e7 81 9b d1 d0  |.v..y...........|
+00000240  41 16 db ef 9e 55 2a 77  6c 34 54 22 48 6a ca 78  |A....U*wl4T"Hj.x|
+00000250  31 6e d2 00 7f 54 93 65  ec 28 42 66 7b 74 4d 58  |1n...T.e.(Bf{tMX|
+00000260  fe 25 74 bd 9f a4 ff f2  45 06 c6 63 1f 11 68 a4  |.%t.....E..c..h.|
+00000270  fb fe 62 2b f8 19 e3 32  2c cc 5d 71 37 21 05 82  |..b+...2,.]q7!..|
+00000280  c9 c7 30 c7 74 64 d9 f9  6b c2 ae d8 15 2b 2a 79  |..0.td..k....+*y|
+00000290  a0 2d a3 18 1f d7 20 99  96 86 52 32 cf 84 bd 73  |.-.... ...R2...s|
+000002a0  63 85 82 a3 64 fb e3 ea  1b 31 f5 df 1c 74 06 48  |c...d....1...t.H|
+000002b0  69 8a e3 f0 72 8c 59 8b  de 0b 06 02 47 54 4c 2d  |i...r.Y.....GTL-|
+000002c0  46 ac d4 f5 4d 5c fe 0d  bf af d0 37 58 82 3e d2  |F...M\.....7X.>.|
+000002d0  4e c1 7e 0f b0 21 f7 8e  2c 88 db 83 43 ed ad 5b  |N.~..!..,...C..[|
+000002e0  0f a2 ce 47 e4 3f dd 1b  71 fe f0 a7 a1 8d 8c dc  |...G.?..q.......|
+000002f0  75 e0 7a 89 f7 14 5b 37  9d 35 f6 23 91 a8 d2 1a  |u.z...[7.5.#....|
+00000300  96 07 1b 5b 9c 35 27 b8  b9 0c 92 1e cf 1b 3c 17  |...[.5'.......<.|
+00000310  03 03 00 a4 f0 59 e1 1d  62 39 69 c5 53 ae 66 85  |.....Y..b9i.S.f.|
+00000320  df ea 32 73 ca 94 e2 b5  14 d4 30 07 dd fd 2f 9a  |..2s......0.../.|
+00000330  16 fc e9 71 4a 20 b8 d2  7e 17 26 ff a9 55 56 24  |...qJ ..~.&..UV$|
+00000340  31 85 bc ea 19 1c 37 b7  fe 8b 47 5f a3 99 0f 5d  |1.....7...G_...]|
+00000350  17 92 4b 2a 4c b5 6c db  8f bb 46 ee 89 31 53 79  |..K*L.l...F..1Sy|
+00000360  aa 34 9d 9b e8 9b e7 82  55 a3 92 f6 53 53 d3 72  |.4......U...SS.r|
+00000370  17 23 33 01 e8 75 7e 8d  63 91 a0 67 8f a5 f0 15  |.#3..u~.c..g....|
+00000380  8c f5 81 e2 c4 08 ff 14  1d 96 cf ef 4e 09 18 a1  |............N...|
+00000390  2c 38 0a f7 33 f0 1d ef  9d 12 4d 8c 25 f0 80 a2  |,8..3.....M.%...|
+000003a0  aa a7 cf e4 7c e6 44 58  6d 30 70 48 55 3b b5 79  |....|.DXm0pHU;.y|
+000003b0  55 aa 03 ed 14 ea e5 ee  17 03 03 00 35 72 1a ca  |U...........5r..|
+000003c0  5c 3d 3b 75 29 cc a9 09  85 67 89 37 18 91 c0 af  |\=;u)....g.7....|
+000003d0  28 d2 0c c9 8b 05 94 04  3a 68 38 f0 c3 db 95 89  |(.......:h8.....|
+000003e0  c8 28 fc 07 4b 49 7d b6  25 36 05 53 96 e0 d9 35  |.(..KI}.%6.S...5|
+000003f0  e5 7c                                             |.||
 >>> Flow 3 (client to server)
-00000000  14 03 03 00 01 01 17 03  03 02 11 ce 65 5f 9d 1a  |............e_..|
-00000010  c6 5f 48 ea da 02 77 1d  79 b2 82 1a da c4 75 aa  |._H...w.y.....u.|
-00000020  11 af ae 1f e4 7e d7 6f  ed 75 48 56 de c8 36 05  |.....~.o.uHV..6.|
-00000030  6a 97 5e 49 49 55 25 6f  ef 3e ed 40 3f 91 9a ae  |j.^IIU%o.>.@?...|
-00000040  f4 a1 d3 02 d3 15 60 23  1b 7a 80 ef ef 60 bb 62  |......`#.z...`.b|
-00000050  a3 8d 6b 24 1a 11 7d 8e  00 76 54 69 f1 b5 df 77  |..k$..}..vTi...w|
-00000060  c0 3a a3 8d 9d a3 56 e7  4d 2d 68 fe 38 49 6d 42  |.:....V.M-h.8ImB|
-00000070  3d 2c 69 fd 8c 53 44 af  13 8b 1d cb dc 04 16 6e  |=,i..SD........n|
-00000080  5a ab 0a 00 19 cf a0 8a  ee bd 71 24 68 ee 18 2a  |Z.........q$h..*|
-00000090  ec 04 fe 0f 12 15 8e 09  e0 87 de 4e c4 2a a1 a5  |...........N.*..|
-000000a0  6d be 79 6e 25 15 11 64  8c 35 71 97 fa a4 43 e2  |m.yn%..d.5q...C.|
-000000b0  dd cd a1 da b3 75 5d d5  36 fb b4 6b 12 30 a7 f6  |.....u].6..k.0..|
-000000c0  d7 7c 72 e1 f8 6a 8b 3e  38 13 9c da ee 07 3d 6a  |.|r..j.>8.....=j|
-000000d0  f5 1b 26 73 ff 24 03 1f  ea dc f3 ed 6b c2 0d fe  |..&s.$......k...|
-000000e0  3e 03 c4 22 93 c9 9b fe  22 5c 1e fb 07 2b 1b 7f  |>.."...."\...+..|
-000000f0  34 ff c6 1b 24 32 4b b1  ee 4c 0b 08 b6 3b 1e aa  |4...$2K..L...;..|
-00000100  49 f3 04 b7 9a 42 e5 42  5a df a2 92 d3 2f 62 54  |I....B.BZ..../bT|
-00000110  e1 21 08 ee ce 64 80 48  d3 6a 15 67 8c 5e d1 ac  |.!...d.H.j.g.^..|
-00000120  a2 64 f9 10 67 2c 27 7e  10 11 d7 09 13 2f 61 a7  |.d..g,'~...../a.|
-00000130  d7 9d 2a 18 0f a8 93 c6  fc 75 5c 31 68 42 22 e6  |..*......u\1hB".|
-00000140  5c e8 4d 7d 82 73 ba 97  5c d7 6a a2 14 37 85 93  |\.M}.s..\.j..7..|
-00000150  48 a7 50 9c fc 66 7b 82  a8 b6 99 0f 8c 9e 40 b5  |H.P..f{.......@.|
-00000160  e4 4f 98 01 db 56 03 44  f9 9f 52 a3 33 ac 77 2a  |.O...V.D..R.3.w*|
-00000170  b6 0a de d5 68 a5 df 67  41 8d 4c 53 9d c4 8d b7  |....h..gA.LS....|
-00000180  2e 3d 1f 93 1c 23 e3 81  76 5a 99 7c 90 60 d8 4d  |.=...#..vZ.|.`.M|
-00000190  e4 a5 00 7d f9 2c c5 19  bc 3c a3 73 c3 83 ff 31  |...}.,...<.s...1|
-000001a0  6a 67 88 32 d3 90 7f ab  20 19 1f 55 72 e4 08 bc  |jg.2.... ..Ur...|
-000001b0  c4 d6 24 e6 00 2d 85 be  d4 9b 2c e5 7b ee 26 6b  |..$..-....,.{.&k|
-000001c0  49 ed 94 3d d6 ee fd 9d  da 39 be 02 23 aa b9 78  |I..=.....9..#..x|
-000001d0  f2 41 97 0a d9 66 15 1e  e1 a2 49 f3 09 f0 25 91  |.A...f....I...%.|
-000001e0  8a ea f5 38 87 ea 66 ae  dc d2 04 d1 02 92 ab 6c  |...8..f........l|
-000001f0  a4 1a cc 1b ba 48 d5 8e  27 c4 c5 34 08 8f c2 c8  |.....H..'..4....|
-00000200  e1 e6 a8 98 48 9c 43 6c  f1 34 ba c0 ff 8e 22 14  |....H.Cl.4....".|
-00000210  f7 f9 93 38 96 1e 73 57  28 5b 25 3e 17 03 03 00  |...8..sW([%>....|
-00000220  99 c7 8d 1d 62 23 f3 c1  31 3d 45 bc d5 59 ff 47  |....b#..1=E..Y.G|
-00000230  8e 34 3d 1d 06 cc e0 05  ea 38 87 f0 fd c3 84 53  |.4=......8.....S|
-00000240  47 6b fb 7b 9b c2 a4 f2  1f e0 61 ab 17 32 d0 57  |Gk.{......a..2.W|
-00000250  34 dd fb 42 9b ad 4c d7  20 ff b1 58 34 e0 0c b1  |4..B..L. ..X4...|
-00000260  44 0c cf d3 05 be 3b 8e  a2 d5 39 44 c8 22 64 ad  |D.....;...9D."d.|
-00000270  61 80 df 5d fd 40 0e c0  c2 41 4f a7 e5 4f b3 7f  |a..].@...AO..O..|
-00000280  0b db d6 ac fe ba c0 8b  24 8e e8 b2 d6 93 3d 12  |........$.....=.|
-00000290  75 41 85 1d b5 4a e2 e0  f8 a1 23 8f 13 24 c6 b6  |uA...J....#..$..|
-000002a0  e5 db 06 3f d8 d5 2f b5  e5 24 59 76 53 dd aa 0a  |...?../..$YvS...|
-000002b0  26 ba 72 23 63 ac 4d 5c  92 13 17 03 03 00 35 47  |&.r#c.M\......5G|
-000002c0  59 18 68 11 0a 9a 0b 66  d3 c0 26 72 da 51 0e 00  |Y.h....f..&r.Q..|
-000002d0  b0 78 8b 6a ef df 75 94  94 b0 aa 9b 77 e3 9c d8  |.x.j..u.....w...|
-000002e0  23 9d 74 ce 85 55 c0 30  4c 96 5b 59 7a f6 03 2e  |#.t..U.0L.[Yz...|
-000002f0  d8 9c 0e 11 17 03 03 00  17 74 ed 13 0b 6a 15 18  |.........t...j..|
-00000300  5e d4 5e 8a c6 e6 5c 0b  3c d0 1b 3d 68 86 2a 07  |^.^...\.<..=h.*.|
-00000310  17 03 03 00 13 6f e2 fe  a0 b8 95 d4 aa fd 11 2b  |.....o.........+|
-00000320  e8 6d 42 28 d1 ca 1c 5e                           |.mB(...^|
+00000000  14 03 03 00 01 01 17 03  03 02 11 6a 55 c4 ff 7a  |...........jU..z|
+00000010  5b c4 b7 cb 8d ad ae 53  53 3d 41 3a fc 16 44 fd  |[......SS=A:..D.|
+00000020  c8 5f 39 c3 5e 6b ee 7d  ea 88 9c a9 78 f9 dc 51  |._9.^k.}....x..Q|
+00000030  b2 90 68 7d ae 2c b7 90  6e 79 cf f4 97 50 95 87  |..h}.,..ny...P..|
+00000040  f1 f6 2c 14 bc 2b a3 68  0d e6 c8 66 2f 3b 89 72  |..,..+.h...f/;.r|
+00000050  67 4d d8 e9 8d 6a 89 2a  f9 e4 c1 b5 c0 92 16 25  |gM...j.*.......%|
+00000060  61 a6 98 ec b6 6b 52 8b  a5 80 5a 9e 6d 03 ad 42  |a....kR...Z.m..B|
+00000070  a9 46 2f d8 e5 67 c9 8d  89 f7 34 93 82 7c a3 bb  |.F/..g....4..|..|
+00000080  48 62 06 90 5c 5a aa fd  7c 71 88 24 22 f9 6a 2c  |Hb..\Z..|q.$".j,|
+00000090  d1 d9 7e 0a 4c 39 11 e8  c0 17 1d 83 64 f2 2b c6  |..~.L9......d.+.|
+000000a0  c0 81 8c 6a 39 a9 09 aa  1e 58 eb 30 88 59 4d f2  |...j9....X.0.YM.|
+000000b0  d2 64 9f 4c 90 29 c0 66  94 e3 df 12 9c 75 33 24  |.d.L.).f.....u3$|
+000000c0  fb 14 bc 70 e1 b5 de 54  28 b0 3f 01 2c 2e 5f 35  |...p...T(.?.,._5|
+000000d0  e3 01 59 2a 3f ce ca 11  bb 29 97 03 f6 f4 30 b9  |..Y*?....)....0.|
+000000e0  66 db 3c f7 06 41 7b e8  f8 af 3e 03 65 2f 5f 88  |f.<..A{...>.e/_.|
+000000f0  fd 30 45 7a c9 b4 9f bf  03 eb c9 dd 06 ac 82 06  |.0Ez............|
+00000100  e8 81 8e ea 29 45 78 5c  0f 8e 21 8a fb 0b 95 c1  |....)Ex\..!.....|
+00000110  63 e9 18 c1 9a a4 c6 7d  56 4b 9a de 96 dd 37 54  |c......}VK....7T|
+00000120  92 ef 71 42 a8 66 e7 df  e7 ea ec 4e 3c b3 8e 7d  |..qB.f.....N<..}|
+00000130  ed 92 da 86 e5 fa 51 f8  e4 b0 09 f3 06 4d 38 f1  |......Q......M8.|
+00000140  d5 5f d2 72 1e 5f c3 1e  1d fd 96 70 e7 9c ae ea  |._.r._.....p....|
+00000150  62 ce e4 a9 31 34 47 bc  f0 9f 1c c7 b6 66 f0 70  |b...14G......f.p|
+00000160  7a e1 c5 a9 76 64 d4 25  0f 56 cd 36 17 67 bd 4d  |z...vd.%.V.6.g.M|
+00000170  c7 78 d8 23 46 4b ac 46  34 1a d2 2d c5 e6 67 55  |.x.#FK.F4..-..gU|
+00000180  11 ec 8c f0 67 84 bf 89  ce 3c 71 4e 3a ab ff 22  |....g....<qN:.."|
+00000190  59 23 00 54 4b b6 9e c4  01 a1 9f e1 46 a6 a6 f3  |Y#.TK.......F...|
+000001a0  24 58 0c b4 6e 85 4c c1  8a d6 f8 02 c9 54 fb 85  |$X..n.L......T..|
+000001b0  c7 63 9b 47 28 10 a0 2d  b6 c2 83 16 71 ae a7 c2  |.c.G(..-....q...|
+000001c0  e0 dc 8b 6d 57 e0 4b a2  a8 5d 4d 8b ed 72 31 d6  |...mW.K..]M..r1.|
+000001d0  54 33 78 df bb 4a f9 58  9f 8c 2b 11 36 29 a0 f0  |T3x..J.X..+.6)..|
+000001e0  8a 95 20 d8 f1 8c 08 e1  54 0a 81 79 33 20 23 de  |.. .....T..y3 #.|
+000001f0  34 c8 2b 45 3a 59 c5 78  39 65 ea 70 e2 fe 59 4c  |4.+E:Y.x9e.p..YL|
+00000200  ed 7f 07 07 25 a7 ff fa  c9 c3 1f 33 55 c4 16 bb  |....%......3U...|
+00000210  c9 b9 e0 2e ff 94 7c de  84 30 60 d6 17 03 03 00  |......|..0`.....|
+00000220  99 53 44 d2 12 38 c4 a7  7e f5 f5 67 b3 79 cf 8a  |.SD..8..~..g.y..|
+00000230  34 0f 5d 49 0f bb 5f 30  c8 36 13 61 8d b5 b1 b0  |4.]I.._0.6.a....|
+00000240  dc 73 2f 1a 51 2f d4 8e  25 71 e1 46 af 11 96 19  |.s/.Q/..%q.F....|
+00000250  f7 fe 09 d9 6e 70 d5 fc  b9 5b 1c ae ed 06 37 af  |....np...[....7.|
+00000260  a1 bf 35 c6 6b 30 33 a2  c4 f6 c8 d4 73 34 73 8e  |..5.k03.....s4s.|
+00000270  69 08 be 91 2c 8d 01 52  30 14 b3 d3 a0 7d 8a 9d  |i...,..R0....}..|
+00000280  e9 af b2 77 64 eb 16 c1  8e 19 72 ad 4a fd d4 c9  |...wd.....r.J...|
+00000290  08 d0 54 6c f1 06 8c 70  2f e6 ef 23 23 67 96 db  |..Tl...p/..##g..|
+000002a0  5f aa 81 6c 41 17 6b f4  30 ce 00 d6 a2 d8 28 f8  |_..lA.k.0.....(.|
+000002b0  be 9f 04 94 fa e3 fa 76  d0 30 17 03 03 00 35 9b  |.......v.0....5.|
+000002c0  43 c4 8f dc b7 a1 44 4e  00 66 0a 95 a6 d7 46 79  |C.....DN.f....Fy|
+000002d0  30 2d 57 51 4e 21 a7 ed  43 e7 22 2d eb 07 9b 7d  |0-WQN!..C."-...}|
+000002e0  ea a4 ff 14 5d 97 1f d5  e8 f1 3d 8d e3 13 b6 79  |....].....=....y|
+000002f0  36 ce 83 e8 17 03 03 00  17 d5 98 a6 a3 b7 40 2b  |6.............@+|
+00000300  26 87 2f 4f 64 95 f1 2d  e0 7b e3 98 c2 81 dc 7b  |&./Od..-.{.....{|
+00000310  17 03 03 00 13 5b ab 65  e4 b1 d0 bd e9 c6 b2 3a  |.....[.e.......:|
+00000320  4b 66 ce eb 25 0c bc 7d                           |Kf..%..}|
index 9488dd6b66d692b932689f088f5cedac4e61831d..2367a397171bc084d0dafef4ce0bc8f5754430e9 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 7a 02 00 00  76 03 03 6d 36 ae 02 a9  |....z...v..m6...|
-00000010  74 ad e5 4d 55 b6 4a 70  c6 f5 cf d5 68 d9 2a 5f  |t..MU.Jp....h.*_|
-00000020  9b 4b 23 ce 38 9b f3 da  44 72 7d 20 00 00 00 00  |.K#.8...Dr} ....|
+00000000  16 03 03 00 7a 02 00 00  76 03 03 a9 f1 13 c3 3c  |....z...v......<|
+00000010  1c dd c9 3a a1 ad 92 92  f1 f4 16 39 be 14 64 9c  |...:.......9..d.|
+00000020  66 d8 28 cd b7 bb 40 43  ec f4 67 20 00 00 00 00  |f.(...@C..g ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 01 00 00  |................|
-00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 ba  |..+.....3.$... .|
-00000060  2a 76 cb fb 6c 6b bb 30  fb ef 87 6f e5 06 5c 6f  |*v..lk.0...o..\o|
-00000070  78 a7 44 41 93 c0 33 89  be 32 8c 0f fa 5c 43 14  |x.DA..3..2...\C.|
-00000080  03 03 00 01 01 17 03 03  00 17 ac 3e 8a 31 22 16  |...........>.1".|
-00000090  d3 69 bf 1d b5 2e 18 23  b3 21 00 17 23 a4 3f 9a  |.i.....#.!..#.?.|
-000000a0  0b 17 03 03 00 20 aa f0  51 64 b5 44 f0 28 ab 56  |..... ..Qd.D.(.V|
-000000b0  da 34 2d 62 77 4d 88 07  b6 82 ad 64 df e6 59 c9  |.4-bwM.....d..Y.|
-000000c0  91 e5 f8 f2 67 88 17 03  03 02 7a cf 2d 71 db 3f  |....g.....z.-q.?|
-000000d0  05 45 b8 68 18 1c b9 66  b6 00 f8 dc 9d ae e5 d2  |.E.h...f........|
-000000e0  a3 a8 02 5f ac e4 95 a6  fc 96 78 7b fd 0a 21 62  |..._......x{..!b|
-000000f0  ff 7c 15 2c fb f1 21 15  1e 8d 9e f9 71 62 43 e4  |.|.,..!.....qbC.|
-00000100  c9 69 e4 fe 87 f0 9d 9e  aa a4 5c d8 4e ae 3c 38  |.i........\.N.<8|
-00000110  e5 76 21 7b 03 a8 70 6f  e8 96 39 34 e7 3c b9 51  |.v!{..po..94.<.Q|
-00000120  b4 ef ce 7d 0b 1e 57 7d  62 de 47 6a 0a b0 97 6d  |...}..W}b.Gj...m|
-00000130  49 fe ae 6f c9 d6 e4 4a  54 60 3d 55 53 06 aa 28  |I..o...JT`=US..(|
-00000140  7a 3e 7b e0 d1 8a 60 45  87 81 bf fc 98 13 1e de  |z>{...`E........|
-00000150  7a 90 73 81 13 91 3a c4  da 71 74 e0 1d d5 30 55  |z.s...:..qt...0U|
-00000160  46 6a 48 c2 0c 18 91 a3  79 8e c2 b9 5b 24 88 76  |FjH.....y...[$.v|
-00000170  5f e6 8f 24 91 95 5b 0d  38 39 5b a4 f6 0e 1a b8  |_..$..[.89[.....|
-00000180  e8 2b 0d ac a8 56 10 23  54 a5 78 c9 2a cb ed 24  |.+...V.#T.x.*..$|
-00000190  58 16 1a 2f 1c b7 72 fc  da ab 56 f6 27 d1 98 39  |X../..r...V.'..9|
-000001a0  1f f9 dd e0 1f 1f 23 1a  ff 6b af e1 17 9d ec 35  |......#..k.....5|
-000001b0  de 0b 4d a4 46 5a fd 07  56 ce 72 19 76 dc 0c 06  |..M.FZ..V.r.v...|
-000001c0  99 38 ce 58 3b 9f 13 9a  d5 b7 d6 08 a6 05 4d e1  |.8.X;.........M.|
-000001d0  75 da 59 4d ab d9 28 e8  af c4 50 f0 b1 49 f8 fd  |u.YM..(...P..I..|
-000001e0  c9 11 b8 01 70 bb 49 e2  0f 26 1b cb ee c2 7b bd  |....p.I..&....{.|
-000001f0  2f 72 78 be a1 67 1d 0c  d0 bb 4e e7 40 b3 bd 8c  |/rx..g....N.@...|
-00000200  e2 f4 4f b2 c5 4c 82 49  51 00 44 17 c6 82 72 f5  |..O..L.IQ.D...r.|
-00000210  cd 55 c1 43 28 52 85 2b  5d 91 33 9c 15 34 6e ae  |.U.C(R.+].3..4n.|
-00000220  77 4e 08 0c 9c d2 ae 7f  e8 83 af 60 96 10 ae dc  |wN.........`....|
-00000230  58 6a 3b ae 15 e5 9c a8  25 f3 69 71 f7 94 9c 75  |Xj;.....%.iq...u|
-00000240  e0 b5 05 16 ae ce f4 23  20 30 aa 74 a3 63 68 76  |.......# 0.t.chv|
-00000250  f6 ec 64 e1 3d f6 0e b6  c4 7d a8 08 44 a9 96 1d  |..d.=....}..D...|
-00000260  7d c8 22 a8 df 04 2c ad  65 f1 4c 99 7d a1 cb bd  |}."...,.e.L.}...|
-00000270  b7 d4 d7 b5 ee 88 bd 15  2e 75 76 e2 72 bb 7d e6  |.........uv.r.}.|
-00000280  5b eb fc f7 96 96 f0 3c  aa b6 a8 58 92 e9 29 f6  |[......<...X..).|
-00000290  40 bf 8e 14 23 7c 45 da  e9 17 4b 32 16 11 ec 74  |@...#|E...K2...t|
-000002a0  78 d5 8c 5a 06 46 e4 dc  90 b9 44 8e d6 8a 4e 43  |x..Z.F....D...NC|
-000002b0  7f f9 60 9e a1 46 fa 16  88 ab 3c f1 1e d0 2e 00  |..`..F....<.....|
-000002c0  5d 01 e6 a7 b1 27 f7 40  26 17 f3 da fb cd 06 d1  |]....'.@&.......|
-000002d0  4e 27 75 9a 6f 0b 63 82  9c 40 07 4c 6e 0d d8 4b  |N'u.o.c..@.Ln..K|
-000002e0  f1 e6 d5 1c 41 55 72 b5  43 24 53 1e 0e a4 08 d7  |....AUr.C$S.....|
-000002f0  44 93 00 c9 8b 49 ba 7a  32 0c d8 e6 46 87 5d 62  |D....I.z2...F.]b|
-00000300  9d 4a 11 04 67 21 19 42  50 ad ad ab dd 62 0f f7  |.J..g!.BP....b..|
-00000310  0f 57 78 82 71 f6 09 9f  41 bc 8e 34 24 7c b5 d2  |.Wx.q...A..4$|..|
-00000320  5d 0c 18 fb d8 f6 62 dc  57 6a 78 2c 21 35 d8 eb  |].....b.Wjx,!5..|
-00000330  bb f8 7e 01 63 50 c1 98  88 a4 b5 63 1e c0 68 3c  |..~.cP.....c..h<|
-00000340  41 3c b8 6e 48 17 03 03  00 99 b6 09 37 a6 c2 d9  |A<.nH.......7...|
-00000350  5f 39 69 e1 0b ca 40 d8  31 5b 4b 4f c1 33 bf 1f  |_9i...@.1[KO.3..|
-00000360  db c2 8c 9c d2 14 26 96  4e aa b2 63 30 40 fa 49  |......&.N..c0@.I|
-00000370  fb 2d 66 59 70 cb c7 f8  fe 59 19 8b eb d5 5c 6c  |.-fYp....Y....\l|
-00000380  5c a0 c9 ba e6 4d d9 c3  e0 fe 00 c4 fb ab 8a f1  |\....M..........|
-00000390  2b ab 53 86 a7 86 57 01  b8 ae c4 a6 12 6b 7d f8  |+.S...W......k}.|
-000003a0  ea 2d df 37 04 01 eb 14  f4 9a d0 e7 67 46 ec 9f  |.-.7........gF..|
-000003b0  35 f8 d4 2e c6 95 91 10  0e dc 01 60 9a d6 f8 d8  |5..........`....|
-000003c0  9e c1 fd f8 2e e2 51 8a  e9 2f c3 4a 4f 01 31 52  |......Q../.JO.1R|
-000003d0  af cb 4b 52 96 4c 90 57  83 1f 11 97 d6 d6 16 74  |..KR.L.W.......t|
-000003e0  77 f8 c4 17 03 03 00 35  b0 61 57 8f 52 7e 93 b1  |w......5.aW.R~..|
-000003f0  f0 90 a1 23 09 6e 11 ff  a5 6c 38 f3 31 11 be 03  |...#.n...l8.1...|
-00000400  ad 59 65 57 1b 60 2b fc  41 98 e0 79 6d 14 26 c8  |.YeW.`+.A..ym.&.|
-00000410  fb d6 5f 00 e0 cc 70 46  a3 81 e4 3c ff           |.._...pF...<.|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 03 00 00  |................|
+00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 ff  |..+.....3.$... .|
+00000060  53 ac b3 b0 48 47 d0 1e  b1 70 eb dd 02 e5 e8 07  |S...HG...p......|
+00000070  ce c7 e0 af d7 e0 46 c7  ff f5 97 30 e5 80 5b 14  |......F....0..[.|
+00000080  03 03 00 01 01 17 03 03  00 17 0b 12 ef 6d ea 5e  |.............m.^|
+00000090  71 41 83 d6 35 9f 39 2c  f0 ab 01 e9 03 54 c6 9e  |qA..5.9,.....T..|
+000000a0  37 17 03 03 00 20 15 7a  35 f4 a6 6e 65 89 10 ae  |7.... .z5..ne...|
+000000b0  18 31 c0 0c 15 1c b8 c5  5d f3 54 0c 98 32 a4 5e  |.1......].T..2.^|
+000000c0  91 f7 03 8a 80 b9 17 03  03 02 7a fa 93 7f c6 d1  |..........z.....|
+000000d0  2f 7e 2d d6 1b b7 ff fd  96 6e a1 f7 0e 98 dc 77  |/~-......n.....w|
+000000e0  cc 6a 4e 91 3d c1 ad 4b  5c 28 ee ea a7 0a ce 8f  |.jN.=..K\(......|
+000000f0  51 dd 89 fd 5a 81 6d 21  d6 0d 35 70 84 73 8c fa  |Q...Z.m!..5p.s..|
+00000100  2e 7a e0 af ab 79 79 aa  67 2b 80 a8 b3 a8 fb 0d  |.z...yy.g+......|
+00000110  eb 87 66 d5 be 33 0b f0  80 b8 5e 21 84 be 25 fe  |..f..3....^!..%.|
+00000120  47 98 5a 26 5d c3 96 2e  c5 b8 da 9f a6 d4 ca bb  |G.Z&]...........|
+00000130  de 7f 2c 0a 28 a8 f3 41  bc a2 2e 70 f2 b3 6f a3  |..,.(..A...p..o.|
+00000140  10 0e 1f 11 af 11 50 2b  22 84 97 d7 80 f5 62 77  |......P+".....bw|
+00000150  a6 94 47 22 ef 24 c6 0e  dc 5c f5 40 08 f7 21 78  |..G".$...\.@..!x|
+00000160  ae 11 f3 d8 a5 d8 20 ac  90 73 d7 a2 e3 f0 08 57  |...... ..s.....W|
+00000170  fc 74 70 66 fd 3d 49 c7  99 37 98 5e b1 1c c4 38  |.tpf.=I..7.^...8|
+00000180  64 09 e6 70 b6 8b 00 72  2d 5b b4 70 39 d6 e9 d5  |d..p...r-[.p9...|
+00000190  dc cd 8e 01 eb 5f 34 61  d0 97 62 0b 4f 81 ed 30  |....._4a..b.O..0|
+000001a0  64 56 f2 6e 31 5e 24 e8  56 2b d6 31 54 c4 48 47  |dV.n1^$.V+.1T.HG|
+000001b0  16 00 a7 65 c1 fa ea 12  30 78 41 e7 30 2d 71 cf  |...e....0xA.0-q.|
+000001c0  b0 e9 be e4 a2 33 38 87  2d 37 14 2d 03 cf ae 87  |.....38.-7.-....|
+000001d0  9a 09 f2 ed f3 44 66 c3  8a 56 8e e4 c4 aa e9 f7  |.....Df..V......|
+000001e0  cd 75 52 1b d9 ed 66 04  13 dd dd cf 0f 44 cd 18  |.uR...f......D..|
+000001f0  68 c5 2c 4c f9 e3 d3 02  12 78 38 5c f6 96 d7 80  |h.,L.....x8\....|
+00000200  f0 83 03 fe 7a e0 35 7e  a3 ad 99 52 ec fc ee 74  |....z.5~...R...t|
+00000210  f5 09 0f ca 69 f0 fb d0  40 90 1b 46 9e 2d 62 c9  |....i...@..F.-b.|
+00000220  0f 59 b2 cc a0 4a 9b 84  14 3a 1b 51 fc e7 e8 a1  |.Y...J...:.Q....|
+00000230  26 fd 20 8c 88 6f 87 11  ae 97 76 f8 4b cc 67 1a  |&. ..o....v.K.g.|
+00000240  3e 58 65 77 77 82 06 c0  d4 41 4e 66 d2 5a 83 b1  |>Xeww....ANf.Z..|
+00000250  ee 19 5d 7b 99 34 d3 2f  6c bd 30 a3 8c 75 89 ec  |..]{.4./l.0..u..|
+00000260  cb 90 8b 89 05 b8 e4 6e  3b 60 5d 0e 19 8f d6 c7  |.......n;`].....|
+00000270  86 f0 a9 2b c7 12 4a 4c  d8 a5 e8 64 49 1d 49 99  |...+..JL...dI.I.|
+00000280  a7 80 01 f0 77 57 4a 78  3c ac 38 40 bb d2 10 24  |....wWJx<.8@...$|
+00000290  9d e2 29 b2 1e 4b 50 66  64 07 79 80 c7 81 9d e2  |..)..KPfd.y.....|
+000002a0  f5 a9 10 9a 8d 3b de 0e  21 85 13 ac 26 30 f9 e4  |.....;..!...&0..|
+000002b0  a6 f9 8f e0 3c c1 69 7e  11 4c d1 a8 4e 88 30 fc  |....<.i~.L..N.0.|
+000002c0  52 6e b0 4f b6 7e 15 9e  a5 8a 46 ca 1f ac 8e 2a  |Rn.O.~....F....*|
+000002d0  07 34 d7 c2 14 c6 c1 ed  a1 f9 1e 59 b4 b4 86 3e  |.4.........Y...>|
+000002e0  d3 d0 78 a6 07 62 d3 88  80 54 a8 2a e9 38 2e 58  |..x..b...T.*.8.X|
+000002f0  43 94 cc ed f0 46 f6 cc  4b 7a b8 f5 a2 d6 a8 36  |C....F..Kz.....6|
+00000300  e2 8e 11 fb e7 21 19 c5  fa c9 90 98 72 43 88 ac  |.....!......rC..|
+00000310  c0 56 84 9e cd b7 e5 26  d6 49 19 88 a5 12 ac 49  |.V.....&.I.....I|
+00000320  5d 77 37 2a ff 38 5a 7a  5b c8 74 5d 74 fc 22 7f  |]w7*.8Zz[.t]t.".|
+00000330  46 97 2b 34 32 fb 83 65  75 b6 8b 5c 8a b1 d4 a2  |F.+42..eu..\....|
+00000340  14 7f 46 0d 63 17 03 03  00 99 c7 79 bb 4f 88 a0  |..F.c......y.O..|
+00000350  78 be 04 ca 39 1f 1f a8  82 59 b5 dd 96 93 0d c4  |x...9....Y......|
+00000360  30 f4 22 4c e2 52 51 d4  33 b8 35 7b ed 01 19 25  |0."L.RQ.3.5{...%|
+00000370  b5 31 36 25 23 a2 51 d9  7a a9 00 72 05 34 81 62  |.16%#.Q.z..r.4.b|
+00000380  d0 df 8b 3a 65 98 4e 87  e2 29 9b 44 77 8c dd c9  |...:e.N..).Dw...|
+00000390  4c a5 de 14 97 e0 f1 2c  e8 5d 0e 8f d0 fd f6 77  |L......,.].....w|
+000003a0  c1 1f ac 79 4d 32 19 09  98 a8 f0 2f 3e d5 7e f7  |...yM2...../>.~.|
+000003b0  aa c1 f0 36 b1 8e c7 0b  ce 09 00 ac 28 64 c0 33  |...6........(d.3|
+000003c0  58 cc 48 3a 15 a4 77 24  50 67 f2 39 53 4d 63 23  |X.H:..w$Pg.9SMc#|
+000003d0  48 74 bd 0a c8 02 17 be  e4 64 af 6e 02 a9 22 92  |Ht.......d.n..".|
+000003e0  65 04 c6 17 03 03 00 35  e0 4e 15 4b 9d 53 57 c6  |e......5.N.K.SW.|
+000003f0  97 b4 9d 1a 03 39 26 b9  ca 5b 04 50 af db 52 99  |.....9&..[.P..R.|
+00000400  d9 13 40 6a 89 23 99 42  9a 91 1d d1 6c 07 a0 aa  |..@j.#.B....l...|
+00000410  05 6e 60 0b fd e7 de 32  c3 97 18 0d 9b           |.n`....2.....|
 >>> Flow 3 (client to server)
-00000000  14 03 03 00 01 01 17 03  03 02 7a 22 a3 3d 18 f8  |..........z".=..|
-00000010  a2 c7 8e 62 c3 07 99 b4  e6 bd 94 79 12 82 e9 e0  |...b.......y....|
-00000020  96 ff 5f c3 ec 34 02 2f  8d 95 2f 40 80 99 19 a3  |.._..4./../@....|
-00000030  bd 64 fd e4 0e b3 81 ad  4c 2e d9 72 d2 a3 bd 00  |.d......L..r....|
-00000040  81 42 78 5d f3 70 c3 78  0b fa cd b8 96 17 5e e7  |.Bx].p.x......^.|
-00000050  6e 03 b8 c6 ab 2b 2e 63  45 c7 b1 c9 98 71 c9 1d  |n....+.cE....q..|
-00000060  bb 7b 6e 6d c7 d5 90 b8  b2 4e 62 1a 8f cf 7d 99  |.{nm.....Nb...}.|
-00000070  52 3d 70 40 0f 0f 96 1c  ee a7 ff 29 2a 53 de d4  |R=p@.......)*S..|
-00000080  34 f9 d9 b2 33 2c 69 5e  2d f2 a7 62 dd ec 77 b1  |4...3,i^-..b..w.|
-00000090  6c 0f 61 86 8a bc 11 1f  91 ad f4 94 de 96 dd ef  |l.a.............|
-000000a0  d8 be 5e 45 50 fe af 1a  03 54 20 f6 05 8e a3 b0  |..^EP....T .....|
-000000b0  f7 31 93 f3 78 59 4d 54  50 99 a5 a1 53 81 1b 5d  |.1..xYMTP...S..]|
-000000c0  6d ea 32 e9 52 ab 83 d6  18 3f 2f 43 cd 64 ac 3f  |m.2.R....?/C.d.?|
-000000d0  11 6c 91 0d fa 86 f8 a5  12 eb 41 ac 24 2d 79 5b  |.l........A.$-y[|
-000000e0  ee 8e 02 46 f0 37 0a b1  19 c7 97 ed 97 d1 11 18  |...F.7..........|
-000000f0  df 80 8f f3 d7 61 a4 fe  6c ec b0 80 4e bc e4 52  |.....a..l...N..R|
-00000100  10 2f b1 6f 3f d4 39 08  81 f6 01 4b b4 d4 d5 20  |./.o?.9....K... |
-00000110  6b a1 be e6 cf c7 0e 95  e9 d7 00 07 63 25 1b 64  |k...........c%.d|
-00000120  4b b7 c4 79 29 84 45 45  5d 0d fe 72 2a 7e c6 bf  |K..y).EE]..r*~..|
-00000130  5a 98 ec e2 16 26 82 57  eb a6 dc ff 73 b6 e8 4c  |Z....&.W....s..L|
-00000140  87 52 e5 0a c1 6a 6f 02  69 17 17 ea e0 1c c1 07  |.R...jo.i.......|
-00000150  b4 f4 78 a7 99 39 8b 63  61 c2 7e 99 f4 64 16 d6  |..x..9.ca.~..d..|
-00000160  0a 84 9a 0f d4 f4 bd 4d  d4 4f 16 ec 19 30 a7 34  |.......M.O...0.4|
-00000170  f9 b9 60 10 39 25 ee 9d  bd 99 37 52 e6 32 a1 c9  |..`.9%....7R.2..|
-00000180  68 9b a2 4e 16 91 0e 54  54 d5 c5 77 bb 01 ba af  |h..N...TT..w....|
-00000190  97 be ea 09 85 91 69 84  4f 2c 04 f0 38 50 93 49  |......i.O,..8P.I|
-000001a0  e7 41 cb c1 d6 b6 77 59  09 7c 1e 0a 58 93 1e b4  |.A....wY.|..X...|
-000001b0  cf ed 32 85 b0 cd 6f 86  c7 94 8c 30 9d 83 a2 a0  |..2...o....0....|
-000001c0  4a de ad 8c b9 d8 58 d3  8c 34 6b 12 54 f1 28 66  |J.....X..4k.T.(f|
-000001d0  ea 55 d9 95 d0 b6 b3 aa  68 c3 31 e1 8f 1b f8 43  |.U......h.1....C|
-000001e0  51 b9 06 fc 53 69 9b 1c  e6 2c f8 b7 f0 47 4a 5a  |Q...Si...,...GJZ|
-000001f0  82 ca 27 df 0f 3d f8 79  90 8d c2 bd 27 85 74 6b  |..'..=.y....'.tk|
-00000200  9e 8b eb 74 a8 28 ba 6a  25 16 01 2c 56 3b c0 fa  |...t.(.j%..,V;..|
-00000210  91 ac af a7 c5 39 8d 2c  b1 f3 a2 c9 a5 72 c6 ff  |.....9.,.....r..|
-00000220  49 a0 78 14 5c 8c d2 71  de b9 4f 55 3a ca b6 a5  |I.x.\..q..OU:...|
-00000230  df ce bb f7 c2 d5 af 2c  c0 97 08 82 cc b4 02 26  |.......,.......&|
-00000240  c3 0c 99 39 4a df 6c d6  59 14 c4 d6 04 9d a4 92  |...9J.l.Y.......|
-00000250  d2 53 42 16 56 99 5f c2  82 a0 a8 5a 92 53 e6 b1  |.SB.V._....Z.S..|
-00000260  cd fc bc 9a b9 55 0b ae  2c 50 ce a3 bf d2 7d d2  |.....U..,P....}.|
-00000270  2b 58 ba 87 65 33 09 cf  74 51 0f 4b 4f a9 53 0d  |+X..e3..tQ.KO.S.|
-00000280  fa 60 1e ba e6 17 03 03  00 99 aa 43 d9 e2 e4 91  |.`.........C....|
-00000290  cf 65 fa 35 0e b0 21 51  9d c4 33 f5 7c 09 ff e5  |.e.5..!Q..3.|...|
-000002a0  db fd 6e 96 6d 13 7c 4c  ec 90 72 bd 54 6a 3f d8  |..n.m.|L..r.Tj?.|
-000002b0  1a a3 e2 a2 01 6b d6 50  a0 b1 d5 67 34 44 42 30  |.....k.P...g4DB0|
-000002c0  97 2e 82 07 46 04 56 0a  43 4b 9d 8c 81 64 bb 0b  |....F.V.CK...d..|
-000002d0  21 62 ea 23 0b 1c a0 c4  b2 cc 2f 51 b5 a2 9a a3  |!b.#....../Q....|
-000002e0  37 d3 0c 57 80 85 77 3b  8d 17 f1 a9 d5 ae 72 f9  |7..W..w;......r.|
-000002f0  cd 8c c4 2c fb c7 e0 f0  3a 5c d5 6a f7 8f 7e 53  |...,....:\.j..~S|
-00000300  c1 d0 7a b0 8d c9 b3 17  7c 99 df 54 d6 43 13 d5  |..z.....|..T.C..|
-00000310  78 9c 34 7e c9 11 4e e7  1c 8c f4 0f 82 89 94 61  |x.4~..N........a|
-00000320  80 d2 49 17 03 03 00 35  aa cd 97 5a a2 d3 27 78  |..I....5...Z..'x|
-00000330  d4 79 28 a7 57 dc 4f b1  2d b8 bd 3c ae ec e6 be  |.y(.W.O.-..<....|
-00000340  33 be b9 20 3b 69 22 03  31 34 7a 8d 68 39 c7 d5  |3.. ;i".14z.h9..|
-00000350  a1 a0 aa 46 15 94 93 d7  54 41 5b 6b 20 17 03 03  |...F....TA[k ...|
-00000360  00 17 f2 60 ff 91 c2 85  55 ed ab 39 6f 5d 0f 22  |...`....U..9o]."|
-00000370  45 3e 61 07 14 a3 05 f4  94 17 03 03 00 13 01 ea  |E>a.............|
-00000380  95 52 29 1c 63 71 3a 2d  73 a7 29 31 2c d0 ce 9f  |.R).cq:-s.)1,...|
-00000390  2b                                                |+|
+00000000  14 03 03 00 01 01 17 03  03 02 7a 94 78 2d 5d 5a  |..........z.x-]Z|
+00000010  3e 96 7f 19 29 51 99 f3  6e d3 a4 d5 3c 9a 3d d5  |>...)Q..n...<.=.|
+00000020  37 bc 3b 71 b3 54 83 d9  5e 9d 64 76 f9 74 7a 24  |7.;q.T..^.dv.tz$|
+00000030  e3 cb ea aa 17 f4 44 41  73 71 39 d6 9b d5 a6 a2  |......DAsq9.....|
+00000040  6a 1e 1c 02 a1 d5 e3 e8  f5 f7 07 9d 3b ea f8 6d  |j...........;..m|
+00000050  80 cf 6b 14 71 b8 bd c4  8a 07 49 31 e7 bd d5 91  |..k.q.....I1....|
+00000060  ac 80 70 25 5e f4 db 07  ed 36 c2 3a 1d ad 86 6e  |..p%^....6.:...n|
+00000070  68 1a ca 4f a1 ba c3 2f  de 49 01 fa a9 39 a6 51  |h..O.../.I...9.Q|
+00000080  3a e6 9f cf 6b 02 4e 1e  70 dd f2 10 c2 62 9b 1f  |:...k.N.p....b..|
+00000090  83 10 fa 85 52 a8 a7 08  37 9c 92 b0 9c fe 00 78  |....R...7......x|
+000000a0  0b a4 7b b5 f9 9f 87 d2  d3 07 72 b2 ab 96 9e 73  |..{.......r....s|
+000000b0  55 3c 1e 65 99 89 36 78  7e 42 8f 05 de b6 fb fc  |U<.e..6x~B......|
+000000c0  1b 34 18 e6 4d 15 6c d1  2f 2c b0 ef 00 e9 07 89  |.4..M.l./,......|
+000000d0  ca 91 d9 c1 73 bf 8f a5  a4 7d 7e cc f5 85 fb af  |....s....}~.....|
+000000e0  57 70 35 63 71 d6 78 57  13 48 27 ba a4 42 22 c2  |Wp5cq.xW.H'..B".|
+000000f0  56 f4 ae 38 39 a0 1f 57  44 57 c4 8a 70 90 30 70  |V..89..WDW..p.0p|
+00000100  ba 4a 98 29 0f aa e2 33  27 24 ee d9 e9 02 80 68  |.J.)...3'$.....h|
+00000110  4c 55 08 fb 3d 25 d6 d4  9d 83 ea 14 99 c2 77 94  |LU..=%........w.|
+00000120  f9 70 34 a8 ed 35 e6 4f  c2 75 50 63 d5 9d 9a 89  |.p4..5.O.uPc....|
+00000130  8f 2e 5b ca 6b b3 ad e7  a2 c6 f7 0c 45 08 b7 f4  |..[.k.......E...|
+00000140  58 d3 d5 54 c2 67 f3 76  fb fc 9d fe 42 43 ea 90  |X..T.g.v....BC..|
+00000150  2b 29 e7 10 2f d7 9c 04  c4 cc 89 8f a9 36 14 f6  |+)../........6..|
+00000160  fc f1 25 6c 90 12 bf c6  cd ad 46 ce 17 3b 26 fb  |..%l......F..;&.|
+00000170  c6 98 cb 6c f2 2c fd b9  2f 52 3e 56 42 78 0b 92  |...l.,../R>VBx..|
+00000180  a5 27 56 18 3d d6 26 3f  e4 a1 6f ce c8 f1 f1 7a  |.'V.=.&?..o....z|
+00000190  1f 84 66 c9 d9 8a 5c 0e  34 80 ba 58 b3 8b 7f f3  |..f...\.4..X....|
+000001a0  8a c9 6b c4 99 94 2c b7  e8 e8 9a a5 43 75 f8 e0  |..k...,.....Cu..|
+000001b0  29 1f 70 77 c7 4a 9f de  ca 92 88 7c 37 12 d9 ef  |).pw.J.....|7...|
+000001c0  2f 94 de ea d1 d9 69 6a  93 06 36 e0 68 02 53 ae  |/.....ij..6.h.S.|
+000001d0  0e 00 cd ad d3 10 a7 89  2c 53 a7 03 d9 07 3c e9  |........,S....<.|
+000001e0  0b b0 18 2e 03 88 03 5c  f4 b2 7e 59 f4 22 8c f7  |.......\..~Y."..|
+000001f0  5e d7 c7 ea ac 0f bc f7  3e 3f 75 fd 6d 9c 4c 3c  |^.......>?u.m.L<|
+00000200  41 8d f5 30 17 20 83 c3  27 83 ce 84 6a e3 75 2b  |A..0. ..'...j.u+|
+00000210  9d 7d de 2a bf 5a fb e1  2f 80 74 74 f6 09 bc 1f  |.}.*.Z../.tt....|
+00000220  be f0 59 9e ce a1 62 46  54 a4 9a 25 97 b7 cd 1a  |..Y...bFT..%....|
+00000230  0a d0 44 f6 ea a4 ed 63  e7 49 9a 4b f4 1a 39 91  |..D....c.I.K..9.|
+00000240  e6 34 e1 7b dd e7 53 ab  83 56 57 b2 89 3f 90 1f  |.4.{..S..VW..?..|
+00000250  98 c4 64 27 b5 f5 f6 57  16 ca d9 0a 33 de 24 c3  |..d'...W....3.$.|
+00000260  f3 7c 23 37 94 93 c5 1a  42 da 18 6b 24 dd 37 54  |.|#7....B..k$.7T|
+00000270  ae f3 8a 3e 10 42 20 6e  49 23 1a 0f bd 65 7e 45  |...>.B nI#...e~E|
+00000280  12 7a 64 9a 30 17 03 03  00 99 af 41 cf 95 21 1f  |.zd.0......A..!.|
+00000290  34 df 1c c7 a8 b6 ee 31  8d b3 9e 5a 59 8e c4 37  |4......1...ZY..7|
+000002a0  79 a4 d8 75 22 da 12 21  e5 de d4 ad 98 17 e2 ae  |y..u"..!........|
+000002b0  ae 9f f6 e8 29 66 d0 ac  b4 08 16 24 40 67 9d d5  |....)f.....$@g..|
+000002c0  bf a4 64 91 a1 17 82 c0  e7 77 b6 20 26 4a 70 1d  |..d......w. &Jp.|
+000002d0  c8 f8 ec 18 b7 c6 3c 81  b9 c6 04 9c 0d 37 a6 39  |......<......7.9|
+000002e0  fd 2d 99 d7 ba 41 a4 91  60 f1 1f d2 76 76 aa 47  |.-...A..`...vv.G|
+000002f0  89 0a d1 97 0b 91 20 a9  43 c9 ce 2c 84 ba 81 7a  |...... .C..,...z|
+00000300  39 91 7d 12 75 05 8e 87  b1 3f 80 8d 12 ca 8f 91  |9.}.u....?......|
+00000310  23 84 28 11 c3 81 ed 09  05 16 6e 50 57 76 ad 5c  |#.(.......nPWv.\|
+00000320  c5 92 77 17 03 03 00 35  5a d9 15 29 1f a3 f0 cf  |..w....5Z..)....|
+00000330  74 c4 1d 0c c3 fa 54 59  1e 54 06 0d 1b ce 07 00  |t.....TY.T......|
+00000340  f9 66 3d e1 75 10 cf de  cb 7d 0d d6 d1 4d 87 81  |.f=.u....}...M..|
+00000350  13 ec 2c 28 13 a5 b3 01  c7 86 3a 84 65 17 03 03  |..,(......:.e...|
+00000360  00 17 b4 e4 18 61 62 04  b3 ca 98 36 93 42 a2 be  |.....ab....6.B..|
+00000370  2c f5 18 11 bd 7d 64 70  bc 17 03 03 00 13 32 65  |,....}dp......2e|
+00000380  fa 07 3e 3c ed 9d 85 31  ba 8e 92 ea de 17 59 cd  |..><...1......Y.|
+00000390  db                                                |.|
index 098f3ab3c984a2786bad8f699db11de9fedd4347..dac9ef70c865e97f7d5e21eee371b8f0e451d85f 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 7a 02 00 00  76 03 03 e8 ec ee 61 3e  |....z...v.....a>|
-00000010  c1 43 87 6d f1 61 ed d2  41 1f 7d d7 b7 c0 92 fd  |.C.m.a..A.}.....|
-00000020  34 17 85 7b c7 ff c4 56  dd 90 bd 20 00 00 00 00  |4..{...V... ....|
+00000000  16 03 03 00 7a 02 00 00  76 03 03 e3 21 e8 24 fb  |....z...v...!.$.|
+00000010  e8 fe 46 e2 54 a7 db 98  ae a4 b2 fc f8 17 99 b4  |..F.T...........|
+00000020  ed 6a aa 9c f9 ce e2 0f  f8 88 05 20 00 00 00 00  |.j......... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 01 00 00  |................|
-00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 3f  |..+.....3.$... ?|
-00000060  be 50 e7 f1 b0 30 60 dc  92 50 b8 01 4a d1 3e ff  |.P...0`..P..J.>.|
-00000070  6e f0 bd e1 17 44 d8 19  1b c6 63 43 e5 c1 58 14  |n....D....cC..X.|
-00000080  03 03 00 01 01 17 03 03  00 17 c0 b7 da 01 3e 64  |..............>d|
-00000090  6b 57 ba 21 12 79 42 8c  63 1f 45 d1 f2 10 fe 98  |kW.!.yB.c.E.....|
-000000a0  b6 17 03 03 02 22 90 87  e6 c3 ba 92 41 a2 96 00  |....."......A...|
-000000b0  c7 92 97 ab 4b 80 02 bb  02 83 19 f3 f6 36 d5 23  |....K........6.#|
-000000c0  3c c7 bd fb 97 67 86 cb  70 4c 60 9e 6c d4 7a f3  |<....g..pL`.l.z.|
-000000d0  03 a5 f1 09 d5 7e 07 74  f3 c8 e4 b8 da 44 a3 94  |.....~.t.....D..|
-000000e0  ee 4e 4a 7b ab 4e 92 03  49 04 4e cf 1b b3 0d 91  |.NJ{.N..I.N.....|
-000000f0  0f 98 51 5c 56 4d d3 a8  75 4b e0 96 d9 9e dd c8  |..Q\VM..uK......|
-00000100  81 c4 37 a0 c6 c9 ec 0f  e0 f1 ed 29 ff 5a a2 d4  |..7........).Z..|
-00000110  af 61 f7 b1 d5 ee e7 1d  7a e1 7f 33 8d 75 e6 9d  |.a......z..3.u..|
-00000120  bc 78 56 eb c5 89 d3 19  86 81 09 e1 ee 10 03 7c  |.xV............||
-00000130  a4 1b 78 17 51 a3 53 b4  67 5d 29 49 21 b2 51 7b  |..x.Q.S.g])I!.Q{|
-00000140  f5 dc fd 60 11 ee 8f 50  ea 28 b5 db 57 04 7e 3b  |...`...P.(..W.~;|
-00000150  ad 6f 29 d4 22 f3 a1 4b  52 ac b8 2b 30 0c 67 16  |.o)."..KR..+0.g.|
-00000160  e3 e0 7d a3 03 66 c4 39  70 8e c7 06 cf d2 6f 98  |..}..f.9p.....o.|
-00000170  c1 c9 f6 a9 6a 89 b4 3e  38 97 ae e4 f2 97 a4 6f  |....j..>8......o|
-00000180  e2 05 f8 e9 53 c9 ae f7  87 c3 0f 68 75 9e 07 e9  |....S......hu...|
-00000190  45 e9 0d 03 7e c8 79 56  30 77 e3 ea db 92 a2 f8  |E...~.yV0w......|
-000001a0  5e 5b ab 77 0d 9b bc 5f  51 40 6c 1b 0d ef b4 cf  |^[.w..._Q@l.....|
-000001b0  4a 3d a6 8c b6 ab ce 4f  6c 08 0e 23 f0 2a 56 07  |J=.....Ol..#.*V.|
-000001c0  f5 88 68 c3 0c fd 63 9b  e4 56 12 a6 f5 0a ed 54  |..h...c..V.....T|
-000001d0  40 30 ee 36 72 5d ca bb  5a 52 d3 84 14 c1 7e e4  |@0.6r]..ZR....~.|
-000001e0  f8 fb e9 c8 10 16 54 16  1f 72 99 8c 7a 69 87 ca  |......T..r..zi..|
-000001f0  62 53 dc cb a4 26 73 90  fb 11 3c 3c 9f 94 65 cb  |bS...&s...<<..e.|
-00000200  28 94 65 ca 56 45 a8 c1  ec 08 31 dd eb bc 17 71  |(.e.VE....1....q|
-00000210  cd 65 04 95 2e e7 e0 fb  73 fe 70 db 70 31 93 90  |.e......s.p.p1..|
-00000220  cf 47 07 ec 92 98 c1 da  fc 13 f8 8a 28 4e e8 80  |.G..........(N..|
-00000230  a8 96 c2 e2 a6 cd df d4  7f 46 4a 3b e9 dd cf a5  |.........FJ;....|
-00000240  75 d5 cc 67 35 81 d5 2e  e4 68 c4 56 1a 46 33 5a  |u..g5....h.V.F3Z|
-00000250  f2 79 32 6b 4e a0 6b 76  53 53 04 73 86 fd bd e2  |.y2kN.kvSS.s....|
-00000260  f7 f8 14 0f 0a a8 10 6d  a1 bf f8 d0 27 8d cb e8  |.......m....'...|
-00000270  a5 51 16 4b 11 a2 8a 6f  22 c5 7c bc c5 7a 0b df  |.Q.K...o".|..z..|
-00000280  70 1d c4 93 ec 87 78 12  77 e3 85 5a 3c 29 d8 f7  |p.....x.w..Z<)..|
-00000290  ab a4 c6 10 50 ed d5 2a  3f b1 84 73 1e 7f 99 eb  |....P..*?..s....|
-000002a0  31 9c 2c d2 6a 80 4a 5e  7c aa 64 e7 83 df a9 17  |1.,.j.J^|.d.....|
-000002b0  c3 4c 13 c8 c1 d7 1b f5  be c9 00 cf ec 7e a5 ab  |.L...........~..|
-000002c0  89 9c b0 72 fd f0 cb 54  17 03 03 00 a4 28 34 92  |...r...T.....(4.|
-000002d0  a7 52 92 5d a0 99 6b e6  22 c5 f6 76 86 1b 0b d6  |.R.]..k."..v....|
-000002e0  b7 a8 67 c1 04 b8 1c ac  7b 02 f5 0a 20 41 dd 43  |..g.....{... A.C|
-000002f0  25 cc 01 f9 dc 6e c7 f7  4f 67 dd b3 54 81 80 d5  |%....n..Og..T...|
-00000300  6d 45 00 42 d0 49 23 d5  12 33 e4 5f fd 58 79 81  |mE.B.I#..3._.Xy.|
-00000310  e3 df 67 6d 03 44 58 0f  76 38 c3 de ed 26 90 29  |..gm.DX.v8...&.)|
-00000320  45 92 ce 3b fa ea 98 da  ea a2 d2 cc c6 0e a8 38  |E..;...........8|
-00000330  c1 2d 92 8c 48 79 58 25  75 fd 2d 6d ef 06 32 1a  |.-..HyX%u.-m..2.|
-00000340  bb 09 fa 66 bc 06 9d c5  fb 46 94 5e b1 73 8d 05  |...f.....F.^.s..|
-00000350  e1 90 24 c3 eb 72 7f a8  b7 12 a3 3c 11 29 ea 80  |..$..r.....<.)..|
-00000360  10 4e 19 40 25 0b c9 34  70 99 e9 1a 60 17 bb 5b  |.N.@%..4p...`..[|
-00000370  1a 17 03 03 00 35 91 4b  45 15 d5 2e 33 a7 ba 9b  |.....5.KE...3...|
-00000380  64 20 bb 72 28 06 27 37  2f ac c9 c0 9e b9 d8 f3  |d .r(.'7/.......|
-00000390  86 36 d2 7d df c2 4d 95  a5 a4 4b 64 5f 1a 83 67  |.6.}..M...Kd_..g|
-000003a0  f6 6a 21 ff d0 b4 1c 65  23 62 ac                 |.j!....e#b.|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 03 00 00  |................|
+00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 a9  |..+.....3.$... .|
+00000060  5a 5c e9 b1 71 e8 a8 64  97 65 02 6b 3d 25 6f 6f  |Z\..q..d.e.k=%oo|
+00000070  9a 47 cb 4a 81 ac 89 23  22 c1 f4 3d db 77 1e 14  |.G.J...#"..=.w..|
+00000080  03 03 00 01 01 17 03 03  00 17 12 15 75 15 9f 10  |............u...|
+00000090  90 07 34 9c eb 05 d0 a1  4b 36 5b 4c 7b 26 2a 00  |..4.....K6[L{&*.|
+000000a0  29 17 03 03 02 22 85 a0  67 d7 72 57 83 19 79 12  |)...."..g.rW..y.|
+000000b0  b7 bd 37 ed ab 49 5d 15  49 2b 4f a1 b2 25 08 22  |..7..I].I+O..%."|
+000000c0  88 83 70 07 bc 8f 69 45  1b 21 36 99 f4 99 40 f8  |..p...iE.!6...@.|
+000000d0  0d 30 13 87 70 68 f6 9d  ce c7 9e 25 2c 1e 7a b5  |.0..ph.....%,.z.|
+000000e0  52 ed f8 0f f7 d9 e5 15  fc a3 47 83 0d 18 c4 de  |R.........G.....|
+000000f0  a1 a6 24 35 aa 56 d1 8b  95 07 5f 0f ba 1f 96 c3  |..$5.V...._.....|
+00000100  5b 36 cc d2 15 e6 b4 88  8f e3 7f 79 c2 24 d5 f3  |[6.........y.$..|
+00000110  a7 35 69 4e d2 2a f7 5c  08 8a c0 26 dd b9 77 5b  |.5iN.*.\...&..w[|
+00000120  96 1b 5f 03 89 07 a0 6a  b1 14 1d 02 46 08 eb 80  |.._....j....F...|
+00000130  d5 4c dc 69 63 8f 14 a1  e5 02 95 05 8a 8b c8 68  |.L.ic..........h|
+00000140  c3 d8 75 56 47 94 32 ba  67 71 ed 4b b4 62 ba 6a  |..uVG.2.gq.K.b.j|
+00000150  31 20 a7 d6 f8 8c a0 e9  e8 d2 1a 6b 85 6b b7 ee  |1 .........k.k..|
+00000160  78 e1 2e 4c 14 f0 b3 3e  b8 dc 7d af f0 9d 29 f3  |x..L...>..}...).|
+00000170  54 1d 9d dc 9e a3 9f 29  5b 33 1d f7 00 98 85 bd  |T......)[3......|
+00000180  42 39 85 75 cf fa dc f3  7e 80 14 4e a5 90 80 b6  |B9.u....~..N....|
+00000190  e3 37 d3 27 c6 7b b9 ee  32 61 a5 72 e5 2f a6 ab  |.7.'.{..2a.r./..|
+000001a0  cb 8e ac 53 4b 86 24 92  4b 77 d6 8d aa b4 37 d5  |...SK.$.Kw....7.|
+000001b0  2b b2 2f 07 23 37 4a d9  1f cc 6c 72 c6 21 5b 38  |+./.#7J...lr.![8|
+000001c0  a3 33 5c 86 50 69 34 8f  5a b8 cc 5e 82 7d 5b b2  |.3\.Pi4.Z..^.}[.|
+000001d0  5b f5 58 7f 2c 61 08 4b  3d 8b 67 09 19 01 d2 4f  |[.X.,a.K=.g....O|
+000001e0  06 62 17 4e d4 bf 88 89  bb c4 6e 14 2b 3a 50 c9  |.b.N......n.+:P.|
+000001f0  56 8a c1 0a 45 e6 67 32  f3 96 37 4b ba c2 2a 2b  |V...E.g2..7K..*+|
+00000200  84 e1 ff bb e0 ea 68 9b  98 fc 78 26 25 f6 50 25  |......h...x&%.P%|
+00000210  52 57 83 94 39 b9 a7 8d  38 43 70 a8 b7 61 a6 cf  |RW..9...8Cp..a..|
+00000220  09 77 db 3d 64 94 63 73  5b a1 6d f4 06 c1 b3 fb  |.w.=d.cs[.m.....|
+00000230  c6 9a 0b ea 9f 8e 6d 58  53 0e 13 e0 a6 21 69 7a  |......mXS....!iz|
+00000240  d3 57 32 d4 c6 32 ef 02  8e 54 1d 72 2d d6 a7 dc  |.W2..2...T.r-...|
+00000250  59 54 be 69 3f 5c 53 23  a9 f7 3e a9 e6 e7 e0 98  |YT.i?\S#..>.....|
+00000260  65 f6 74 f4 49 1c 77 0f  92 34 87 81 29 85 d1 e0  |e.t.I.w..4..)...|
+00000270  1e 4d b4 eb c2 44 43 a7  10 51 7c 5e 8e a4 b6 37  |.M...DC..Q|^...7|
+00000280  78 e8 35 02 07 3d 60 a5  01 75 01 25 f3 ff 32 ff  |x.5..=`..u.%..2.|
+00000290  34 ab a4 c3 4c ad 21 b8  91 0a d6 54 4b 7d cf c5  |4...L.!....TK}..|
+000002a0  ec 0f e5 4a 4d 75 4c ec  fc 37 2b 26 5a 73 93 70  |...JMuL..7+&Zs.p|
+000002b0  88 c7 9c cf 32 f9 ee a7  27 6e 1d 9e 36 a2 31 9e  |....2...'n..6.1.|
+000002c0  cd 0e c2 89 ef 2b 40 1a  17 03 03 00 a4 ad 19 05  |.....+@.........|
+000002d0  e6 40 5e b1 ec 69 6b 47  ef 5d d3 ee a6 94 51 85  |.@^..ikG.]....Q.|
+000002e0  d8 28 d9 df 8b d0 df 23  7e bd 98 6c 33 26 45 fa  |.(.....#~..l3&E.|
+000002f0  60 71 8b f5 71 5c 22 4e  b3 a7 01 fe 17 39 89 67  |`q..q\"N.....9.g|
+00000300  0b 70 ff 52 b9 10 9c e9  02 c0 1c 56 9d c8 45 51  |.p.R.......V..EQ|
+00000310  5a dd 86 79 6d a7 7d eb  16 c2 1a 5f 6a 3b 93 42  |Z..ym.}...._j;.B|
+00000320  13 f3 3d 8a 39 21 5f a9  7f cf 4b 1e 22 f1 a3 f8  |..=.9!_...K."...|
+00000330  5c 35 41 2a e2 91 72 4f  59 61 1c 15 be 27 6a bd  |\5A*..rOYa...'j.|
+00000340  b7 16 1f 63 97 51 d6 96  dd 81 f9 e7 fd 97 33 6e  |...c.Q........3n|
+00000350  da 5a 61 77 57 6e 3b 65  24 db b3 3a 18 7b dc f4  |.ZawWn;e$..:.{..|
+00000360  7c ff ab 43 7f 1b ae ae  b8 73 71 9e be 91 d6 56  ||..C.....sq....V|
+00000370  13 17 03 03 00 35 39 61  a3 b7 e5 1d 3d 87 92 84  |.....59a....=...|
+00000380  11 39 7d f4 ce 29 b9 4b  fd 3c 0c 5a b6 3a fa e2  |.9}..).K.<.Z.:..|
+00000390  a8 5b e6 d2 e5 7e e3 a6  33 59 e4 a8 59 95 5d b9  |.[...~..3Y..Y.].|
+000003a0  31 6d 51 90 22 be c0 3f  6e 43 f2                 |1mQ."..?nC.|
 >>> Flow 3 (client to server)
-00000000  14 03 03 00 01 01 17 03  03 00 35 10 bd 5d 23 36  |..........5..]#6|
-00000010  58 43 f4 bb 5e 4e ee 43  fd 0e a1 d9 de 81 99 54  |XC..^N.C.......T|
-00000020  de 6e 82 33 71 8a 45 a7  35 f1 cd fb 5f bf 46 20  |.n.3q.E.5..._.F |
-00000030  a5 79 d6 87 aa f4 29 51  02 f5 4e 69 ef a5 d7 d6  |.y....)Q..Ni....|
-00000040  17 03 03 00 17 21 1f 90  0b 01 63 89 6a af 53 72  |.....!....c.j.Sr|
-00000050  51 c0 11 01 7b 09 dd 40  82 dd e1 32 17 03 03 00  |Q...{..@...2....|
-00000060  13 93 5d c1 19 16 5c 17  1a 7b 92 a0 9b f5 14 57  |..]...\..{.....W|
-00000070  85 39 4a ac                                       |.9J.|
+00000000  14 03 03 00 01 01 17 03  03 00 35 50 4f ce ae a5  |..........5PO...|
+00000010  f7 b0 7e 2b 91 86 72 da  90 65 fd 1b a5 46 c6 98  |..~+..r..e...F..|
+00000020  47 90 5a f2 b8 5a 1f 18  44 19 bd ca dd 2a 15 e7  |G.Z..Z..D....*..|
+00000030  53 f5 17 e8 7d 9b f1 9a  63 ac b0 b0 df c3 0e 4c  |S...}...c......L|
+00000040  17 03 03 00 17 8b bd fb  bc fd f7 af 53 9b 8b 1a  |............S...|
+00000050  a3 e5 f6 e9 87 bd 4a 8a  1b 0e c9 d9 17 03 03 00  |......J.........|
+00000060  13 8e c6 d3 6e 04 8f 3b  d4 76 a4 c7 c8 63 a8 a8  |....n..;.v...c..|
+00000070  9e ba e7 fd                                       |....|
index 0b4a17af3a297276a4a6e6d218f67bb463e505b0..d28474011bf3ec0d5106126ed7c662eac09cb5a6 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 7a 02 00 00  76 03 03 a8 21 4e 51 6a  |....z...v...!NQj|
-00000010  ce ba 17 cc 2d 25 b3 31  59 6a 3f 81 eb e6 ac a0  |....-%.1Yj?.....|
-00000020  91 d9 ef 76 a1 5f bb 63  ab 2c 6b 20 00 00 00 00  |...v._.c.,k ....|
+00000000  16 03 03 00 7a 02 00 00  76 03 03 6f b6 d3 79 9b  |....z...v..o..y.|
+00000010  00 17 a8 46 3f e4 bc fc  08 1e 56 6c d8 63 86 f3  |...F?.....Vl.c..|
+00000020  83 1b d8 26 6d 86 d6 4c  f3 4f e1 20 00 00 00 00  |...&m..L.O. ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 01 00 00  |................|
-00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 81  |..+.....3.$... .|
-00000060  4c a8 07 aa 6b 4a f9 44  77 78 a9 57 d0 07 55 07  |L...kJ.Dwx.W..U.|
-00000070  9a c2 8e 33 bf c4 09 ee  49 51 5c fe f1 7b 30 14  |...3....IQ\..{0.|
-00000080  03 03 00 01 01 17 03 03  00 17 5a 22 a1 07 01 ea  |..........Z"....|
-00000090  97 bd 5a 59 3a 21 de 9c  45 0c 41 ff 34 45 35 ab  |..ZY:!..E.A.4E5.|
-000000a0  25 17 03 03 01 50 a1 8c  19 e7 0c 69 d3 e0 f6 53  |%....P.....i...S|
-000000b0  95 15 13 4c e3 c3 3f 35  d9 73 c9 fe 24 b0 14 5f  |...L..?5.s..$.._|
-000000c0  b6 9e 94 20 cf 80 f7 88  7c 0f be 4c 70 16 00 2a  |... ....|..Lp..*|
-000000d0  55 02 aa a9 4b 7f a7 a5  b8 46 09 9e 18 78 78 66  |U...K....F...xxf|
-000000e0  22 c2 31 19 12 f7 e4 7e  f3 26 39 7d cd 5e 74 24  |".1....~.&9}.^t$|
-000000f0  fb 75 7d b7 2c b5 fb e0  49 bd da 96 e1 c3 63 8f  |.u}.,...I.....c.|
-00000100  e3 28 43 bb 32 a7 fd 9c  ab 54 ba ce 07 4a 23 35  |.(C.2....T...J#5|
-00000110  a4 3a ff 43 40 19 ef 38  07 02 ba d6 c4 f0 bf 63  |.:.C@..8.......c|
-00000120  aa b3 ea 55 d0 e1 a9 f3  cb 04 6b 1b 8d 35 3a f8  |...U......k..5:.|
-00000130  0b 1c 40 99 fe b0 04 5f  d1 5b 3f 4b be fe b5 96  |..@...._.[?K....|
-00000140  f0 49 3d bf a5 92 f3 bd  a6 4c 47 24 f8 b5 7c 45  |.I=......LG$..|E|
-00000150  47 85 9b 08 a1 da 51 7a  ce 3f 32 66 de 89 c0 c3  |G.....Qz.?2f....|
-00000160  ac da 73 0d 15 14 18 e6  a0 7d 07 26 44 df 55 b7  |..s......}.&D.U.|
-00000170  6e 4e fa c0 f5 5e 42 3a  d9 29 d3 1d e6 cf 3c 8c  |nN...^B:.)....<.|
-00000180  6d c1 d9 f9 04 f0 57 dc  47 4e d1 e2 a1 f1 a1 c9  |m.....W.GN......|
-00000190  2e da 97 4d 65 65 04 54  e7 80 f1 88 b2 34 26 61  |...Mee.T.....4&a|
-000001a0  77 8a 1f bb 82 7f 4b ce  b3 5a 55 60 e1 3a ef 95  |w.....K..ZU`.:..|
-000001b0  bd 34 fc ef 2b 18 4b bb  8a cf ba 3a 69 43 f4 59  |.4..+.K....:iC.Y|
-000001c0  98 a1 95 a3 22 f6 b5 1a  84 83 cf cb 90 eb 28 29  |....".........()|
-000001d0  b3 84 e1 0d 37 9e 98 96  91 73 f1 7f d7 9b 71 38  |....7....s....q8|
-000001e0  6e bc 2e 60 2d 27 0c 18  fd 2a b8 76 01 33 2f 95  |n..`-'...*.v.3/.|
-000001f0  6e 0b bf 2b 26 5e 17 03  03 00 59 ed 43 2f e8 df  |n..+&^....Y.C/..|
-00000200  f3 2f 91 f3 dc 1b aa ff  d3 3b 28 1f 78 21 fb e2  |./.......;(.x!..|
-00000210  7d 6e 03 09 98 c1 23 09  d7 45 da b8 e0 5a e5 27  |}n....#..E...Z.'|
-00000220  38 9a 2f da 9b d3 04 35  f5 b9 31 b0 c0 1f 8a 1e  |8./....5..1.....|
-00000230  d8 8a 19 f1 38 af a6 74  ac e5 b4 0d 45 83 b4 59  |....8..t....E..Y|
-00000240  83 42 97 14 23 55 71 ef  66 8c 35 69 3f 2c 88 63  |.B..#Uq.f.5i?,.c|
-00000250  8d 3b 05 fe 17 03 03 00  35 47 82 ec 22 f4 86 6a  |.;......5G.."..j|
-00000260  b7 c1 d8 64 3b 42 f4 ca  5c 3d ba a3 6a ea 77 6a  |...d;B..\=..j.wj|
-00000270  d6 52 e3 b0 42 fb c2 f1  2c b1 ef 44 ed 11 29 6d  |.R..B...,..D..)m|
-00000280  2b 6f 13 0f 42 48 a0 2e  5b ba a1 93 6b de        |+o..BH..[...k.|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 03 00 00  |................|
+00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 5b  |..+.....3.$... [|
+00000060  8f 4f 5a a9 95 6b 04 07  31 d3 ed 91 8b 25 b4 7b  |.OZ..k..1....%.{|
+00000070  5c a1 0a a6 26 09 92 9b  b0 72 26 f9 0d 09 60 14  |\...&....r&...`.|
+00000080  03 03 00 01 01 17 03 03  00 17 a8 99 d3 76 1f 12  |.............v..|
+00000090  19 18 15 8e 4c 59 43 92  11 4a aa 50 98 7e 4c d9  |....LYC..J.P.~L.|
+000000a0  63 17 03 03 01 50 66 f5  d6 ce 35 0f 10 e5 ab 34  |c....Pf...5....4|
+000000b0  78 17 c6 b6 60 40 eb 53  34 9f ce 02 c4 36 51 18  |x...`@.S4....6Q.|
+000000c0  c2 b3 fb f3 98 92 d0 f2  b7 be 28 f5 c7 2d fa 1f  |..........(..-..|
+000000d0  9b 8b aa e5 45 54 6b 0e  ed 6b 44 cb d4 4d 62 b2  |....ETk..kD..Mb.|
+000000e0  30 c9 df ac cf a3 7e 43  58 1e bf 6e 5b 69 4e 48  |0.....~CX..n[iNH|
+000000f0  1c 39 49 eb 8a 0c 22 f3  70 4a 80 50 39 d6 68 29  |.9I...".pJ.P9.h)|
+00000100  d0 6d 08 20 26 39 6d 37  5a 9f 79 e9 16 e3 7e 94  |.m. &9m7Z.y...~.|
+00000110  8f 5f 9b 97 2d e1 b1 48  e4 a3 36 63 40 5a 80 93  |._..-..H..6c@Z..|
+00000120  06 27 3b 93 d9 ed 2d b1  3e 74 ed bc 38 a1 cb 17  |.';...-.>t..8...|
+00000130  06 4a 9b c1 c1 d7 7a 1c  ca ff 4d ee 91 6d d0 3c  |.J....z...M..m.<|
+00000140  c2 4b cc 33 c6 7c 76 8e  db a2 e0 fe 15 e2 ec db  |.K.3.|v.........|
+00000150  1f 5d 05 c8 5e 0e 7f 2c  7a 95 08 34 68 a2 2c 7c  |.]..^..,z..4h.,||
+00000160  04 16 92 7a c8 ec 52 2d  1a c4 7a ea 12 cd 0f b9  |...z..R-..z.....|
+00000170  7c 00 51 55 02 5b 02 7d  ec 89 af f5 6d 76 89 0e  ||.QU.[.}....mv..|
+00000180  67 42 f0 e4 67 4d 3f 70  ff 2c 64 81 1c 4a 92 1f  |gB..gM?p.,d..J..|
+00000190  26 8b a4 4f 15 18 b5 11  4a 61 df 45 53 74 fd 8d  |&..O....Ja.ESt..|
+000001a0  ff 22 32 91 af c7 7f a4  7b 62 c3 3b 30 51 b6 34  |."2.....{b.;0Q.4|
+000001b0  b6 01 21 f9 86 74 be 62  27 1a 41 1f f0 0d 8b 5c  |..!..t.b'.A....\|
+000001c0  4b 82 ea 76 23 9c 36 af  25 1f f6 2d 5f 9c 28 bd  |K..v#.6.%..-_.(.|
+000001d0  b6 d5 1e 26 8b c1 dc ac  ed 6d 10 ff 13 ed fc 08  |...&.....m......|
+000001e0  08 0a 74 1c b1 5b f8 45  e4 83 44 f2 be ce 8d ac  |..t..[.E..D.....|
+000001f0  ee ae e6 21 da c7 17 03  03 00 59 d9 b3 95 0a f7  |...!......Y.....|
+00000200  1a 1a 54 fa ab 09 38 6d  6d 53 0a ef 11 73 bc a2  |..T...8mmS...s..|
+00000210  20 03 31 48 e2 0a d1 af  56 6c ca dd 88 ba 72 3a  | .1H....Vl....r:|
+00000220  c1 e0 c5 60 44 74 d6 c9  18 23 96 2c e7 88 c8 3e  |...`Dt...#.,...>|
+00000230  02 73 c0 38 d4 bd 85 a4  bb 78 a0 ba d3 fd f1 c4  |.s.8.....x......|
+00000240  27 08 05 fb 2c 26 20 b7  1a 41 87 a6 b7 97 19 26  |'...,& ..A.....&|
+00000250  50 ed 9a e4 17 03 03 00  35 68 36 c7 78 c3 5e ff  |P.......5h6.x.^.|
+00000260  b3 92 a7 25 31 2a a2 fa  24 d9 da 69 16 03 8b db  |...%1*..$..i....|
+00000270  fe b2 3f 63 88 49 f1 14  63 7a 58 a9 6f c5 64 92  |..?c.I..czX.o.d.|
+00000280  21 84 82 d8 49 98 fb f3  f1 fd 52 83 32 97        |!...I.....R.2.|
 >>> Flow 3 (client to server)
-00000000  14 03 03 00 01 01 17 03  03 00 35 11 45 8f b2 e0  |..........5.E...|
-00000010  87 3d 09 94 93 16 19 04  3d 84 6c e5 14 5e c6 8b  |.=......=.l..^..|
-00000020  73 1a 53 4c d0 f4 11 27  0c 0d 05 c7 9d ba d0 04  |s.SL...'........|
-00000030  37 ed 8b 8a 65 34 54 b1  07 36 92 8c 8c a8 30 b7  |7...e4T..6....0.|
-00000040  17 03 03 00 17 ea fc b8  84 8d f0 9d 8e 1c 2c 65  |..............,e|
-00000050  10 a8 69 7f dd 3c a4 80  45 5d c3 38 17 03 03 00  |..i..<..E].8....|
-00000060  13 15 4b b7 23 2f 55 b0  ae d3 3f f6 68 c9 b2 ef  |..K.#/U...?.h...|
-00000070  d7 e2 18 49                                       |...I|
+00000000  14 03 03 00 01 01 17 03  03 00 35 07 7b a2 7a 4f  |..........5.{.zO|
+00000010  40 e9 a2 94 9f b7 2d 91  87 1e 37 b0 ca b7 ea 91  |@.....-...7.....|
+00000020  53 f1 bf 7d 56 6a 0c 6a  9d 07 ac 93 9c db ca ac  |S..}Vj.j........|
+00000030  43 7b eb 56 9d 6c 79 f2  72 f8 0b 8d 15 08 84 d5  |C{.V.ly.r.......|
+00000040  17 03 03 00 17 07 b3 7d  a9 56 c4 76 e5 12 97 29  |.......}.V.v...)|
+00000050  b7 99 e6 3e 08 79 2d fb  1a 5b eb 7a 17 03 03 00  |...>.y-..[.z....|
+00000060  13 66 b7 65 57 0d 54 7b  6a 34 98 a1 4e 29 d5 92  |.f.eW.T{j4..N)..|
+00000070  1e b6 52 bc                                       |..R.|
index b30641131ead5daa2b2e9375dc01857313afd98a..a0ede61c70fd340b508e57417cd1018e1c7896f7 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 7a 02 00 00  76 03 03 6d fb 70 07 b4  |....z...v..m.p..|
-00000010  2d 14 d1 d1 88 17 6a a3  b1 c1 e7 23 4b 06 c4 fa  |-.....j....#K...|
-00000020  4a 0e e1 2c ce 5a d5 c7  8c ab f2 20 00 00 00 00  |J..,.Z..... ....|
+00000000  16 03 03 00 7a 02 00 00  76 03 03 d6 7f ef 2d f6  |....z...v.....-.|
+00000010  82 d9 be 6d 33 80 73 c0  d4 d8 63 e9 95 a6 5b 1f  |...m3.s...c...[.|
+00000020  ce c0 ec 13 07 f4 68 7d  cc 79 18 20 00 00 00 00  |......h}.y. ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 01 00 00  |................|
-00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 4e  |..+.....3.$... N|
-00000060  fe 87 d7 81 71 25 ba 33  de 10 df 19 38 d8 af 43  |....q%.3....8..C|
-00000070  58 3f 41 2e b9 b8 cb 1c  65 a7 cd 8d 00 b1 0e 14  |X?A.....e.......|
-00000080  03 03 00 01 01 17 03 03  00 17 b3 63 09 54 ad 41  |...........c.T.A|
-00000090  24 fe 2c 81 49 c8 86 88  c2 ad ba cd 45 77 51 c0  |$.,.I.......EwQ.|
-000000a0  d5 17 03 03 02 6d 74 7d  de 53 70 5c 11 d0 a7 68  |.....mt}.Sp\...h|
-000000b0  8e 10 c9 cb cd 0c 25 ac  88 e7 17 54 8b 32 2c ee  |......%....T.2,.|
-000000c0  97 9c 3d f6 ce d1 83 70  ee c0 85 0c fc 61 ba db  |..=....p.....a..|
-000000d0  6d e0 04 26 6f b7 4e 44  4d 1c 5c 16 9a 57 4f e6  |m..&o.NDM.\..WO.|
-000000e0  52 89 27 53 88 f8 93 91  ed b2 42 b4 4c f0 58 a3  |R.'S......B.L.X.|
-000000f0  50 a7 af 2c 47 ac ad 8b  14 a0 9f d4 28 2e 7b 28  |P..,G.......(.{(|
-00000100  8e ec d1 bb 7d d9 78 fb  24 82 9f 2a ac 4e 85 83  |....}.x.$..*.N..|
-00000110  35 25 75 8f 9e 6d 4c 8a  dd 6f 9f 9a 34 93 a2 9d  |5%u..mL..o..4...|
-00000120  d0 26 4c 7b a8 72 a3 12  b9 ef 6b c8 d0 4f 44 5b  |.&L{.r....k..OD[|
-00000130  dd f1 72 3a b4 5c 7e a8  8d d4 68 bc 6d 54 2c ee  |..r:.\~...h.mT,.|
-00000140  c1 f7 78 f1 15 cd 57 b5  54 89 08 f0 d8 56 ef 8d  |..x...W.T....V..|
-00000150  14 d1 e8 fd 83 bd ab 64  c1 99 36 4e af 81 27 52  |.......d..6N..'R|
-00000160  0f 5e 31 5e c0 70 21 fb  05 40 d4 d2 71 df 0c 09  |.^1^.p!..@..q...|
-00000170  31 83 b0 71 82 84 d9 90  6b 25 5a 67 03 30 c4 80  |1..q....k%Zg.0..|
-00000180  2c 99 41 3f fa 51 ce a8  b4 b8 98 2a bc e9 cc ce  |,.A?.Q.....*....|
-00000190  f7 0c 69 a3 c3 02 dc b9  4f 00 ac 4f 29 d5 e5 df  |..i.....O..O)...|
-000001a0  df 67 3b ed 94 8e 80 3f  aa 6e a8 b7 e0 7f 4d fd  |.g;....?.n....M.|
-000001b0  95 80 54 89 57 ff d7 73  86 bd e8 98 11 d5 09 c6  |..T.W..s........|
-000001c0  ab af 1a a4 a0 cc 30 40  bc 63 dc d0 db 92 41 f5  |......0@.c....A.|
-000001d0  5c 1e f1 92 03 5b 3f 27  23 1f 9c 8e f8 8b 4f 69  |\....[?'#.....Oi|
-000001e0  0c 3d 09 e5 95 d8 ba 8c  90 cd ac 53 ed 77 8d 75  |.=.........S.w.u|
-000001f0  3a 56 b4 f3 21 a5 4e c2  6e 1f 87 74 56 69 32 95  |:V..!.N.n..tVi2.|
-00000200  29 56 07 2c 0d b3 74 47  28 6d 8f ef 56 f6 68 7f  |)V.,..tG(m..V.h.|
-00000210  25 e4 76 06 7c 82 40 11  f8 eb 3c ec 62 fa be 60  |%.v.|.@...<.b..`|
-00000220  d3 11 98 e2 d4 b1 d0 72  3d e6 4a da f0 d6 c0 42  |.......r=.J....B|
-00000230  8e a6 63 cc a1 41 e3 18  21 00 ac cc 98 f8 8d 78  |..c..A..!......x|
-00000240  ab 9b 39 16 ad 4c fd 11  15 79 0c fd 0e 87 45 d6  |..9..L...y....E.|
-00000250  81 30 bb 3a 72 89 92 c1  fa e8 ad 59 3b 8b b0 38  |.0.:r......Y;..8|
-00000260  2d c3 6e 87 a8 b8 1f 7d  a0 b3 e6 91 83 97 78 94  |-.n....}......x.|
-00000270  f0 01 66 a2 c8 89 45 8e  2e a0 7e 89 4d 7f 49 ee  |..f...E...~.M.I.|
-00000280  2a 69 c0 ec 77 db 85 df  01 d9 02 36 df 94 81 01  |*i..w......6....|
-00000290  aa 43 a2 3d 76 8c c3 21  bf 05 c3 b2 c4 28 85 65  |.C.=v..!.....(.e|
-000002a0  7b 4a ac e3 45 40 77 1d  a9 ee 1e e9 97 7c 2f 45  |{J..E@w......|/E|
-000002b0  45 18 58 47 ab 51 0f 26  eb d5 bb ac c2 8b a9 ae  |E.XG.Q.&........|
-000002c0  65 6a 91 9b 13 93 69 c6  9d bc 61 23 20 d2 ad a0  |ej....i...a# ...|
-000002d0  d3 f9 2d 32 79 e3 4b 07  90 32 9e e1 f3 13 18 b0  |..-2y.K..2......|
-000002e0  65 6e 89 a5 45 c6 a1 9b  f0 f6 d1 66 d3 e7 49 1a  |en..E......f..I.|
-000002f0  b8 e2 17 cd d0 13 9c e6  e1 77 87 a4 8b 6a d3 74  |.........w...j.t|
-00000300  0e 85 b1 2c f3 c8 a8 f3  65 b3 71 c2 bb f5 95 d7  |...,....e.q.....|
-00000310  81 78 45 17 03 03 00 99  1e 53 96 f9 b9 97 ec 53  |.xE......S.....S|
-00000320  4e 97 a9 8c 01 06 ee 6b  31 47 93 4b ac f7 b6 4a  |N......k1G.K...J|
-00000330  15 bb 28 d7 87 73 7c 1d  3b d3 6b 9d 48 77 df 09  |..(..s|.;.k.Hw..|
-00000340  c9 97 98 b6 d6 20 94 8a  ed 71 08 2d 56 af b2 b8  |..... ...q.-V...|
-00000350  20 fc d7 81 e4 53 eb 57  6a bd 9b 1c 11 4f 2e fb  | ....S.Wj....O..|
-00000360  9a 0e 65 08 69 df 28 70  a7 50 21 62 9f 63 39 db  |..e.i.(p.P!b.c9.|
-00000370  9e 73 40 5d 73 77 a7 1d  2e 79 61 fa b9 50 f0 70  |.s@]sw...ya..P.p|
-00000380  1e 71 d1 9e c6 2f 8c 4c  5f e0 b1 37 d7 c9 ab fc  |.q.../.L_..7....|
-00000390  5f 6a ca a9 9e 27 38 42  78 ba fb e6 8e c2 3f a6  |_j...'8Bx.....?.|
-000003a0  a0 c6 04 b6 d8 b7 3a 68  83 15 3b 70 f9 0a 27 4a  |......:h..;p..'J|
-000003b0  0a 17 03 03 00 35 d0 88  b7 b8 cf 81 4e 97 76 96  |.....5......N.v.|
-000003c0  c2 ed e8 15 e4 01 54 2b  1f 0e 34 08 52 6c a8 6a  |......T+..4.Rl.j|
-000003d0  cf 04 29 7b 27 fb e9 1e  d1 6c d2 28 15 03 2a 58  |..){'....l.(..*X|
-000003e0  d4 eb 67 18 83 3f d4 2a  ab 9f aa                 |..g..?.*...|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 03 00 00  |................|
+00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 00  |..+.....3.$... .|
+00000060  e9 40 7a 65 78 98 47 43  aa e1 63 fd 6b c4 21 1d  |.@zex.GC..c.k.!.|
+00000070  58 45 5f 64 a0 18 55 a0  c3 14 7d 4e 12 93 7c 14  |XE_d..U...}N..|.|
+00000080  03 03 00 01 01 17 03 03  00 17 4c 01 0b f7 e7 1b  |..........L.....|
+00000090  a9 47 84 10 3b 50 85 6e  3d 8e 52 bc 99 bf d4 35  |.G..;P.n=.R....5|
+000000a0  45 17 03 03 02 6d 8c b3  22 04 de 8b 09 e5 e7 9f  |E....m..".......|
+000000b0  d5 1f fb 8a 57 ad a7 93  4c 5f 29 46 df c3 e5 86  |....W...L_)F....|
+000000c0  66 f1 c7 6b 14 79 cf 9d  cc e1 f5 3f 31 2c dc ff  |f..k.y.....?1,..|
+000000d0  77 99 14 9e 56 12 4e a4  cb 56 5c d6 c0 5b 57 dc  |w...V.N..V\..[W.|
+000000e0  22 72 12 2d d6 a0 8a c7  90 e6 41 66 78 1a d7 a6  |"r.-......Afx...|
+000000f0  87 db f1 e3 9b 86 8c cf  94 22 cf 81 99 20 bc 19  |........."... ..|
+00000100  50 f9 fe 6c ab ea d4 a2  ee f8 17 1d ae 37 86 2a  |P..l.........7.*|
+00000110  f9 83 3c 59 d0 aa 63 22  18 d5 12 40 be f7 02 f1  |..<Y..c"...@....|
+00000120  9a bf 07 39 23 73 23 a1  66 70 b7 be 9a 24 de 30  |...9#s#.fp...$.0|
+00000130  2f 62 6e f8 d5 ee 69 a7  87 3c 73 10 4c 7c 97 42  |/bn...i..<s.L|.B|
+00000140  62 b9 d5 74 40 f0 d7 b3  74 42 73 d7 41 bc 35 43  |b..t@...tBs.A.5C|
+00000150  87 2e c5 1b e9 15 e8 5e  18 b9 6b 57 2a ee 59 7a  |.......^..kW*.Yz|
+00000160  1c a6 2b cb b4 db e8 bb  99 87 74 4a ee 57 3a 87  |..+.......tJ.W:.|
+00000170  3c 2d b9 76 41 4a 7a a5  6a fa 92 e9 80 24 08 dc  |<-.vAJz.j....$..|
+00000180  18 44 4b 59 7c 81 99 29  f2 c4 55 b6 58 71 0d 68  |.DKY|..)..U.Xq.h|
+00000190  6b 06 bd 13 2c a0 04 15  2e 49 cc 99 7f a6 b4 5d  |k...,....I.....]|
+000001a0  d3 49 a5 21 15 d7 66 2d  a2 e8 cd a7 7e 46 c4 ac  |.I.!..f-....~F..|
+000001b0  89 ae cb 58 73 42 9f dc  c3 c9 5a 13 2f 6f f7 ab  |...XsB....Z./o..|
+000001c0  04 4b 9f f1 6c c4 ac 0f  f5 eb 8d 7a ef cf 01 00  |.K..l......z....|
+000001d0  8a 02 ec 16 09 c1 e9 27  81 32 70 b1 24 d4 db 4e  |.......'.2p.$..N|
+000001e0  9e 22 65 21 a7 8f 19 d5  c6 57 78 8a fa a6 41 87  |."e!.....Wx...A.|
+000001f0  52 eb 5d ef f8 7e 3b 34  a5 31 ff 33 33 fd 85 03  |R.]..~;4.1.33...|
+00000200  e4 94 56 ef 11 c0 fe 84  f6 87 94 26 de 7c bd d1  |..V........&.|..|
+00000210  1b ea 15 34 62 e5 da bd  e6 c4 b0 74 b5 27 ad 21  |...4b......t.'.!|
+00000220  39 16 c8 be e8 41 50 7b  de fb 71 10 4c b1 f4 5a  |9....AP{..q.L..Z|
+00000230  bf ea fd 9b 86 a5 c6 e7  2f c2 13 e4 d2 cd 32 7a  |......../.....2z|
+00000240  6b ad ab 43 12 3b 45 b9  5c e4 cf 2c f9 f3 44 2c  |k..C.;E.\..,..D,|
+00000250  11 31 ce c5 65 dd ea e6  52 bd 8a 35 d0 31 d4 4f  |.1..e...R..5.1.O|
+00000260  01 24 54 e4 d2 bf 6e 79  b2 bf a8 f0 5d 9d 72 44  |.$T...ny....].rD|
+00000270  6e df 29 8a d2 cc a8 d2  ee 0c 51 50 cd 71 a6 2a  |n.).......QP.q.*|
+00000280  fe 53 2e f7 ae fa 4c 34  d0 68 31 d5 69 be 64 a5  |.S....L4.h1.i.d.|
+00000290  03 54 31 1a dc f0 9e c7  82 1f 15 d1 64 ff 79 07  |.T1.........d.y.|
+000002a0  5e 71 3a 98 3c 21 a7 8e  1e bf 2d f3 86 4b 3f 30  |^q:.<!....-..K?0|
+000002b0  73 0d 7c 5d 57 1b a9 89  2b 52 70 84 8e e6 bb fe  |s.|]W...+Rp.....|
+000002c0  b7 1f 65 6a 08 63 58 16  81 51 09 b2 79 7d 84 c0  |..ej.cX..Q..y}..|
+000002d0  6f e1 ab 92 35 16 2e 8f  5c 17 2d 5e 68 7f d4 94  |o...5...\.-^h...|
+000002e0  5a 1b 1d 6c 5f e0 36 a0  ae 54 5b e9 39 1f bc 73  |Z..l_.6..T[.9..s|
+000002f0  f9 04 80 e9 36 d2 2c de  64 ca 08 95 d0 98 4b da  |....6.,.d.....K.|
+00000300  7b 0d 7f 79 1b a0 56 6c  dd 3c 40 52 3e 7a 8f 52  |{..y..Vl.<@R>z.R|
+00000310  3c c9 2f 17 03 03 00 99  07 91 f0 6b e0 bb 6f 0b  |<./........k..o.|
+00000320  ff 08 69 bc d2 1d f1 40  d2 d7 c7 f6 c2 b3 57 d7  |..i....@......W.|
+00000330  90 00 c9 9e ef 40 b6 96  86 0d 27 8b 6f ac 54 2f  |.....@....'.o.T/|
+00000340  73 b3 b4 82 1b d3 f5 e9  41 a7 fd d5 b1 67 f7 6e  |s.......A....g.n|
+00000350  2e c1 06 34 ef a3 b9 97  4d a8 64 4f f8 48 24 5c  |...4....M.dO.H$\|
+00000360  66 f4 d7 d4 e3 ad 45 fb  4a 42 0d 19 bb a1 cc b3  |f.....E.JB......|
+00000370  88 d2 2a d7 c3 53 c4 7b  08 a5 68 dc c4 1a f6 f3  |..*..S.{..h.....|
+00000380  a1 42 48 1c c9 2b 1f fb  5d fc 49 ed ce 16 14 34  |.BH..+..].I....4|
+00000390  34 01 c9 ef e6 29 9c 81  1a 7d 7b bd 95 eb ad 5f  |4....)...}{...._|
+000003a0  ce 19 30 9c e6 ae 09 15  3c 2b 38 8b e6 97 76 4e  |..0.....<+8...vN|
+000003b0  dd 17 03 03 00 35 d2 a1  3f 22 e9 2b b6 7a d1 d8  |.....5..?".+.z..|
+000003c0  7b 87 bf d1 bf 56 0b 55  52 d0 a9 cf ae 57 6e 6f  |{....V.UR....Wno|
+000003d0  29 0c c3 f7 f3 d4 bf ff  a4 6b 49 1a 57 57 27 89  |)........kI.WW'.|
+000003e0  e0 f5 bb d2 16 85 39 40  fd 77 a3                 |......9@.w.|
 >>> Flow 3 (client to server)
-00000000  14 03 03 00 01 01 17 03  03 00 35 02 ed 34 8f 83  |..........5..4..|
-00000010  44 27 8b 71 af c1 06 33  0b 25 aa 22 85 96 41 75  |D'.q...3.%."..Au|
-00000020  4f fe 46 82 ba 95 91 4c  cc a9 99 60 5c f7 72 7f  |O.F....L...`\.r.|
-00000030  e4 1f e4 99 6a c2 25 db  d0 11 5d fc d6 28 8f 56  |....j.%...]..(.V|
-00000040  17 03 03 00 17 fe e8 cf  ed a0 7a ce 77 57 e6 aa  |..........z.wW..|
-00000050  f0 ce 6d 2f 5c e5 1f 7d  37 c8 91 cf 17 03 03 00  |..m/\..}7.......|
-00000060  13 a4 a9 4c b5 33 38 4a  1e b7 65 9d 72 85 1b 79  |...L.38J..e.r..y|
-00000070  79 87 e3 bf                                       |y...|
+00000000  14 03 03 00 01 01 17 03  03 00 35 b3 39 ad 6b 24  |..........5.9.k$|
+00000010  47 e3 9f 11 f9 7e 9a cf  41 db c8 43 ce 86 ae ce  |G....~..A..C....|
+00000020  0c af 17 42 d7 24 57 13  e6 ba a7 44 7c 72 38 aa  |...B.$W....D|r8.|
+00000030  8f fa a2 a2 9f b0 ba 43  47 20 e8 03 3c 00 ee ad  |.......CG ..<...|
+00000040  17 03 03 00 17 ff 5b 79  f8 c8 0c 7a 52 6d b0 b2  |......[y...zRm..|
+00000050  22 17 3b 5d f9 75 23 bb  27 38 35 a6 17 03 03 00  |".;].u#.'85.....|
+00000060  13 d3 94 d9 b5 8b fa dc  b6 fe 26 ca b0 52 5c ef  |..........&..R\.|
+00000070  84 e3 3c f9                                       |..<.|
index 10e13ec33d9ab61ead0e26ce5f695686b6d912b8..48403391bb19d1358094fa42e84a1f6bf56c9250 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 77 00 05 00 05  01 00 00 00 00 00 0a 00  |...w............|
 00000090  06 00 04 00 1d 00 17 00  0b 00 02 01 00 00 0d 00  |................|
 000000a0  1a 00 18 08 04 04 03 08  07 08 05 08 06 04 01 05  |................|
@@ -20,7 +20,7 @@
 00000010  9a 61 11 be 1d 8c 02 1e  65 b8 91 c2 a2 11 16 7a  |.a......e......z|
 00000020  bb 8c 5e 07 9e 09 e2 c8  a8 33 9c 20 00 00 00 00  |..^......3. ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 01 00 00  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 03 00 00  |................|
 00000050  0c 00 2b 00 02 03 04 00  33 00 02 00 17 14 03 03  |..+.....3.......|
 00000060  00 01 01                                          |...|
 >>> Flow 3 (client to server)
 00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000030  00 20 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |. ..............|
 00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000050  00 00 00 32 cc a8 cc a9  c0 2f c0 2b c0 30 c0 2c  |...2...../.+.0.,|
-00000060  c0 27 c0 13 c0 23 c0 09  c0 14 c0 0a 00 9c 00 9d  |.'...#..........|
-00000070  00 3c 00 2f 00 35 c0 12  00 0a 00 05 c0 11 c0 07  |.<./.5..........|
-00000080  13 01 13 03 13 02 01 00  00 98 00 05 00 05 01 00  |................|
+00000050  00 00 00 32 cc a9 cc a8  c0 2b c0 2f c0 2c c0 30  |...2.....+./.,.0|
+00000060  c0 09 c0 13 c0 0a c0 14  00 9c 00 9d 00 2f 00 35  |............./.5|
+00000070  c0 12 00 0a c0 23 c0 27  00 3c c0 07 c0 11 00 05  |.....#.'.<......|
+00000080  13 03 13 01 13 02 01 00  00 98 00 05 00 05 01 00  |................|
 00000090  00 00 00 00 0a 00 06 00  04 00 1d 00 17 00 0b 00  |................|
 000000a0  02 01 00 00 0d 00 1a 00  18 08 04 04 03 08 07 08  |................|
 000000b0  05 08 06 04 01 05 01 06  01 05 03 06 03 02 01 02  |................|
 00000110  32 42 e9 58 b6 d7 49 a6  b5 68 1a 41 03 56 6b dc  |2B.X..I..h.A.Vk.|
 00000120  5a 89                                             |Z.|
 >>> Flow 4 (server to client)
-00000000  16 03 03 00 9b 02 00 00  97 03 03 b5 7c 4a c4 82  |............|J..|
-00000010  67 2c 0d e4 cf 12 5a 8c  fc 44 10 da 7e ef ec ae  |g,....Z..D..~...|
-00000020  bc 59 6c 7d 62 b1 d8 95  5d 9d 3b 20 00 00 00 00  |.Yl}b...].; ....|
+00000000  16 03 03 00 9b 02 00 00  97 03 03 1d 65 62 8f 58  |............eb.X|
+00000010  2b 99 04 1d fd cc e3 0b  46 5c 55 a9 3a 80 76 60  |+.......F\U.:.v`|
+00000020  8f 52 09 6e 48 5d 5a e3  92 da a3 20 00 00 00 00  |.R.nH]Z.... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 01 00 00  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 03 00 00  |................|
 00000050  4f 00 2b 00 02 03 04 00  33 00 45 00 17 00 41 04  |O.+.....3.E...A.|
-00000060  51 c8 a4 d2 63 ec a1 b7  72 7e 42 30 8e d2 eb b0  |Q...c...r~B0....|
-00000070  3c e0 06 d0 69 39 b7 55  ee 47 c3 b3 b6 56 2d df  |<...i9.U.G...V-.|
-00000080  3e 0c 1c 92 cf f6 c4 52  13 90 fa e6 52 13 e6 6d  |>......R....R..m|
-00000090  35 46 de 60 05 a1 85 a9  ec 86 dc da 19 4d 21 67  |5F.`.........M!g|
-000000a0  17 03 03 00 17 d7 59 69  75 49 13 ac 27 ad 1c a9  |......YiuI..'...|
-000000b0  17 68 46 77 a2 22 0a f5  6f ce 70 67 17 03 03 02  |.hFw."..o.pg....|
-000000c0  6d ee 92 51 b3 07 0f 46  be 24 a1 12 02 7e d1 d4  |m..Q...F.$...~..|
-000000d0  b1 2e f5 87 f5 96 ed 00  77 f1 ad 1b 8e cd 1d 01  |........w.......|
-000000e0  41 78 6a ff 68 9f 6d ac  fe 92 8a c5 43 d2 c9 1d  |Axj.h.m.....C...|
-000000f0  a8 d8 0f 00 7e c1 06 a9  16 ba 13 94 e7 d9 cd e1  |....~...........|
-00000100  01 fd 52 12 be b0 04 14  85 d3 06 a2 63 d7 16 7a  |..R.........c..z|
-00000110  06 5f 1f c2 31 ea 27 1a  a5 1d f6 39 d2 b1 99 8c  |._..1.'....9....|
-00000120  e0 71 32 3b ef 4e d3 1c  21 3f 30 59 5b 3e 1f 64  |.q2;.N..!?0Y[>.d|
-00000130  3c 27 35 0f ee f4 75 5c  53 38 f8 43 87 55 88 28  |<'5...u\S8.C.U.(|
-00000140  17 8f 4c 2d 73 d0 bd db  43 25 2f da fb f3 f7 b4  |..L-s...C%/.....|
-00000150  63 90 08 24 c6 b3 ae 91  00 2d 4f bd af bc 22 82  |c..$.....-O...".|
-00000160  08 ef 29 c9 49 d2 73 97  ce 6c 8d 1e a2 cb 53 ff  |..).I.s..l....S.|
-00000170  fe 9c b1 14 58 6f 45 bf  ee 93 c0 9b 96 86 54 1a  |....XoE.......T.|
-00000180  fc fe 84 c3 88 13 92 d4  d7 de 00 07 d4 f7 ef 8e  |................|
-00000190  5e 5f b0 12 c9 6a 81 df  05 e6 c3 a1 f6 8a bc 06  |^_...j..........|
-000001a0  bc 45 47 06 d4 45 70 78  f9 16 0f d2 f4 ae b5 94  |.EG..Epx........|
-000001b0  e6 ac b5 bf e3 40 d1 fe  20 07 23 f8 65 fe 57 b2  |.....@.. .#.e.W.|
-000001c0  63 a0 db 7b fa 12 25 2b  1f 1c df 66 ee c4 84 80  |c..{..%+...f....|
-000001d0  4a 95 64 3d 9f c2 e9 eb  7c 59 72 1c 52 68 fa 5a  |J.d=....|Yr.Rh.Z|
-000001e0  b3 d6 9e dc 51 d6 ac 0b  34 f1 66 42 4b 99 1d cb  |....Q...4.fBK...|
-000001f0  94 f4 08 c6 57 f9 97 87  54 9c 3b ba 4e 21 c7 b3  |....W...T.;.N!..|
-00000200  a0 d9 41 33 22 c4 3f a4  29 e4 7a 3c a1 86 e0 65  |..A3".?.).z<...e|
-00000210  f4 ff 67 c5 32 ae 16 01  67 8e 16 d7 28 5e b3 19  |..g.2...g...(^..|
-00000220  c6 18 c7 27 0d 01 8e 04  87 fb 6b f9 72 ee 00 ff  |...'......k.r...|
-00000230  25 f9 c5 dd bc 30 45 63  2d 4d 2d 9d ea 7f 54 aa  |%....0Ec-M-...T.|
-00000240  ac 9e d8 a2 ae c2 e3 64  b7 3d 54 56 67 39 e8 96  |.......d.=TVg9..|
-00000250  a5 5d fd 1e 01 2a 0c 7d  ee f1 4e fc 1b 19 f9 ef  |.]...*.}..N.....|
-00000260  60 dd e1 b2 94 f3 5f 54  d4 05 f7 86 83 6f 97 43  |`....._T.....o.C|
-00000270  4e 30 c1 49 cc 5e 98 10  5c 4e 32 84 97 70 c8 b9  |N0.I.^..\N2..p..|
-00000280  6d 0b c2 23 ab f9 e8 85  6f 0a 2a 99 e7 12 33 e8  |m..#....o.*...3.|
-00000290  f2 62 6f 65 0c 3d ff 9f  e6 15 eb 1d 24 0e e9 8a  |.boe.=......$...|
-000002a0  28 e0 09 31 23 a4 5c 2c  25 49 b4 0c 5f 18 e1 12  |(..1#.\,%I.._...|
-000002b0  82 16 6e 79 68 21 fb 5a  68 73 dd f7 2f aa e2 f9  |..nyh!.Zhs../...|
-000002c0  85 8d af c6 84 50 af 84  95 12 c8 32 a6 eb f0 93  |.....P.....2....|
-000002d0  a2 bd 97 d3 ba 76 a8 2e  a2 44 2f 98 23 ca 78 cd  |.....v...D/.#.x.|
-000002e0  7a 5f bf ab 19 00 72 b5  b3 e0 a7 b5 da 47 05 c8  |z_....r......G..|
-000002f0  44 0b 6c 7f 0b 4c 99 79  3c 47 7e e9 25 bd a8 4d  |D.l..L.y<G~.%..M|
-00000300  7a 1c 17 aa 00 dc f8 d8  98 5b 8e e4 30 9f 52 9e  |z........[..0.R.|
-00000310  d3 13 ea 82 65 8b 43 1f  05 f9 3a 86 09 e0 ed b9  |....e.C...:.....|
-00000320  8d 42 75 c7 dd 70 5d 04  c5 a4 68 04 e1 36 17 03  |.Bu..p]...h..6..|
-00000330  03 00 99 52 81 9b 5c ed  c2 08 48 13 d9 4f 0a 52  |...R..\...H..O.R|
-00000340  db 15 fc 73 66 03 85 10  b3 32 f3 e9 60 f1 c5 30  |...sf....2..`..0|
-00000350  e4 85 d8 ab 85 c7 52 f0  1e 99 88 cf b0 e1 f9 c7  |......R.........|
-00000360  c1 8a d0 ed 0f 0d 34 05  35 63 a6 52 bf 91 db f0  |......4.5c.R....|
-00000370  b2 46 fb d9 68 95 ec a7  e4 fc ff f7 f0 7f 54 db  |.F..h.........T.|
-00000380  a8 96 fe 9d 12 f0 38 3e  4f 68 ff 27 1c 25 a6 1d  |......8>Oh.'.%..|
-00000390  1f 89 9e 21 34 97 b9 7e  6e 2a c2 df 47 22 7d a6  |...!4..~n*..G"}.|
-000003a0  aa 7a 4a fd 11 b0 73 10  f5 16 8b 2c 3a af a6 7a  |.zJ...s....,:..z|
-000003b0  cc 3d 4b f0 36 43 60 db  53 2a 4e 2c 1b 2c 0a 54  |.=K.6C`.S*N,.,.T|
-000003c0  01 ff ad 7e 93 a8 d0 76  da 5a 88 88 17 03 03 00  |...~...v.Z......|
-000003d0  35 d0 36 70 7c 4c 6a 10  bd 43 50 2c 47 74 f9 ed  |5.6p|Lj..CP,Gt..|
-000003e0  9f 0b d7 33 82 74 2f fd  81 4d 08 d6 cf f4 13 4e  |...3.t/..M.....N|
-000003f0  de ec 84 bf 79 35 ee 72  8a a3 d0 61 29 94 ad 79  |....y5.r...a)..y|
-00000400  04 42 0f 2b 65 a1                                 |.B.+e.|
+00000060  1c 01 c6 9e c8 49 43 49  6f 0f 17 f3 ce 87 1a 0f  |.....ICIo.......|
+00000070  1f 2c 70 18 e4 29 f2 16  a2 e0 02 b7 9d 52 bc b9  |.,p..).......R..|
+00000080  d4 b0 1d 19 da 3a 38 f6  93 04 0b ae 5f 60 45 87  |.....:8....._`E.|
+00000090  57 80 20 27 c6 9c d4 eb  ec c0 85 df f5 aa be de  |W. '............|
+000000a0  17 03 03 00 17 d4 a9 5f  09 d3 e6 47 ad a7 7b 38  |......._...G..{8|
+000000b0  a3 b8 02 37 16 ec 03 56  df d5 8d ec 17 03 03 02  |...7...V........|
+000000c0  6d be 1b 2a 60 52 3c 01  2e 6e 7f e3 68 fa de 09  |m..*`R<..n..h...|
+000000d0  ed 5e 8f 0f a0 34 d5 0a  8b 2f 30 8f 6c 56 9e fe  |.^...4.../0.lV..|
+000000e0  e6 9a a9 f1 6e 7c 63 a7  d8 88 e2 95 fa 17 ad 0c  |....n|c.........|
+000000f0  49 20 93 18 3c ba db fc  a1 14 60 2c 77 d4 44 5f  |I ..<.....`,w.D_|
+00000100  69 9c c7 a3 b9 d0 ee e8  c5 ec 45 d3 79 d0 ee 04  |i.........E.y...|
+00000110  fd c3 6d 12 1a f2 6e 62  9f eb ff 32 88 17 4c df  |..m...nb...2..L.|
+00000120  20 4f cc f9 fd d5 7c 8b  8c c2 da 7d 8a c9 f9 27  | O....|....}...'|
+00000130  32 06 75 fe 75 e2 bb bd  6c 31 5d 32 af 36 95 39  |2.u.u...l1]2.6.9|
+00000140  92 6c 32 e5 4f b5 f7 07  9f b3 1b b8 10 a8 d9 db  |.l2.O...........|
+00000150  d3 b0 40 2f 1e e6 54 f5  35 73 7d 22 b3 6b b8 3c  |..@/..T.5s}".k.<|
+00000160  83 82 8a 75 f4 ec 18 94  57 0c de 98 41 73 61 63  |...u....W...Asac|
+00000170  5b 95 3e 4e d4 02 c3 b7  f9 4c 6f 01 c9 52 3c b9  |[.>N.....Lo..R<.|
+00000180  ad 61 83 2c 89 6d 63 40  fd d4 67 83 36 8b 9a 1c  |.a.,.mc@..g.6...|
+00000190  ca 93 16 d8 e3 91 08 d1  3f ba af cb d9 69 09 10  |........?....i..|
+000001a0  07 a7 54 9c ee a2 7d 97  ce b6 1f 31 9b 85 b0 82  |..T...}....1....|
+000001b0  fc 22 87 70 93 59 9c c9  e3 07 9b d0 c0 a4 1d d4  |.".p.Y..........|
+000001c0  2e 36 c0 72 b6 d5 2a f5  b3 fa ab fb 1a 90 05 51  |.6.r..*........Q|
+000001d0  b7 19 15 af d9 b2 5f 32  ef e6 5a 2d 4a 2c 7f a9  |......_2..Z-J,..|
+000001e0  43 cf b8 ac e4 8a f0 bf  68 90 b9 7c 1c 7e fa f0  |C.......h..|.~..|
+000001f0  bc e3 a9 4f a7 2d 3a f3  12 eb b1 93 b4 b9 1b d7  |...O.-:.........|
+00000200  81 31 db 58 c4 8e 9f 46  44 39 74 a1 a8 b0 78 0c  |.1.X...FD9t...x.|
+00000210  b9 23 6d 90 bb a8 b0 7c  e2 a3 a3 c4 e6 83 32 5d  |.#m....|......2]|
+00000220  ea 5a a4 3d 94 ca 51 3c  71 28 cf 43 27 9f 66 9b  |.Z.=..Q<q(.C'.f.|
+00000230  ec 49 0f a4 12 f5 a3 96  cd 3e 05 5b 9c d0 07 6f  |.I.......>.[...o|
+00000240  8a 11 df 2f be a7 1d 0d  9f a8 04 41 3d 5e 1b f6  |.../.......A=^..|
+00000250  b0 10 9b 6a 49 da 6c f9  6c 6e 2e 6c 9b cf f1 fe  |...jI.l.ln.l....|
+00000260  49 92 2b 16 3f 63 ef 87  71 9c da 0d 49 63 2a 4c  |I.+.?c..q...Ic*L|
+00000270  b5 82 c8 b0 75 5b 7b 89  39 cd 9a da dc 42 d1 1f  |....u[{.9....B..|
+00000280  92 61 e1 71 b9 b5 d2 40  3c 7a 4a 8d 91 1f e6 9d  |.a.q...@<zJ.....|
+00000290  79 37 71 3c dc a3 98 0b  b3 64 39 74 f1 8f 84 35  |y7q<.....d9t...5|
+000002a0  1d 6b b7 0a f9 aa 26 55  a8 39 7f 11 26 18 98 fe  |.k....&U.9..&...|
+000002b0  94 fb 5d e4 a1 2f 0f 3b  f0 b6 78 d5 87 32 73 6e  |..]../.;..x..2sn|
+000002c0  3e b1 3e 3c 19 31 7a ae  d8 73 67 96 56 9c 38 a6  |>.><.1z..sg.V.8.|
+000002d0  bc 39 1f 11 74 ad 69 c6  d2 40 0f 65 d8 ee aa 87  |.9..t.i..@.e....|
+000002e0  b3 4c 6c 1a 1d 62 4a 7a  d9 15 05 54 0d 8a 22 68  |.Ll..bJz...T.."h|
+000002f0  8e 41 22 b0 ee 41 b3 94  5d 1a 62 d8 bb ac f2 87  |.A"..A..].b.....|
+00000300  ad 91 19 e7 e1 bc 29 3b  96 8c d1 76 99 e5 82 48  |......);...v...H|
+00000310  0b 87 6a 93 3b 2c b7 c1  73 07 53 7c 1f 9f 48 dd  |..j.;,..s.S|..H.|
+00000320  71 da 55 e1 4a a3 86 d2  ff 23 b2 1d ea b0 17 03  |q.U.J....#......|
+00000330  03 00 99 75 af 84 36 54  8e 17 09 c7 2e 72 de 7d  |...u..6T.....r.}|
+00000340  29 5c 94 a9 e3 d3 d0 9b  3e a0 84 e6 cf b4 48 d8  |)\......>.....H.|
+00000350  dd 7c 8a 82 96 15 aa cb  95 38 88 9e 48 c4 bf 75  |.|.......8..H..u|
+00000360  9c f4 07 ed 5d 4d 36 8b  58 7f 9c 32 0b f9 d2 44  |....]M6.X..2...D|
+00000370  3d d6 ab 3b 3d 38 1f 8d  7e e8 b6 26 57 c9 c6 98  |=..;=8..~..&W...|
+00000380  49 4f 1e ad 5d fa 8b ca  bc ce 99 f2 d9 5b 14 54  |IO..]........[.T|
+00000390  56 0c 59 c8 22 9f 77 f1  db 92 43 c3 dd a5 29 ec  |V.Y.".w...C...).|
+000003a0  0d 79 0d b3 04 3f 4b 6b  d6 a8 da 99 64 94 78 a5  |.y...?Kk....d.x.|
+000003b0  e9 cd 7e f8 0c fb 72 d6  03 89 dd 00 13 f3 14 18  |..~...r.........|
+000003c0  ba 59 3c 04 7f 6a b5 62  37 56 2e 2d 17 03 03 00  |.Y<..j.b7V.-....|
+000003d0  35 af eb 05 4e ec ee 4b  d6 6b 03 35 d8 ba a3 cf  |5...N..K.k.5....|
+000003e0  50 c6 80 07 90 92 1c ed  1f d2 d5 12 e3 7f 74 1a  |P.............t.|
+000003f0  2c 3b 4b 6c f4 58 af 9a  1a cd 90 f4 d8 78 97 09  |,;Kl.X.......x..|
+00000400  2f f6 35 c1 29 b8                                 |/.5.).|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 35 4b f7 dd  b6 64 32 61 42 e7 b2 93  |....5K...d2aB...|
-00000010  b8 4b dd 7c 25 c6 57 5b  68 d5 f2 d9 27 85 ee cf  |.K.|%.W[h...'...|
-00000020  09 44 79 8d 8e 14 0f 84  44 e5 16 a9 bf d9 14 bb  |.Dy.....D.......|
-00000030  22 73 c7 a9 24 c1 dd 38  1e 63 17 03 03 00 17 63  |"s..$..8.c.....c|
-00000040  56 45 91 62 9c 00 4b d6  ae f4 dc 17 a2 89 55 0d  |VE.b..K.......U.|
-00000050  c3 d4 f3 12 8b bf 17 03  03 00 13 1f ac ed f8 80  |................|
-00000060  31 7f 75 9f 6c a1 48 6e  20 89 b8 45 08 33        |1.u.l.Hn ..E.3|
+00000000  17 03 03 00 35 8d 07 5a  33 f5 d1 e7 6d 71 48 45  |....5..Z3...mqHE|
+00000010  3e 2a c0 7e 66 03 77 b5  69 b1 e5 13 04 0e 0d ea  |>*.~f.w.i.......|
+00000020  6f 80 46 a1 9a 54 09 6f  a7 be b7 a3 a1 0c d4 ba  |o.F..T.o........|
+00000030  0e 7d 00 8f 1b 01 0b d4  6b 4c 17 03 03 00 17 b9  |.}......kL......|
+00000040  fd 5a 5c a1 c2 33 71 63  99 25 bd 03 a3 24 a7 b6  |.Z\..3qc.%...$..|
+00000050  e7 42 04 6a 81 c5 17 03  03 00 13 b6 4a f1 0a 26  |.B.j........J..&|
+00000060  95 e8 fb 4b d1 db 24 95  8f 65 1f 3c 5d b9        |...K..$..e.<].|
index d1efba928c55b454f46415416523a9de30d4a9a4..ea10f66ff0cc3f5bee977a25c65b60d32fe39a26 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 7b 00 05 00 05  01 00 00 00 00 00 0a 00  |...{............|
 00000090  0a 00 08 00 1d 00 17 00  18 00 19 00 0b 00 02 01  |................|
 000000a0  00 00 0d 00 1a 00 18 08  04 04 03 08 07 08 05 08  |................|
 000000e0  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 000000f0  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74     |.........._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 7a 02 00 00  76 03 03 a2 49 b5 61 fe  |....z...v...I.a.|
-00000010  e3 52 ca 87 58 57 0f ec  bc 71 51 a9 50 7c ac 5e  |.R..XW...qQ.P|.^|
-00000020  af 4e 47 56 81 6c 92 d9  10 3d d0 20 00 00 00 00  |.NGV.l...=. ....|
+00000000  16 03 03 00 7a 02 00 00  76 03 03 86 ed 46 3d 38  |....z...v....F=8|
+00000010  c5 47 10 b5 4e ac e5 b7  d7 ba cc 23 db f5 0a f4  |.G..N......#....|
+00000020  5e d3 62 af 47 8a 23 34  59 5c db 20 00 00 00 00  |^.b.G.#4Y\. ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 01 00 00  |................|
-00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 75  |..+.....3.$... u|
-00000060  c4 ba b0 c4 9b a0 57 6a  ca e4 9c c6 eb f8 66 5a  |......Wj......fZ|
-00000070  d4 64 36 34 71 9d 6d 0f  2f 34 b8 ad b7 4a 55 14  |.d64q.m./4...JU.|
-00000080  03 03 00 01 01 17 03 03  00 17 ec 4c 36 aa 81 cf  |...........L6...|
-00000090  61 2c 2f 6c 35 e8 25 62  54 17 ae 9b 46 b0 96 f5  |a,/l5.%bT...F...|
-000000a0  0f 17 03 03 02 6d 6f 6c  27 e5 53 42 db 32 b4 2c  |.....mol'.SB.2.,|
-000000b0  6a 70 56 a7 0d 3a 7f a3  d7 fe 04 4f 0a 3e 52 8c  |jpV..:.....O.>R.|
-000000c0  52 1e 3a 26 5d 47 b1 6b  da 90 e2 74 50 0d 6e fa  |R.:&]G.k...tP.n.|
-000000d0  1b 3f 17 3b 21 f7 fa f7  c7 c3 e3 14 05 09 76 b2  |.?.;!.........v.|
-000000e0  27 66 bc 42 7e 49 4b ff  3a f1 3f a3 1a d4 9e 03  |'f.B~IK.:.?.....|
-000000f0  3f b6 a8 87 98 50 f3 d8  cb 8b a2 e9 2a ea ff bc  |?....P......*...|
-00000100  50 18 d0 57 58 c5 e9 c8  96 67 01 8b e2 a3 f4 77  |P..WX....g.....w|
-00000110  5e 1d 93 89 b6 f6 57 7d  93 b6 62 86 0a 21 18 56  |^.....W}..b..!.V|
-00000120  8c 14 25 df 47 1a b3 23  e6 99 d1 fc dc 07 0a 38  |..%.G..#.......8|
-00000130  9a 05 c8 3f 23 5c c5 d3  c4 48 fb b2 fd 9f 83 37  |...?#\...H.....7|
-00000140  1d 0c 85 9c 2b e6 ae 42  aa ad d4 5a 9e 49 89 b7  |....+..B...Z.I..|
-00000150  b0 c2 c5 ec 42 89 88 87  6e 54 3d 73 b2 f1 5f 0f  |....B...nT=s.._.|
-00000160  4b 49 3f 6b a3 8f 5f 99  bf fe af e9 25 ac 27 b7  |KI?k.._.....%.'.|
-00000170  e7 96 bb 4a c8 e8 9e f1  2c 23 c2 e7 96 ba b4 fe  |...J....,#......|
-00000180  d5 94 b5 72 82 bd 7f c2  e1 af b4 bd db c7 15 20  |...r........... |
-00000190  85 60 bb 02 f6 4b ef 09  3e a1 4e b9 77 64 0a 4a  |.`...K..>.N.wd.J|
-000001a0  2c 05 82 96 91 be 23 44  50 c1 c5 6c 05 55 51 42  |,.....#DP..l.UQB|
-000001b0  84 87 20 71 65 8d 09 86  66 fa 88 8b 54 21 44 34  |.. qe...f...T!D4|
-000001c0  df 6f ce a3 e9 12 4a e0  90 76 bb 1a f5 00 79 cb  |.o....J..v....y.|
-000001d0  d8 82 3b 88 c8 6a 5b a1  49 49 a0 c0 f7 d9 8f 89  |..;..j[.II......|
-000001e0  f2 04 59 2b 0c 6f e2 3f  b8 a8 c9 aa bf 2e 18 74  |..Y+.o.?.......t|
-000001f0  45 b5 35 34 9a bb fa 77  e8 46 b2 f8 6d 41 65 36  |E.54...w.F..mAe6|
-00000200  d9 f8 64 81 a6 50 63 b4  73 3e fb f9 b3 3e 03 3d  |..d..Pc.s>...>.=|
-00000210  d1 f4 b5 c1 ac f8 3f 4d  73 b7 da 16 8a 37 c9 a7  |......?Ms....7..|
-00000220  51 33 b1 68 69 19 0b 26  de a6 42 4d 22 a3 e8 c0  |Q3.hi..&..BM"...|
-00000230  7b 1d 66 e7 70 26 44 f7  62 3f 3d 0d e2 02 50 61  |{.f.p&D.b?=...Pa|
-00000240  db 9b 5e e4 49 e8 32 32  7a c0 03 37 a8 c6 85 80  |..^.I.22z..7....|
-00000250  4a 7e 39 b5 ba 6c cb 6f  53 e5 90 d0 0d 9c 2e e5  |J~9..l.oS.......|
-00000260  90 df 9b b1 c5 3f 16 98  a9 dd a1 b5 7a 48 04 0e  |.....?......zH..|
-00000270  15 f9 60 a7 35 0b 33 a1  93 4b 73 5f b3 46 a6 43  |..`.5.3..Ks_.F.C|
-00000280  ea a3 6e 4c fa bb 24 44  cd 48 85 c1 9f ea c2 14  |..nL..$D.H......|
-00000290  92 48 2e 35 43 30 dc e6  76 23 0b e4 2f 28 13 c1  |.H.5C0..v#../(..|
-000002a0  e1 bb 2d 9f de cf 10 8f  c3 8f 48 eb 64 eb 6d ef  |..-.......H.d.m.|
-000002b0  2a b3 c5 d6 85 db a2 05  b2 46 f8 77 aa 2c fb 14  |*........F.w.,..|
-000002c0  be 09 e7 11 33 88 cb 71  1b ca 46 cb 79 c6 99 eb  |....3..q..F.y...|
-000002d0  43 bb 59 c6 91 3b 0f 1a  76 cb c7 3b ef 07 c9 cb  |C.Y..;..v..;....|
-000002e0  3a 75 ac 14 d9 53 08 ca  4d 45 48 24 4a af 4e 94  |:u...S..MEH$J.N.|
-000002f0  0e 81 31 63 d1 f6 67 25  7d c0 dd 02 05 1b ce 38  |..1c..g%}......8|
-00000300  69 cf e7 6a bb b5 02 85  00 82 71 a6 e3 c0 33 b8  |i..j......q...3.|
-00000310  78 51 55 17 03 03 00 99  b3 5c cb a4 a3 6c e9 fa  |xQU......\...l..|
-00000320  33 25 04 21 28 66 e7 d4  22 02 8f d4 3e cc e1 20  |3%.!(f.."...>.. |
-00000330  15 5b 5a 55 14 d3 2b a5  de 7b 95 48 3c 26 68 22  |.[ZU..+..{.H<&h"|
-00000340  a3 0d c6 ac 7f ec d3 7b  fa 4d 51 20 6f 32 97 bc  |.......{.MQ o2..|
-00000350  fa 0c d6 8e bf ee 13 ca  b3 cf 00 c5 f5 87 f1 cb  |................|
-00000360  9b 63 22 e6 61 99 83 78  69 1d 03 f1 0b 66 c5 c4  |.c".a..xi....f..|
-00000370  2e 6f d8 b5 59 93 f7 40  3c 40 4e 1a 58 af b5 37  |.o..Y..@<@N.X..7|
-00000380  ce dd 83 dd b1 78 a8 ba  a3 35 f8 9f 0c 47 1e fb  |.....x...5...G..|
-00000390  aa 9b b5 5f 11 4c b9 0c  c1 a0 01 47 87 f9 e6 1f  |..._.L.....G....|
-000003a0  d5 e5 3f a7 15 4d c8 a5  79 9c e5 bc 62 6f cb cd  |..?..M..y...bo..|
-000003b0  86 17 03 03 00 35 e7 4d  67 3a 39 5b ac 13 89 cc  |.....5.Mg:9[....|
-000003c0  c4 dc 20 2b a4 b2 3c 5d  96 f1 45 17 52 12 ed 85  |.. +..<]..E.R...|
-000003d0  00 f0 7e 73 3a 6d a2 46  b8 59 7f e8 6f 46 06 e1  |..~s:m.F.Y..oF..|
-000003e0  43 c9 ca af a9 3e ca d6  42 4b 41                 |C....>..BKA|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 03 00 00  |................|
+00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 e3  |..+.....3.$... .|
+00000060  ff 35 33 31 c9 d8 5c 68  2a e5 73 98 4d 11 5b d7  |.531..\h*.s.M.[.|
+00000070  06 18 a9 dd 0e 4a 21 92  5b 15 8f bb 91 a9 6c 14  |.....J!.[.....l.|
+00000080  03 03 00 01 01 17 03 03  00 17 ea ac f8 a0 41 47  |..............AG|
+00000090  af 01 fb 51 2e ec 3b 79  f1 8a 54 2b 93 45 33 c3  |...Q..;y..T+.E3.|
+000000a0  79 17 03 03 02 6d 0e c9  a4 55 8e 8c 09 55 cd a6  |y....m...U...U..|
+000000b0  d4 dc 1e 5a de ee 56 c8  c2 ac 12 77 77 76 82 fc  |...Z..V....wwv..|
+000000c0  a6 44 cb c8 c3 16 c4 5e  bc 3f f3 3b 6c 33 f3 35  |.D.....^.?.;l3.5|
+000000d0  ed bd 8e 37 1a 25 de 7e  b3 88 71 ce f9 e5 9b a6  |...7.%.~..q.....|
+000000e0  99 11 0f 71 6b 36 11 04  66 a2 5f 74 1c c6 6a 99  |...qk6..f._t..j.|
+000000f0  49 84 d1 36 96 df 6d 2c  c5 a3 cf 5a c9 37 22 8a  |I..6..m,...Z.7".|
+00000100  72 e4 d4 25 ed 4a b1 c4  85 5a 9a f7 de 0b dd 41  |r..%.J...Z.....A|
+00000110  7d 14 63 35 2e 1c 77 6c  9e 6f 41 d1 cb 29 ca 6d  |}.c5..wl.oA..).m|
+00000120  88 1c 35 53 1b 14 24 79  84 ec 85 0d de e3 0f 2c  |..5S..$y.......,|
+00000130  23 ae 41 72 85 fb 43 36  82 ba 8f 78 79 a2 c3 95  |#.Ar..C6...xy...|
+00000140  72 19 ea 1d 2f 29 0e d5  11 85 e4 cc 8c a5 f4 8e  |r.../)..........|
+00000150  39 ba 88 8f e1 5a 54 7c  53 8b a3 1a 44 9c ae 5b  |9....ZT|S...D..[|
+00000160  1f 0e ea 06 f1 8e 5f 22  d1 ef ee e1 4c b6 1a 26  |......_"....L..&|
+00000170  db 53 96 e6 bc 0b 2f ee  b7 fa 47 af 1e 9c f6 7b  |.S..../...G....{|
+00000180  81 97 0f c3 08 9b 2c a3  de bd f7 8a 1e 13 ad de  |......,.........|
+00000190  a5 fc 5f c7 7a 53 72 e5  17 dc 0a eb 90 91 29 2e  |.._.zSr.......).|
+000001a0  7a a5 09 fd be 31 ff 81  ec a3 fc 91 41 4f cb c7  |z....1......AO..|
+000001b0  27 c3 39 8f cd 77 62 72  9a e9 e9 16 da 90 b6 6b  |'.9..wbr.......k|
+000001c0  05 70 c8 aa f5 cd 88 13  4d ff a5 a9 0f e7 d2 d3  |.p......M.......|
+000001d0  97 2b eb e1 d7 fe 74 da  fb 1e af 94 e6 52 18 48  |.+....t......R.H|
+000001e0  5b e8 c3 10 9d 76 de 17  86 67 83 4a e9 fa 30 e8  |[....v...g.J..0.|
+000001f0  46 95 f5 81 b1 a5 76 38  57 37 3a 8d df ad e7 30  |F.....v8W7:....0|
+00000200  41 b2 94 31 da 0d d6 5c  df 76 01 cd 4d c2 1b fe  |A..1...\.v..M...|
+00000210  bc 69 41 ac dd d7 dd 0a  7c 5b 31 5c c8 1e b3 14  |.iA.....|[1\....|
+00000220  39 20 51 26 6d e5 55 27  a4 9a bb fc 3d 4b 6a b0  |9 Q&m.U'....=Kj.|
+00000230  54 92 ee 33 1b 9b d5 41  fd ef 21 c6 f0 f8 90 a0  |T..3...A..!.....|
+00000240  c4 f5 86 d4 d9 c7 89 6f  67 23 37 31 44 2f 8f 55  |.......og#71D/.U|
+00000250  0a aa e1 9a ec 32 26 e2  ce 96 90 c6 f5 cc 95 79  |.....2&........y|
+00000260  da 0c b4 c1 62 d3 0a 8d  7b 83 33 8e af ff 57 c0  |....b...{.3...W.|
+00000270  5b ca 0f b5 64 10 81 43  12 86 67 cf b2 0a 53 f2  |[...d..C..g...S.|
+00000280  04 46 4f 99 ee e2 cd ce  3e 82 1f 34 43 26 f9 4c  |.FO.....>..4C&.L|
+00000290  57 b0 10 c0 37 40 9c 4f  fb 14 fa 4e 1e 4b 40 da  |W...7@.O...N.K@.|
+000002a0  cc c3 d0 d7 ee 63 18 2e  97 06 a6 49 69 07 7a 3e  |.....c.....Ii.z>|
+000002b0  da 47 68 70 b0 10 bf 8d  18 d2 14 c0 18 18 b2 61  |.Ghp...........a|
+000002c0  45 54 e8 20 34 f8 a3 74  5a 8d aa c2 63 af e8 ff  |ET. 4..tZ...c...|
+000002d0  f9 1b 33 d6 34 c2 f2 c2  3d d8 0e 32 7a 10 cc 21  |..3.4...=..2z..!|
+000002e0  02 22 a6 aa 7d 15 c3 7b  3f a2 50 5a 4e 53 ec f5  |."..}..{?.PZNS..|
+000002f0  11 dd 48 6e 7e e9 c5 94  2c c4 9a 6e 10 a6 c6 a5  |..Hn~...,..n....|
+00000300  9d e1 c5 43 e6 69 a1 91  65 50 eb e6 76 db f0 09  |...C.i..eP..v...|
+00000310  14 45 ef 17 03 03 00 99  e4 82 99 6b d8 57 ca 1b  |.E.........k.W..|
+00000320  78 98 88 ad c7 04 b7 d2  b2 d5 00 3b a9 bf 86 66  |x..........;...f|
+00000330  a7 30 72 95 29 2a 27 9f  9a 3d bd 0b e6 a0 04 22  |.0r.)*'..=....."|
+00000340  56 3d d8 08 84 a7 e7 c5  67 74 34 7d 57 1f c9 df  |V=......gt4}W...|
+00000350  71 0c 97 55 5a d9 8d 99  df 49 b5 a9 57 6d b0 c7  |q..UZ....I..Wm..|
+00000360  2d 4b 70 9d e7 e3 70 31  f0 2f 32 15 7b 67 b4 4c  |-Kp...p1./2.{g.L|
+00000370  f0 f0 4a 16 a5 37 b2 ae  9b 2a 72 7c 2e d8 22 a1  |..J..7...*r|..".|
+00000380  2b 91 f2 14 fc f9 27 fd  ca ad 27 dd 15 11 df b1  |+.....'...'.....|
+00000390  cc 4c 3a 45 3f b6 7c 53  c5 d0 82 49 1a f2 28 63  |.L:E?.|S...I..(c|
+000003a0  a2 be 6f 2f db d8 d3 76  0a 12 fa 87 14 00 11 e7  |..o/...v........|
+000003b0  1f 17 03 03 00 35 0c af  49 a1 ba 14 d4 e5 5c cf  |.....5..I.....\.|
+000003c0  c8 f7 fb 93 e3 d5 45 ac  59 ed 56 3c 1c e6 53 6a  |......E.Y.V<..Sj|
+000003d0  77 62 a3 1a 8c 55 14 b0  d8 6f dd 1c fb a4 6f 25  |wb...U...o....o%|
+000003e0  18 28 ab 9e a5 ad 6d 97  63 f4 9c                 |.(....m.c..|
 >>> Flow 3 (client to server)
-00000000  14 03 03 00 01 01 17 03  03 00 35 4d ad c5 c7 cc  |..........5M....|
-00000010  5a 34 8a f8 5f 71 83 af  fa 94 df 2a 94 a0 c4 8e  |Z4.._q.....*....|
-00000020  5e 00 f7 02 e1 30 62 a5  49 27 58 0b 1f fa 46 98  |^....0b.I'X...F.|
-00000030  f0 b8 6f 42 e3 3a 7f 26  77 b6 46 8f ab c6 5d d6  |..oB.:.&w.F...].|
-00000040  17 03 03 00 17 90 81 68  7a 48 8d 3b 59 9e 11 6f  |.......hzH.;Y..o|
-00000050  86 b5 24 e4 d9 e0 60 9f  c2 4f 3d 33              |..$...`..O=3|
+00000000  14 03 03 00 01 01 17 03  03 00 35 12 2a a7 31 42  |..........5.*.1B|
+00000010  e9 65 d6 88 9c 49 85 53  16 6c 85 bc d1 70 65 3a  |.e...I.S.l...pe:|
+00000020  aa cd d3 12 ce 69 e3 3a  63 7a 8d ed 54 df 9c 97  |.....i.:cz..T...|
+00000030  4e ef 7c 20 ce 41 ac 33  a9 3b fc 5e 35 34 65 00  |N.| .A.3.;.^54e.|
+00000040  17 03 03 00 17 11 5f 88  3b 45 0e 4e 8a 26 43 a3  |......_.;E.N.&C.|
+00000050  9e 77 10 76 8c e1 ed d3  19 f4 27 5f              |.w.v......'_|
 >>> Flow 4 (server to client)
-00000000  17 03 03 00 16 94 83 fa  cc 66 b4 60 c0 c7 6d b3  |.........f.`..m.|
-00000010  6e 8c 84 9d 89 76 61 3d  69 fd 29                 |n....va=i.)|
+00000000  17 03 03 00 16 7d 92 67  60 95 ba fa a0 5f 03 e9  |.....}.g`...._..|
+00000010  2b e6 53 ed fb 6b 4f b9  e9 09 10                 |+.S..kO....|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 16 60 cb 39  3d 7d 79 01 88 93 bd bf  |.....`.9=}y.....|
-00000010  23 3b d1 f3 a4 5e 78 ea  cd 0f 5e                 |#;...^x...^|
+00000000  17 03 03 00 16 06 17 fb  4b 33 c7 06 d5 a9 40 e8  |........K3....@.|
+00000010  c7 09 65 b2 5c 2d 45 2f  bf 45 a8                 |..e.\-E/.E.|
 >>> Flow 6 (server to client)
-00000000  17 03 03 00 1a 88 13 b4  f1 5f cc 63 1e 99 9f 85  |........._.c....|
-00000010  60 ff 0e 97 13 59 64 2a  c3 0d 2b ac ca a2 25     |`....Yd*..+...%|
+00000000  17 03 03 00 1a 04 5e c0  bb ad 6c 2f 65 61 5c 39  |......^...l/ea\9|
+00000010  a9 e2 c4 9e 0e 4c 68 d2  a9 97 8a bf 95 39 3f     |.....Lh......9?|
 >>> Flow 7 (client to server)
-00000000  17 03 03 00 1d 4f f2 48  ea b8 d6 75 8e 97 ab 54  |.....O.H...u...T|
-00000010  29 57 50 5b 59 40 59 d3  7a 3c 01 43 6a 33 30 bb  |)WP[Y@Y.z<.Cj30.|
-00000020  d4 40 17 03 03 00 13 18  fc b7 ac eb e7 52 6d f0  |.@...........Rm.|
-00000030  d4 d3 03 c6 5f 4e ea e3  7b 4e                    |...._N..{N|
+00000000  17 03 03 00 1d 1f 74 d0  fb ed fa 59 81 21 7e f0  |......t....Y.!~.|
+00000010  41 c8 6e 6b 9f b6 1a 86  ad 2e ac 9e 3d 3b 66 c9  |A.nk........=;f.|
+00000020  4a 87 17 03 03 00 13 7b  76 c4 85 c1 41 47 6d 35  |J......{v...AGm5|
+00000030  98 86 02 d5 3b e4 6b 4c  3e 7a                    |....;.kL>z|
index e6d81184e10c8d8885a1b01ee47dae37fa5d780c..db87bef8a1517e60e028a2614f9c941bfa65934e 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 96 00 05 00 05  01 00 00 00 00 00 0a 00  |................|
 00000090  04 00 02 00 17 00 0b 00  02 01 00 00 0d 00 1a 00  |................|
 000000a0  18 08 04 04 03 08 07 08  05 08 06 04 01 05 01 06  |................|
 00000100  07 9f 6c 4b 5b 83 56 e2  32 42 e9 58 b6 d7 49 a6  |..lK[.V.2B.X..I.|
 00000110  b5 68 1a 41 03 56 6b dc  5a 89                    |.h.A.Vk.Z.|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 9b 02 00 00  97 03 03 b5 3c c8 fe 64  |............<..d|
-00000010  f6 04 7d 28 a4 25 7c 1b  f5 0b e6 6d 0b f5 2f ec  |..}(.%|....m../.|
-00000020  78 c1 bd 5a cf c8 19 d9  5c 54 72 20 00 00 00 00  |x..Z....\Tr ....|
+00000000  16 03 03 00 9b 02 00 00  97 03 03 bb 03 f1 4e 88  |..............N.|
+00000010  23 9e 85 ee 32 13 db 0d  69 11 48 47 c6 c9 e5 b2  |#...2...i.HG....|
+00000020  25 9d 0c 27 87 05 3f 58  42 60 2d 20 00 00 00 00  |%..'..?XB`- ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 01 00 00  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 03 00 00  |................|
 00000050  4f 00 2b 00 02 03 04 00  33 00 45 00 17 00 41 04  |O.+.....3.E...A.|
-00000060  d7 63 55 0e 0d 7b fb 09  a9 61 92 70 2b 52 9c 38  |.cU..{...a.p+R.8|
-00000070  2d e8 2a 68 27 b7 15 3e  4a 1e 92 c8 08 7b 5c c9  |-.*h'..>J....{\.|
-00000080  8d d4 aa 97 63 42 a5 3e  4b e8 7d 37 98 d9 8c a6  |....cB.>K.}7....|
-00000090  e7 c7 45 9f 73 48 bd c3  14 82 67 5b bb 19 bd a5  |..E.sH....g[....|
-000000a0  14 03 03 00 01 01 17 03  03 00 17 67 d9 cb 2b d1  |...........g..+.|
-000000b0  d2 30 7d b3 3f c1 77 5a  6c 87 41 2c 29 83 36 19  |.0}.?.wZl.A,).6.|
-000000c0  74 38 17 03 03 02 6d ac  0c 4f fe b5 93 6a fa 9f  |t8....m..O...j..|
-000000d0  e9 76 a7 c3 8a bb 4a 64  7a 04 35 58 e6 a2 d8 7a  |.v....Jdz.5X...z|
-000000e0  cf 99 1c 60 13 1a ca c6  e6 10 11 7a f1 f4 be ec  |...`.......z....|
-000000f0  1d 2d db b1 a5 3a dd 7e  10 2b 65 ca 40 b2 5f fc  |.-...:.~.+e.@._.|
-00000100  3f c9 df 7d 26 c1 fc b7  2d 67 a1 2d a2 22 b3 40  |?..}&...-g.-.".@|
-00000110  79 d4 c8 b6 73 f7 93 8a  97 4f b7 ab b6 0c ca 14  |y...s....O......|
-00000120  3c 1e 6c 27 c0 be 01 d7  98 ef 93 78 f5 14 15 21  |<.l'.......x...!|
-00000130  4c f8 8e a6 f7 72 b2 b7  bc c2 3e 9b b7 e4 0d 15  |L....r....>.....|
-00000140  b5 69 75 e9 61 10 e4 d5  8e 60 44 88 bf 5f df f9  |.iu.a....`D.._..|
-00000150  8d 70 54 4e f6 0f 37 70  ff b8 6b c0 4f fb 61 c1  |.pTN..7p..k.O.a.|
-00000160  48 00 96 9b da 05 0f 78  7a 87 f5 b1 69 f6 4f 8e  |H......xz...i.O.|
-00000170  80 74 7b e0 e5 b7 0f ba  7d 9d 4c ff c9 d7 7c b9  |.t{.....}.L...|.|
-00000180  f0 bd dd 34 8e 77 5f 3b  48 10 10 6f ed c7 84 15  |...4.w_;H..o....|
-00000190  7a 0c 26 3e 5d 9d 58 07  02 8c e3 fa f0 6b 86 df  |z.&>].X......k..|
-000001a0  76 af 3c 13 c4 93 28 7a  17 04 98 91 26 72 5f aa  |v.<...(z....&r_.|
-000001b0  cf b2 9e 37 a9 93 12 bd  1d 92 64 b8 82 60 b0 b5  |...7......d..`..|
-000001c0  1d 2c 4e 18 24 11 3b 52  33 05 f0 3b f2 27 ed a6  |.,N.$.;R3..;.'..|
-000001d0  f6 4a 82 b6 df 05 a0 07  a3 9d 73 0a 3c 7f 02 47  |.J........s.<..G|
-000001e0  60 c8 aa 20 b4 9c cd 48  12 a3 82 fe 99 4e 0c bb  |`.. ...H.....N..|
-000001f0  ec 4f 10 75 26 99 a4 ed  5e 4a 34 51 38 88 2c 3c  |.O.u&...^J4Q8.,<|
-00000200  0b 8d f8 65 84 38 47 c8  31 30 82 71 3f 54 e3 3f  |...e.8G.10.q?T.?|
-00000210  f1 e6 2c ef a3 fe 02 34  16 58 21 55 6e 0f 95 d3  |..,....4.X!Un...|
-00000220  3e 18 e5 c4 fa 95 65 07  d8 4b 31 4b fa a7 85 74  |>.....e..K1K...t|
-00000230  6c 1c a3 7c 7b c6 20 e0  1f 28 33 6d 61 93 d0 7d  |l..|{. ..(3ma..}|
-00000240  e7 c4 5c 27 c9 d9 ca f9  fe 21 6f 7f 05 34 37 54  |..\'.....!o..47T|
-00000250  30 59 68 e1 04 36 60 52  d7 fc 4f 8c 67 f6 42 88  |0Yh..6`R..O.g.B.|
-00000260  bc 41 5f 8e 2c 05 dd 6a  b0 49 6c d8 8e 9c 9e 06  |.A_.,..j.Il.....|
-00000270  35 f9 f1 33 f2 54 b0 3f  9e bd 4f c7 48 aa a3 9e  |5..3.T.?..O.H...|
-00000280  fe 69 79 16 e0 5a ca 48  72 fe 52 4a f1 6f f1 e0  |.iy..Z.Hr.RJ.o..|
-00000290  8c fe 16 15 ce c9 87 dc  9b 66 4d 3a bb 05 21 82  |.........fM:..!.|
-000002a0  21 65 cb 7b da 06 1a 0b  53 ee 60 e4 79 0f bc 5d  |!e.{....S.`.y..]|
-000002b0  b6 52 fd 3b 33 28 97 6c  67 d7 ab 3d b0 da bb ac  |.R.;3(.lg..=....|
-000002c0  0d d9 06 81 a3 6c 1f ad  b8 05 20 63 2b c7 cb 4b  |.....l.... c+..K|
-000002d0  e2 96 6e 3d f1 9c 0a 6a  c6 01 3e 3a d0 54 c8 09  |..n=...j..>:.T..|
-000002e0  9b 17 a0 cc d6 d0 82 d1  02 a8 eb 9d 91 7e 30 b9  |.............~0.|
-000002f0  3d 5e 6d 43 fc 50 f8 9f  80 67 7a e3 33 30 cd b7  |=^mC.P...gz.30..|
-00000300  00 b3 bc 17 50 82 6c 80  67 bd c4 12 11 b1 53 22  |....P.l.g.....S"|
-00000310  96 67 07 90 d4 54 5c f1  5d ca cd f8 b5 35 94 e0  |.g...T\.]....5..|
-00000320  21 e6 58 d7 b0 32 ca 24  90 11 30 f5 2b 1d ca 3d  |!.X..2.$..0.+..=|
-00000330  6a 6d 35 fa 17 03 03 00  99 ad ab 79 79 28 a0 a9  |jm5........yy(..|
-00000340  9a cd 6d 8d 8c 92 2e 83  3d d4 be c7 50 61 f5 49  |..m.....=...Pa.I|
-00000350  97 6c ab 92 d4 a7 1a 6f  fc 5b dd 6e 73 0d bd d2  |.l.....o.[.ns...|
-00000360  09 52 9f c9 de bb 8d 09  0a 4f e0 c5 9a 08 79 4c  |.R.......O....yL|
-00000370  fc 01 b3 94 45 f6 1d bd  8d 23 62 14 14 65 4c 2a  |....E....#b..eL*|
-00000380  d9 ad 8f 76 5a 5e 9d da  68 37 c7 b1 54 1e b4 bd  |...vZ^..h7..T...|
-00000390  d3 15 b8 89 94 87 8b 17  17 0f 4c dc db a8 3b 2f  |..........L...;/|
-000003a0  e5 e2 25 d6 ec f6 f4 bb  ab d0 c5 7f 2a cb c6 57  |..%.........*..W|
-000003b0  84 50 3a e7 62 8b 76 ae  6a 06 6b 85 1c 23 f1 d1  |.P:.b.v.j.k..#..|
-000003c0  10 e2 6f 57 8c 20 7d da  2d f8 bc c5 df 4e 7c 22  |..oW. }.-....N|"|
-000003d0  d8 36 17 03 03 00 35 62  fa d4 65 7f 9a 97 5b ec  |.6....5b..e...[.|
-000003e0  25 4a 3a 43 18 08 08 fb  7f 9d 3b 73 64 9e f3 7a  |%J:C......;sd..z|
-000003f0  28 f1 a0 0e 00 7a 51 74  0e 6b 90 c6 39 7a 09 98  |(....zQt.k..9z..|
-00000400  6e d8 63 cc 1f f0 8f bc  37 66 27 a0              |n.c.....7f'.|
+00000060  85 3c 83 1b e5 02 e9 0d  89 cc c0 f7 af 1e ba af  |.<..............|
+00000070  de ad cb 8f 4d 58 04 40  c2 60 e9 41 8b 94 26 76  |....MX.@.`.A..&v|
+00000080  73 64 c3 27 e3 51 9d 5f  21 97 59 a3 02 cc 20 61  |sd.'.Q._!.Y... a|
+00000090  b7 ef cb bb d9 31 b6 b7  b1 77 ea 8d 69 13 13 48  |.....1...w..i..H|
+000000a0  14 03 03 00 01 01 17 03  03 00 17 ab ac 2e 62 de  |..............b.|
+000000b0  b6 f4 c7 35 cf b4 75 fc  a4 a5 2c 40 68 f5 48 80  |...5..u...,@h.H.|
+000000c0  d2 8b 17 03 03 02 6d a9  36 b5 10 78 1f af 79 65  |......m.6..x..ye|
+000000d0  dd ee 36 08 b9 96 e2 bf  09 53 c7 ee 12 19 1b de  |..6......S......|
+000000e0  96 25 cb a7 55 71 28 22  16 3f 4b 3e 15 a2 2e 57  |.%..Uq(".?K>...W|
+000000f0  99 85 28 b2 01 16 3a 75  ff 5e 21 39 6c be fc bd  |..(...:u.^!9l...|
+00000100  24 33 ec c7 50 83 49 91  8a ed 43 38 b5 48 cd 92  |$3..P.I...C8.H..|
+00000110  dd 9a f1 b7 90 61 3b 8f  ff b9 cf 97 3d 8e 23 8e  |.....a;.....=.#.|
+00000120  d1 78 52 b4 ba a1 75 97  32 52 e3 1f c8 43 ca b7  |.xR...u.2R...C..|
+00000130  89 46 e6 30 c2 c5 32 b3  5f a8 ea ea e2 31 d2 41  |.F.0..2._....1.A|
+00000140  23 5e 64 a2 b9 23 27 73  b2 df 77 cd 04 8b dd 37  |#^d..#'s..w....7|
+00000150  a5 77 df 0e 4f 9d 01 22  7b be 7a 0c 18 5c 8b 62  |.w..O.."{.z..\.b|
+00000160  7c 6b 7e a7 54 8c 69 97  50 d7 cf a0 a4 cb 3a 3b  ||k~.T.i.P.....:;|
+00000170  76 7b 0a de 80 d1 40 c3  05 5e b3 4e 71 cd 03 82  |v{....@..^.Nq...|
+00000180  d5 95 d0 38 ab 65 83 24  66 d2 31 2d 9e 58 16 87  |...8.e.$f.1-.X..|
+00000190  b8 ab 4c 4e 75 40 7e 3d  33 2f f4 ed 0b a8 11 1c  |..LNu@~=3/......|
+000001a0  7a a4 b0 e3 6a 73 d0 6e  e6 82 39 c1 cf 57 a4 9a  |z...js.n..9..W..|
+000001b0  8b fc bc 8e e8 6a c3 e1  b0 64 18 55 6d 19 30 25  |.....j...d.Um.0%|
+000001c0  34 f8 b1 ef cf 3c 04 08  69 10 ad 08 67 5b 8d 64  |4....<..i...g[.d|
+000001d0  eb 83 72 39 2e 56 e4 d2  e9 f2 da 40 3e 85 29 ab  |..r9.V.....@>.).|
+000001e0  5b 83 e5 b0 d2 9b eb c3  99 6e 2a f3 78 95 d4 7a  |[........n*.x..z|
+000001f0  7f bf 9c 16 55 77 43 4d  67 f7 4a 6f 40 27 a2 82  |....UwCMg.Jo@'..|
+00000200  b9 86 05 5d 90 e2 52 a2  d4 7c 7b 3e da 30 c1 aa  |...]..R..|{>.0..|
+00000210  30 2e 9a 34 c5 59 dd db  e9 25 67 da 22 47 f2 be  |0..4.Y...%g."G..|
+00000220  cc c8 5a 4e da cf ad 86  8d bd b0 68 26 69 ea 3a  |..ZN.......h&i.:|
+00000230  1c 1e 29 ae e1 09 63 88  f0 81 31 f9 70 a7 92 27  |..)...c...1.p..'|
+00000240  32 9e 3b 6f 09 5e 42 20  53 88 bf 09 8b a8 17 5c  |2.;o.^B S......\|
+00000250  24 7c 18 1f 9c 99 9b db  6d 11 26 8e 92 2c a1 b4  |$|......m.&..,..|
+00000260  5c 9f d9 0a a8 af 25 f7  84 f5 65 d1 b1 6c d8 aa  |\.....%...e..l..|
+00000270  49 c7 a6 13 47 2e 55 f4  2e de 3d 43 c1 15 8d 60  |I...G.U...=C...`|
+00000280  c1 27 59 7e 7b 14 ee 54  09 fc 99 79 c9 bf fb 45  |.'Y~{..T...y...E|
+00000290  2d 32 ed 1a 2c 84 bc f4  a2 b5 5f 4e cf 60 29 91  |-2..,....._N.`).|
+000002a0  90 b6 ab 06 8f 2d 43 a5  a5 54 0d 67 52 c2 1c fb  |.....-C..T.gR...|
+000002b0  f3 41 b7 67 b4 50 05 86  19 75 93 8b 6c c3 bf 08  |.A.g.P...u..l...|
+000002c0  64 f2 df ff 37 6d 2f 1e  3a 28 f4 ba 27 8d 61 d5  |d...7m/.:(..'.a.|
+000002d0  79 70 19 82 99 7a e5 68  f3 c1 23 da 5d e1 98 b2  |yp...z.h..#.]...|
+000002e0  69 ca 42 83 61 29 3f d9  20 51 f2 a9 ea 1c 0b 5a  |i.B.a)?. Q.....Z|
+000002f0  20 b0 af 70 cc c5 ad 72  6b 09 85 56 8a 26 86 cf  | ..p...rk..V.&..|
+00000300  4e 9a 56 97 5d 63 8d 1d  46 04 48 16 c9 1e 91 47  |N.V.]c..F.H....G|
+00000310  74 53 28 51 7e 3c 84 a1  50 d6 f3 ac 31 ce 04 18  |tS(Q~<..P...1...|
+00000320  81 38 0d c5 3d f5 d5 04  2f f0 96 9b 73 49 4c d6  |.8..=.../...sIL.|
+00000330  89 d9 b9 be 17 03 03 00  99 3a 37 ed 2d 98 80 f9  |.........:7.-...|
+00000340  d0 04 14 12 8c 63 45 cc  8d cb 29 5f 0e f0 86 ef  |.....cE...)_....|
+00000350  8d 6c d6 0f ef 66 99 91  e8 8c d7 7b 21 07 7e 96  |.l...f.....{!.~.|
+00000360  84 f8 f9 5b 1b 39 8b 4f  16 ec 5c 69 7b 18 09 5d  |...[.9.O..\i{..]|
+00000370  95 f1 f3 73 4b 8f 84 66  ee 61 85 dd fe ea 36 df  |...sK..f.a....6.|
+00000380  e5 2a 71 ec 2d 7e 47 1c  b7 79 2d 87 f8 dc 44 27  |.*q.-~G..y-...D'|
+00000390  8a f1 13 6e df ca 59 79  9b 18 01 7e 31 bd 44 f7  |...n..Yy...~1.D.|
+000003a0  8d ad 1c 97 e7 e1 b9 a6  17 d1 25 d1 b8 0d 04 bb  |..........%.....|
+000003b0  21 a4 08 db a2 08 87 5c  04 9a 11 fa c6 24 db 20  |!......\.....$. |
+000003c0  42 79 9c 97 dd 6c d2 e7  24 b4 79 47 be f3 43 87  |By...l..$.yG..C.|
+000003d0  0f 95 17 03 03 00 35 9e  7d 12 0e d6 0a e6 af a3  |......5.}.......|
+000003e0  83 dd eb 08 73 2d 43 7e  81 85 51 4c d1 ad d0 77  |....s-C~..QL...w|
+000003f0  8d 28 62 44 41 9c b0 e9  93 d7 3d 07 e4 e1 6e 4c  |.(bDA.....=...nL|
+00000400  a8 5b 4a 3f 58 3f 97 07  73 d7 5a 62              |.[J?X?..s.Zb|
 >>> Flow 3 (client to server)
-00000000  14 03 03 00 01 01 17 03  03 00 35 ba 59 57 3e a3  |..........5.YW>.|
-00000010  cd 02 7f 7c c2 16 f5 6b  ec 42 66 aa a2 7a 3d 47  |...|...k.Bf..z=G|
-00000020  43 c9 02 4b a3 72 d0 4d  fa f8 32 28 1a 19 16 6a  |C..K.r.M..2(...j|
-00000030  7c 0e 4a 75 80 94 34 fe  30 7b d0 52 15 48 10 30  ||.Ju..4.0{.R.H.0|
-00000040  17 03 03 00 17 5d de 53  df 00 21 ca 6d 69 ff 45  |.....].S..!.mi.E|
-00000050  2e 53 57 db 3f 8d d8 6c  5a e1 f8 cc 17 03 03 00  |.SW.?..lZ.......|
-00000060  13 43 d9 94 95 41 af 1d  80 a7 f2 28 2a 44 50 8d  |.C...A.....(*DP.|
-00000070  41 8f 82 09                                       |A...|
+00000000  14 03 03 00 01 01 17 03  03 00 35 df 31 1a 84 e2  |..........5.1...|
+00000010  93 54 01 f2 d1 e8 32 6c  32 91 e5 64 86 68 ad 5f  |.T....2l2..d.h._|
+00000020  aa 24 54 86 b2 39 92 24  06 65 5c 06 67 43 7d 09  |.$T..9.$.e\.gC}.|
+00000030  79 78 c6 f3 cf 6c a9 ec  38 e3 ec 81 c4 9b c5 33  |yx...l..8......3|
+00000040  17 03 03 00 17 25 ed 98  67 8f ad e8 60 ce 5b ad  |.....%..g...`.[.|
+00000050  ab 3e 67 64 e3 8d bf 98  96 a2 3d 99 17 03 03 00  |.>gd......=.....|
+00000060  13 9d 28 f2 24 fe d6 11  b0 64 d6 8a 8d c1 81 e0  |..(.$....d......|
+00000070  17 d5 a0 f3                                       |....|
index 4e3eb760e690669c07f6c9132b24769a9ae92e42..4a43382da58fc9084c4b1901eec7a33cb4f0495d 100644 (file)
@@ -3,10 +3,10 @@
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000020  00 00 00 00 00 00 00 00  00 00 00 20 00 00 00 00  |........... ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a8  |.............2..|
-00000050  cc a9 c0 2f c0 2b c0 30  c0 2c c0 27 c0 13 c0 23  |.../.+.0.,.'...#|
-00000060  c0 09 c0 14 c0 0a 00 9c  00 9d 00 3c 00 2f 00 35  |...........<./.5|
-00000070  c0 12 00 0a 00 05 c0 11  c0 07 13 01 13 03 13 02  |................|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 32 cc a9  |.............2..|
+00000050  cc a8 c0 2b c0 2f c0 2c  c0 30 c0 09 c0 13 c0 0a  |...+./.,.0......|
+00000060  c0 14 00 9c 00 9d 00 2f  00 35 c0 12 00 0a c0 23  |......./.5.....#|
+00000070  c0 27 00 3c c0 07 c0 11  00 05 13 03 13 01 13 02  |.'.<............|
 00000080  01 00 00 75 00 05 00 05  01 00 00 00 00 00 0a 00  |...u............|
 00000090  04 00 02 00 1d 00 0b 00  02 01 00 00 0d 00 1a 00  |................|
 000000a0  18 08 04 04 03 08 07 08  05 08 06 04 01 05 01 06  |................|
 000000e0  43 15 28 da ac 5f bb 29  07 30 ff f6 84 af c4 cf  |C.(.._.).0......|
 000000f0  c2 ed 90 99 5f 58 cb 3b  74                       |...._X.;t|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 7a 02 00 00  76 03 03 5d 2e e6 ba 34  |....z...v..]...4|
-00000010  6c 42 bb 48 58 fe c5 f0  95 f9 34 11 04 b5 2a f4  |lB.HX.....4...*.|
-00000020  f1 16 41 db 14 a0 19 d8  43 7c 09 20 00 00 00 00  |..A.....C|. ....|
+00000000  16 03 03 00 7a 02 00 00  76 03 03 eb 1b 4e e5 65  |....z...v....N.e|
+00000010  54 ab 07 68 1c d9 32 0f  0e c2 ae a3 2a 89 37 50  |T..h..2.....*.7P|
+00000020  23 51 61 7d 68 60 34 0d  40 2f b8 20 00 00 00 00  |#Qa}h`4.@/. ....|
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 01 00 00  |................|
-00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 82  |..+.....3.$... .|
-00000060  de 1b d1 83 7a e1 46 cc  c7 36 15 62 48 07 6b f6  |....z.F..6.bH.k.|
-00000070  eb 0a 53 a3 34 cd 34 ee  cc 0c d0 c9 02 d5 38 14  |..S.4.4.......8.|
-00000080  03 03 00 01 01 17 03 03  00 17 3d 0c 61 12 1b 55  |..........=.a..U|
-00000090  6e f4 13 59 c8 4a e7 12  63 5d bf be 34 9f d7 2a  |n..Y.J..c]..4..*|
-000000a0  c2 17 03 03 02 6d 82 e8  43 93 e4 80 4d a7 d2 cf  |.....m..C...M...|
-000000b0  43 9d 71 8d cc 78 e8 e9  58 7e 28 53 57 6d 95 1e  |C.q..x..X~(SWm..|
-000000c0  fb 98 05 ec 66 47 d9 a1  6a b5 f4 28 09 4a 6c 4c  |....fG..j..(.JlL|
-000000d0  ee a0 1a 86 e7 29 c0 0e  d8 e0 ca 2d bb 50 e4 34  |.....).....-.P.4|
-000000e0  8d 66 be 54 b5 df 94 fc  69 0e a6 9a 76 8b 8f f5  |.f.T....i...v...|
-000000f0  a9 01 1a 1d 8d b0 ae a9  0c 10 58 13 f9 91 80 43  |..........X....C|
-00000100  69 f8 3f 03 14 8e 73 1a  ce 52 72 86 3d 60 8b 0f  |i.?...s..Rr.=`..|
-00000110  38 e7 4b 43 f0 b3 4b 12  3a a7 cd 4b ac ef 7d fb  |8.KC..K.:..K..}.|
-00000120  27 3a 38 36 ad a5 90 eb  57 80 47 99 bc c6 58 55  |':86....W.G...XU|
-00000130  15 6f 53 f7 83 ca 2b 89  ae be 23 9a 83 3c 6b b1  |.oS...+...#..<k.|
-00000140  10 67 a2 c4 65 e0 3a 25  05 4a 5b dc 10 96 93 b8  |.g..e.:%.J[.....|
-00000150  72 7b 1f 07 6d c7 48 c4  86 b5 a5 cd bf 6f d4 98  |r{..m.H......o..|
-00000160  bc 71 5b 39 36 67 9b 1a  88 a1 74 c4 7d 34 7c 1b  |.q[96g....t.}4|.|
-00000170  a7 31 c1 04 77 b7 cd 30  8e 69 6c 99 c4 9f 0b b8  |.1..w..0.il.....|
-00000180  e4 53 03 b9 86 12 61 b0  fe 0e 37 df 99 77 00 3f  |.S....a...7..w.?|
-00000190  d4 10 c9 73 eb a2 9a 00  d6 cd 6a 5e 67 ec 55 ca  |...s......j^g.U.|
-000001a0  26 89 2f 11 9d 30 8f bd  5a 68 55 20 f5 93 44 5e  |&./..0..ZhU ..D^|
-000001b0  1f f2 24 20 fa 80 94 c7  01 62 c2 95 d3 18 c6 2c  |..$ .....b.....,|
-000001c0  00 42 fa ee 32 75 27 5f  df 81 f2 14 83 30 cd 25  |.B..2u'_.....0.%|
-000001d0  1d 6c 3a c5 f5 3f 6e b7  6a f0 cf 02 f9 a3 8d da  |.l:..?n.j.......|
-000001e0  96 55 31 2c 3c ef 62 c0  19 ac 36 f3 89 44 a4 a4  |.U1,<.b...6..D..|
-000001f0  60 c3 99 b5 db 9f c7 4c  9d fb f1 77 98 dc 90 0e  |`......L...w....|
-00000200  8a e2 0e e2 6a 25 6e 84  2b d6 dc 73 57 7a 6e 1d  |....j%n.+..sWzn.|
-00000210  41 2e d0 de 45 ab 49 f0  e3 64 e4 6a 02 fa 64 6f  |A...E.I..d.j..do|
-00000220  09 22 05 b5 0c 12 b0 57  e2 61 5a 63 b1 4c a4 e5  |.".....W.aZc.L..|
-00000230  79 c4 42 17 36 f0 0c 43  04 a5 d7 7c 3f 59 17 38  |y.B.6..C...|?Y.8|
-00000240  f0 f1 2c 2d be 6c 4e 58  e5 45 c9 c2 d6 df 7b b3  |..,-.lNX.E....{.|
-00000250  08 50 db e6 a8 ae 73 f2  82 09 6e 58 07 d3 87 e4  |.P....s...nX....|
-00000260  c2 70 c6 8f 8f 13 74 09  b1 7d 1a 42 e1 d1 72 41  |.p....t..}.B..rA|
-00000270  bd 71 cc f4 6c 7f 70 a2  99 95 34 b7 2c 08 af 43  |.q..l.p...4.,..C|
-00000280  43 ec 61 66 51 73 e2 87  b3 f3 ef ee 20 f2 55 58  |C.afQs...... .UX|
-00000290  c7 1a 0c ad dd 7b 44 9f  f1 ff 5e 2b 18 63 e1 45  |.....{D...^+.c.E|
-000002a0  88 5d c1 ce cb dc 42 ec  10 03 d4 d7 ae 2f ed ce  |.]....B....../..|
-000002b0  49 01 e3 1e de b0 68 ce  25 e0 69 b1 33 37 3d 0f  |I.....h.%.i.37=.|
-000002c0  b6 96 7e cd 7e 91 fb 82  a2 b8 66 6b 9a 44 83 c7  |..~.~.....fk.D..|
-000002d0  56 86 87 a5 f2 b1 06 16  a3 43 e1 29 fe f7 26 c9  |V........C.)..&.|
-000002e0  39 ea a4 b0 62 7b d5 9e  8a 0f 89 07 f9 a0 fc 45  |9...b{.........E|
-000002f0  bf ce 70 1d 75 7f fa db  2a 5b 32 02 bb 69 cc 72  |..p.u...*[2..i.r|
-00000300  cf 24 3d 92 20 d9 2f ee  a5 9d 72 33 23 f5 99 f5  |.$=. ./...r3#...|
-00000310  b1 82 eb 17 03 03 00 99  01 f0 87 1b 28 83 73 0f  |............(.s.|
-00000320  67 c8 76 69 e7 e6 ae d4  5c fc e0 e7 1c 6b 85 de  |g.vi....\....k..|
-00000330  de a0 9e 6c 1a 7d 90 31  d8 63 92 a1 bc f3 47 54  |...l.}.1.c....GT|
-00000340  c4 00 b9 62 30 db 1d 5b  c9 d5 e5 58 67 5e ab 68  |...b0..[...Xg^.h|
-00000350  3a 41 65 11 8d 9b a2 8c  4f e7 b7 76 ca c6 ca 2e  |:Ae.....O..v....|
-00000360  2d 6b 7b d1 90 41 9f 0c  c6 a5 18 4d d2 99 49 0b  |-k{..A.....M..I.|
-00000370  24 ab c5 84 cd a1 79 0a  0f 48 f3 f6 a4 f3 44 f3  |$.....y..H....D.|
-00000380  42 cb eb 6d 7d 16 b8 42  43 37 78 d9 e3 47 ce ee  |B..m}..BC7x..G..|
-00000390  c9 4b 3d 4f 47 ab 77 15  45 59 dd 31 02 f9 f8 60  |.K=OG.w.EY.1...`|
-000003a0  41 c6 dc e2 e3 25 8f 43  dd 77 c4 ce ba b9 63 c7  |A....%.C.w....c.|
-000003b0  5e 17 03 03 00 35 2a d8  c8 91 25 bb 27 c2 fc cd  |^....5*...%.'...|
-000003c0  b3 d0 c2 57 70 39 fc 81  d7 11 01 6c 72 ca 58 19  |...Wp9.....lr.X.|
-000003d0  c1 5d 72 9e 72 dc 70 2a  3d 1f 35 1c 05 4f 51 26  |.]r.r.p*=.5..OQ&|
-000003e0  30 72 97 a5 7a 7a 0a 7b  9e 91 03                 |0r..zz.{...|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 13 03 00 00  |................|
+00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 17  |..+.....3.$... .|
+00000060  7d df 14 8a ad 43 51 c3  c2 08 3a ea f7 e3 96 6a  |}....CQ...:....j|
+00000070  b7 8b 61 66 d9 82 c5 7b  b9 77 bc 62 6a 19 04 14  |..af...{.w.bj...|
+00000080  03 03 00 01 01 17 03 03  00 17 4e 7b b6 d1 b1 19  |..........N{....|
+00000090  0d 0c d0 d3 5a 66 44 5c  81 49 74 f3 71 3b 97 5e  |....ZfD\.It.q;.^|
+000000a0  ee 17 03 03 02 6d 00 17  b1 4d b9 f5 fc ea 48 72  |.....m...M....Hr|
+000000b0  aa a5 1c 8b fe 97 08 54  ab 2d 0a 0e f7 51 41 bf  |.......T.-...QA.|
+000000c0  7b 14 ba b7 d9 0a 30 44  db b9 06 e7 6b a9 0a 94  |{.....0D....k...|
+000000d0  49 a2 29 50 f2 7f 7e 68  91 41 ad a9 cb ee e2 bd  |I.)P..~h.A......|
+000000e0  03 fd 95 79 ea c3 77 ee  88 3b 7a 81 15 9f 17 96  |...y..w..;z.....|
+000000f0  b2 db b9 f3 26 dd 75 69  ef 12 c0 63 b0 04 63 ae  |....&.ui...c..c.|
+00000100  aa b3 67 f8 7f a5 17 cf  56 5f ee 34 2d d7 83 23  |..g.....V_.4-..#|
+00000110  84 00 4b 94 1a 76 2a 01  ce 49 0a 57 7d c8 65 7a  |..K..v*..I.W}.ez|
+00000120  d7 16 34 1c a8 37 fd 71  d4 79 08 b1 44 9f 9e a7  |..4..7.q.y..D...|
+00000130  78 ab 9d 0d c4 80 0e 81  35 75 23 59 89 1b 2c d3  |x.......5u#Y..,.|
+00000140  bc c9 86 b9 7b 22 19 30  dd cc 68 93 ab d2 98 dd  |....{".0..h.....|
+00000150  c2 9f 20 af c9 1a 87 b3  28 73 84 83 ca 98 1d 60  |.. .....(s.....`|
+00000160  df 12 19 70 80 f2 ff 20  64 b5 8c ef e2 e8 6a 5a  |...p... d.....jZ|
+00000170  df 8e ba 95 d8 2c c4 b6  4f a1 33 8c 8d a3 fc d3  |.....,..O.3.....|
+00000180  c4 4b ba b2 6d 3a f7 da  38 23 5f 03 a7 92 13 76  |.K..m:..8#_....v|
+00000190  12 73 26 17 30 e0 21 f1  16 8f a1 e5 6d f0 21 a8  |.s&.0.!.....m.!.|
+000001a0  c6 25 64 86 95 5e 6f 4d  21 f0 f3 a3 27 23 2b 4b  |.%d..^oM!...'#+K|
+000001b0  90 03 ba 6c ce 9c 20 ed  69 15 76 cb 39 bc fd 44  |...l.. .i.v.9..D|
+000001c0  10 b4 72 d5 44 9d f7 eb  a4 b0 d5 07 20 a1 6b 71  |..r.D....... .kq|
+000001d0  16 e4 f7 8f a0 d8 fa 86  db e6 ef eb 63 41 a0 17  |............cA..|
+000001e0  83 71 0d 1c 4b ec 58 c3  90 9c ea 34 79 a7 91 43  |.q..K.X....4y..C|
+000001f0  ad 3d ff 28 c8 b4 3e 7a  b6 83 53 f4 99 0b 86 bc  |.=.(..>z..S.....|
+00000200  f2 cf ae 1d a7 5c 7f 57  d9 85 95 25 33 bb 4d 79  |.....\.W...%3.My|
+00000210  25 2e 54 6d 5d 14 32 68  7d 6e 45 bd b1 e1 24 30  |%.Tm].2h}nE...$0|
+00000220  c2 1c 45 b9 a2 42 ae b5  c6 6a 56 f9 8a 12 51 f9  |..E..B...jV...Q.|
+00000230  61 a2 9d 56 98 09 8d ea  70 17 48 d8 23 48 ca 18  |a..V....p.H.#H..|
+00000240  43 1e a2 bc 88 69 3d 45  95 89 cc f0 74 8d 88 36  |C....i=E....t..6|
+00000250  5e a8 1b be 88 41 35 8d  de a9 20 23 f3 5e ab c9  |^....A5... #.^..|
+00000260  61 22 2e 86 54 2f c4 4a  60 04 c2 e3 b8 cf 1a 41  |a"..T/.J`......A|
+00000270  a6 31 ab 7a b5 07 dc 54  82 89 b1 1f 9f 62 98 bc  |.1.z...T.....b..|
+00000280  bd 39 be 23 ed d5 bc 0d  8e a6 69 14 26 39 fe ed  |.9.#......i.&9..|
+00000290  98 c8 48 36 6c 8e 9f 93  57 7a ba 33 03 35 c6 de  |..H6l...Wz.3.5..|
+000002a0  55 03 63 e8 a4 53 08 0a  b0 a7 3e a3 cb f2 df 3d  |U.c..S....>....=|
+000002b0  cd 59 df ee f6 45 2d 77  39 32 4a 1f 08 21 e7 db  |.Y...E-w92J..!..|
+000002c0  52 2a 06 86 e6 00 98 ca  9f a3 ad 0f 7f d3 25 6d  |R*............%m|
+000002d0  56 58 21 e2 39 59 56 15  74 4d 18 37 f5 40 29 db  |VX!.9YV.tM.7.@).|
+000002e0  de be 49 77 e0 2c 5c 6b  ee b1 bd 4a ea 2a 07 94  |..Iw.,\k...J.*..|
+000002f0  0f 21 7c bb 1f bd 3e ad  9e b6 95 7d 16 e8 f0 4e  |.!|...>....}...N|
+00000300  de e2 ca 9c 34 9f b8 e5  57 d5 b7 b5 8d 60 dd c2  |....4...W....`..|
+00000310  ce 47 2c 17 03 03 00 99  37 37 20 49 98 44 f6 b4  |.G,.....77 I.D..|
+00000320  58 54 ff 5e b0 05 22 8e  c6 68 9a ae 49 51 e9 f1  |XT.^.."..h..IQ..|
+00000330  71 75 cf 1a 79 da 33 f1  5f 7e a1 02 81 05 12 8b  |qu..y.3._~......|
+00000340  a3 a8 ad 87 ee f0 87 da  f1 16 80 9d 2e fa 5a 22  |..............Z"|
+00000350  a5 f5 b9 14 f5 8f 9b 35  87 ba 1a f7 c4 17 c8 f6  |.......5........|
+00000360  a1 1e 28 cd fe 03 90 9f  f0 81 d3 80 bb 4c 1a b1  |..(..........L..|
+00000370  c6 11 de 19 a1 5a 3c 73  77 f0 70 b8 d1 38 16 f3  |.....Z<sw.p..8..|
+00000380  64 d0 8e 9c fe 4d 83 48  dc 20 78 db 6a 65 3f f4  |d....M.H. x.je?.|
+00000390  0f a0 70 cc 30 bb cd 86  51 0c 20 ea 59 a5 ed e8  |..p.0...Q. .Y...|
+000003a0  72 d9 5e f3 c3 41 0b 19  f3 97 0f fc 77 42 6d 15  |r.^..A......wBm.|
+000003b0  92 17 03 03 00 35 ac 97  30 a0 8a d8 d2 e6 4a 5b  |.....5..0.....J[|
+000003c0  f5 58 32 22 63 8e 36 2e  21 a2 30 33 ae 49 55 76  |.X2"c.6.!.03.IUv|
+000003d0  cf c8 b3 3f 82 8d c3 0e  ea 22 ec 8f 65 c8 c4 0d  |...?....."..e...|
+000003e0  bf cc 6a 86 e9 32 50 db  02 93 ec                 |..j..2P....|
 >>> Flow 3 (client to server)
-00000000  14 03 03 00 01 01 17 03  03 00 35 7d 5e 95 38 a2  |..........5}^.8.|
-00000010  d3 f4 04 59 57 2a 1a 86  ac 12 8e 17 88 fb 52 25  |...YW*........R%|
-00000020  1d 19 2c c5 ac 57 c9 bf  af 07 e7 c1 4d f3 dd f0  |..,..W......M...|
-00000030  13 ad a1 73 07 32 a4 c5  7c 9e ad 5a 88 59 57 4b  |...s.2..|..Z.YWK|
-00000040  17 03 03 00 17 e2 65 4f  bd 1f bb 00 a1 6b ae a4  |......eO.....k..|
-00000050  9d d3 d2 6e 7b 62 b5 09  19 d6 8f 1b 17 03 03 00  |...n{b..........|
-00000060  13 96 de 94 2b a7 bb c5  4b 7e 02 b2 27 07 4d 49  |....+...K~..'.MI|
-00000070  32 2b 83 48                                       |2+.H|
+00000000  14 03 03 00 01 01 17 03  03 00 35 e5 27 80 72 fd  |..........5.'.r.|
+00000010  6c 0d b5 a7 14 23 08 0b  f5 54 70 8c 29 61 d0 2a  |l....#...Tp.)a.*|
+00000020  81 2d 05 83 2a 21 1e 16  94 5b 65 0d 6a ca b6 81  |.-..*!...[e.j...|
+00000030  d9 9d 3c 5c 9c fe 2b 01  a8 3b 23 fb 9e eb 2c 56  |..<\..+..;#...,V|
+00000040  17 03 03 00 17 79 fd 43  29 72 96 e0 ad fd 7e 60  |.....y.C)r....~`|
+00000050  94 51 8d 8a 6e 6a 5d 6c  f3 0d 4b 74 17 03 03 00  |.Q..nj]l..Kt....|
+00000060  13 a4 7c e1 31 71 61 82  e7 7d 28 0f 63 d7 ae 76  |..|.1qa..}(.c..v|
+00000070  9c 71 37 cd                                       |.q7.|
index a5d9ee4cdbd7b667a90925f7b8e71e662a351fa3..cb3b8da8235e9a7cdc4385067d4f9c5b1340a6f9 100644 (file)
@@ -1,11 +1,11 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 63 01 00 00  5f 03 01 7a df fa af 20  |....c..._..z... |
-00000010  74 5a 83 3b 91 95 b4 9b  57 d8 6b f2 88 2a 68 e8  |tZ.;....W.k..*h.|
-00000020  b8 9e e7 88 a6 c5 e7 59  08 ff 9b 00 00 12 c0 0a  |.......Y........|
-00000030  c0 14 00 39 c0 09 c0 13  00 33 00 35 00 2f 00 ff  |...9.....3.5./..|
-00000040  01 00 00 24 00 0b 00 04  03 00 01 02 00 0a 00 0c  |...$............|
-00000050  00 0a 00 1d 00 17 00 1e  00 19 00 18 00 23 00 00  |.............#..|
-00000060  00 16 00 00 00 17 00 00                           |........|
+00000000  16 03 01 00 67 01 00 00  63 03 01 41 69 16 b5 d5  |....g...c..Ai...|
+00000010  c2 9d 36 2b 95 8e e5 41  9b 92 82 27 2a cc 4e 6e  |..6+...A...'*.Nn|
+00000020  5d f1 1b 58 49 3c 95 1d  8b 61 35 00 00 04 c0 14  |]..XI<...a5.....|
+00000030  00 ff 01 00 00 36 00 00  00 0e 00 0c 00 00 09 31  |.....6.........1|
+00000040  32 37 2e 30 2e 30 2e 31  00 0b 00 04 03 00 01 02  |27.0.0.1........|
+00000050  00 0a 00 0c 00 0a 00 1d  00 17 00 1e 00 19 00 18  |................|
+00000060  00 23 00 00 00 16 00 00  00 17 00 00              |.#..........|
 >>> Flow 2 (server to client)
 00000000  16 03 01 00 3b 02 00 00  37 03 01 00 00 00 00 00  |....;...7.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000290  d4 db fe 3d 13 60 84 5c  21 d3 3b e9 fa e7 16 03  |...=.`.\!.;.....|
 000002a0  01 00 aa 0c 00 00 a6 03  00 1d 20 2f e5 7d a3 47  |.......... /.}.G|
 000002b0  cd 62 43 15 28 da ac 5f  bb 29 07 30 ff f6 84 af  |.bC.(.._.).0....|
-000002c0  c4 cf c2 ed 90 99 5f 58  cb 3b 74 00 80 bb 96 fe  |......_X.;t.....|
-000002d0  bf a0 81 24 bc 40 b4 e2  37 b1 c9 66 2d c3 c1 bb  |...$.@..7..f-...|
-000002e0  89 fb 28 23 60 76 b1 e6  2c c1 e9 06 d0 95 c5 10  |..(#`v..,.......|
-000002f0  17 ce 79 36 c2 14 e0 1d  1d 0d 0e 49 3e b9 7f 00  |..y6.......I>...|
-00000300  ad e3 1d 37 ab ce 2c 37  dc eb be aa 6c 28 33 05  |...7..,7....l(3.|
-00000310  53 fd 06 17 b4 85 b9 b8  35 1c a7 3c bb 07 3f 4b  |S.......5..<..?K|
-00000320  53 98 00 4d 8e 49 bd 35  55 64 92 d0 a0 db 05 80  |S..M.I.5Ud......|
-00000330  57 24 78 cd 10 ed ae f0  6a 83 bc b4 4d 77 79 ba  |W$x.....j...Mwy.|
-00000340  6e e7 2e 8f ac 9e 98 34  36 9d a9 27 f0 16 03 01  |n......46..'....|
+000002c0  c4 cf c2 ed 90 99 5f 58  cb 3b 74 00 80 c6 ad e2  |......_X.;t.....|
+000002d0  21 0d d7 30 42 da 08 52  d5 46 70 a3 e5 d6 40 ab  |!..0B..R.Fp...@.|
+000002e0  bf 52 f8 da a5 41 86 1d  48 e6 51 91 52 8d 3c 5d  |.R...A..H.Q.R.<]|
+000002f0  ca 36 4c 62 d1 6b c8 48  8c 99 50 89 a9 27 4b 21  |.6Lb.k.H..P..'K!|
+00000300  c9 9d a6 43 34 d2 47 a7  b3 1a 6d 98 b3 7f 37 94  |...C4.G...m...7.|
+00000310  60 ba 88 f1 b7 ed 34 2b  47 f4 80 27 d3 a0 74 6a  |`.....4+G..'..tj|
+00000320  c6 d6 49 e3 8a e5 5d f1  a7 54 8a b4 84 8d a8 6b  |..I...]..T.....k|
+00000330  3b 7a 3f eb 81 77 4b bf  be 1e ac cd aa f9 4b 79  |;z?..wK.......Ky|
+00000340  24 78 6c 67 14 13 ab f8  ad 33 7c 94 38 16 03 01  |$xlg.....3|.8...|
 00000350  00 04 0e 00 00 00                                 |......|
 >>> Flow 3 (client to server)
-00000000  16 03 01 00 25 10 00 00  21 20 00 ad c5 2b 21 7f  |....%...! ...+!.|
-00000010  8e 44 f2 f5 32 22 c8 c2  c6 de 2c 0b 7a a9 24 b6  |.D..2"....,.z.$.|
-00000020  03 20 c0 cc 79 2e 11 2f  d3 43 14 03 01 00 01 01  |. ..y../.C......|
-00000030  16 03 01 00 30 78 5c 32  72 a1 c8 3b 9c 7b 77 0b  |....0x\2r..;.{w.|
-00000040  a0 28 52 55 17 16 d5 39  89 d0 43 bf 67 29 85 6f  |.(RU...9..C.g).o|
-00000050  b5 1e 83 fa 22 96 78 e3  5c 45 5a 3d fe 2b d5 b7  |....".x.\EZ=.+..|
-00000060  3d 64 44 8c a8                                    |=dD..|
+00000000  16 03 01 00 25 10 00 00  21 20 f5 be 48 cb fb 0d  |....%...! ..H...|
+00000010  69 27 a8 ab 59 c4 9a ac  92 71 46 d1 17 7e 35 67  |i'..Y....qF..~5g|
+00000020  15 b1 ea 9f 53 48 a3 b5  f9 55 14 03 01 00 01 01  |....SH...U......|
+00000030  16 03 01 00 30 e1 79 95  7c ab 01 74 35 39 9b ce  |....0.y.|..t59..|
+00000040  79 5f 15 21 88 fc be fc  46 a9 31 ca 82 07 0c 1f  |y_.!....F.1.....|
+00000050  d8 2f 93 b5 5d 23 bf f9  10 40 bc b5 22 53 df d6  |./..]#...@.."S..|
+00000060  b1 10 b9 16 96                                    |.....|
 >>> Flow 4 (server to client)
 00000000  16 03 01 00 8b 04 00 00  87 00 00 00 00 00 81 50  |...............P|
 00000010  46 ad c1 db a8 38 86 7b  2b bb fd d0 c3 42 3e 00  |F....8.{+....B>.|
 00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 94  |................|
-00000030  6d ec a4 83 51 ed 14 ef  68 ca 42 c5 4c 5f bb 3b  |m...Q...h.B.L_.;|
-00000040  9c c8 3c 7e 1c cf dc da  e4 35 83 03 13 95 82 5f  |..<~.....5....._|
-00000050  32 77 8a cf dc e9 10 65  9b 97 d4 5d ff 43 57 14  |2w.....e...].CW.|
-00000060  a3 25 e0 fa c8 26 0c ff  71 67 9b 32 2f 49 38 16  |.%...&..qg.2/I8.|
-00000070  aa ea b9 fa 99 86 4c b9  db 7a ef bc 87 43 e8 db  |......L..z...C..|
-00000080  26 27 73 76 80 77 59 c4  fb 7d 56 e9 7e 23 03 75  |&'sv.wY..}V.~#.u|
-00000090  14 03 01 00 01 01 16 03  01 00 30 80 8f 8e 11 b5  |..........0.....|
-000000a0  f4 a0 8c 4a ae 3f 25 17  66 93 1c c5 a5 10 57 e3  |...J.?%.f.....W.|
-000000b0  24 7a c1 a9 72 74 4f fd  20 5e 5b 58 4d bd 5d f0  |$z..rtO. ^[XM.].|
-000000c0  05 8e 06 61 0a 98 19 a0  a8 73 02 17 03 01 00 20  |...a.....s..... |
-000000d0  d9 dd 86 e6 55 55 df 2c  0d 1e 5f 0e 9e 1e 76 51  |....UU.,.._...vQ|
-000000e0  98 e0 2b 09 f9 44 4d 4d  22 97 0d 1e 95 7b b9 41  |..+..DMM"....{.A|
-000000f0  17 03 01 00 30 74 82 1c  35 9b 87 cd 5e 29 95 e1  |....0t..5...^)..|
-00000100  18 e3 76 32 94 b5 1b d0  06 d2 ec 49 40 24 73 d3  |..v2.......I@$s.|
-00000110  fc 5d 1a 26 59 5b 33 d8  5a 30 d5 92 30 bc 80 e0  |.].&Y[3.Z0..0...|
-00000120  ed 85 e8 14 01 15 03 01  00 20 ec 69 2f 9d 29 4f  |......... .i/.)O|
-00000130  1f 8e e6 34 f0 87 66 40  e8 13 14 02 74 c4 1d aa  |...4..f@....t...|
-00000140  65 72 43 50 6e 71 9c 2e  b6 3a                    |erCPnq...:|
+00000030  6d ec a4 83 51 ed 14 ef  68 ca 42 c5 4c d2 34 08  |m...Q...h.B.L.4.|
+00000040  0b cc b9 32 8f 21 f7 50  c4 e1 28 9b 7d 5e ed de  |...2.!.P..(.}^..|
+00000050  0a df 30 0d 16 34 6b 6d  22 3c d3 c8 b2 99 84 8e  |..0..4km"<......|
+00000060  09 6d 3c 62 d4 0f f6 37  dc 53 ae 72 40 49 38 16  |.m<b...7.S.r@I8.|
+00000070  9c 30 34 bf 6e 34 bb 54  73 33 c0 c9 8c 12 ae bc  |.04.n4.Ts3......|
+00000080  e9 a8 80 23 de d0 e5 d3  46 d8 6a 86 c7 a5 6c 61  |...#....F.j...la|
+00000090  14 03 01 00 01 01 16 03  01 00 30 27 a7 5d e7 93  |..........0'.]..|
+000000a0  54 9a 77 d5 43 aa e3 ec  21 00 fa d4 36 04 c3 82  |T.w.C...!...6...|
+000000b0  b0 b7 f5 b4 19 ce f9 58  0a b4 7f d6 bf 95 43 9d  |.......X......C.|
+000000c0  26 44 46 77 48 cd 77 82  e2 48 51 17 03 01 00 20  |&DFwH.w..HQ.... |
+000000d0  c0 9b b1 d3 9f e6 4f 55  59 17 5a dc e4 2f bc 04  |......OUY.Z../..|
+000000e0  6f eb 4d d9 22 6e 97 20  33 94 d4 91 aa 70 4d ab  |o.M."n. 3....pM.|
+000000f0  17 03 01 00 30 9b 0f 50  a8 95 f5 db 67 96 c2 3e  |....0..P....g..>|
+00000100  46 a7 41 99 d5 e2 ab 60  b1 eb 8d 68 2f 71 30 70  |F.A....`...h/q0p|
+00000110  75 cc b8 50 1a 58 3b 96  d3 5c 99 43 27 4f b1 4a  |u..P.X;..\.C'O.J|
+00000120  c8 8d 5b ab 49 15 03 01  00 20 34 a6 41 25 fd 23  |..[.I.... 4.A%.#|
+00000130  44 6d 60 7f 79 5d 27 23  f7 cb 77 d0 cd 81 c4 67  |Dm`.y]'#..w....g|
+00000140  0e 56 92 60 ac a1 32 a5  0d 94                    |.V.`..2...|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-Fallback b/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-Fallback
new file mode 100644 (file)
index 0000000..4fadf39
--- /dev/null
@@ -0,0 +1,91 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 a6 01 00 00  a2 03 03 b5 c9 ab 32 7f  |..............2.|
+00000010  e1 af 3f f2 ac 2a 11 dd  33 f9 b5 21 88 0d e4 29  |..?..*..3..!...)|
+00000020  e2 47 49 dc c7 31 a8 a5  25 81 0c 00 00 04 cc a8  |.GI..1..%.......|
+00000030  00 ff 01 00 00 75 00 0b  00 04 03 00 01 02 00 0a  |.....u..........|
+00000040  00 0c 00 0a 00 1d 00 17  00 1e 00 19 00 18 00 23  |...............#|
+00000050  00 00 00 10 00 19 00 17  06 70 72 6f 74 6f 33 08  |.........proto3.|
+00000060  68 74 74 70 2f 31 2e 31  06 70 72 6f 74 6f 34 00  |http/1.1.proto4.|
+00000070  16 00 00 00 17 00 00 00  0d 00 30 00 2e 04 03 05  |..........0.....|
+00000080  03 06 03 08 07 08 08 08  09 08 0a 08 0b 08 04 08  |................|
+00000090  05 08 06 04 01 05 01 06  01 03 03 02 03 03 01 02  |................|
+000000a0  01 03 02 02 02 04 02 05  02 06 02                 |...........|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 3b 02 00 00  37 03 03 00 00 00 00 00  |....;...7.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 44 4f 57 4e 47  52 44 01 00 cc a8 00 00  |...DOWNGRD......|
+00000030  0f 00 23 00 00 ff 01 00  01 00 00 0b 00 02 01 00  |..#.............|
+00000040  16 03 03 02 59 0b 00 02  55 00 02 52 00 02 4f 30  |....Y...U..R..O0|
+00000050  82 02 4b 30 82 01 b4 a0  03 02 01 02 02 09 00 e8  |..K0............|
+00000060  f0 9d 3f e2 5b ea a6 30  0d 06 09 2a 86 48 86 f7  |..?.[..0...*.H..|
+00000070  0d 01 01 0b 05 00 30 1f  31 0b 30 09 06 03 55 04  |......0.1.0...U.|
+00000080  0a 13 02 47 6f 31 10 30  0e 06 03 55 04 03 13 07  |...Go1.0...U....|
+00000090  47 6f 20 52 6f 6f 74 30  1e 17 0d 31 36 30 31 30  |Go Root0...16010|
+000000a0  31 30 30 30 30 30 30 5a  17 0d 32 35 30 31 30 31  |1000000Z..250101|
+000000b0  30 30 30 30 30 30 5a 30  1a 31 0b 30 09 06 03 55  |000000Z0.1.0...U|
+000000c0  04 0a 13 02 47 6f 31 0b  30 09 06 03 55 04 03 13  |....Go1.0...U...|
+000000d0  02 47 6f 30 81 9f 30 0d  06 09 2a 86 48 86 f7 0d  |.Go0..0...*.H...|
+000000e0  01 01 01 05 00 03 81 8d  00 30 81 89 02 81 81 00  |.........0......|
+000000f0  db 46 7d 93 2e 12 27 06  48 bc 06 28 21 ab 7e c4  |.F}...'.H..(!.~.|
+00000100  b6 a2 5d fe 1e 52 45 88  7a 36 47 a5 08 0d 92 42  |..]..RE.z6G....B|
+00000110  5b c2 81 c0 be 97 79 98  40 fb 4f 6d 14 fd 2b 13  |[.....y.@.Om..+.|
+00000120  8b c2 a5 2e 67 d8 d4 09  9e d6 22 38 b7 4a 0b 74  |....g....."8.J.t|
+00000130  73 2b c2 34 f1 d1 93 e5  96 d9 74 7b f3 58 9f 6c  |s+.4......t{.X.l|
+00000140  61 3c c0 b0 41 d4 d9 2b  2b 24 23 77 5b 1c 3b bd  |a<..A..++$#w[.;.|
+00000150  75 5d ce 20 54 cf a1 63  87 1d 1e 24 c4 f3 1d 1a  |u]. T..c...$....|
+00000160  50 8b aa b6 14 43 ed 97  a7 75 62 f4 14 c8 52 d7  |P....C...ub...R.|
+00000170  02 03 01 00 01 a3 81 93  30 81 90 30 0e 06 03 55  |........0..0...U|
+00000180  1d 0f 01 01 ff 04 04 03  02 05 a0 30 1d 06 03 55  |...........0...U|
+00000190  1d 25 04 16 30 14 06 08  2b 06 01 05 05 07 03 01  |.%..0...+.......|
+000001a0  06 08 2b 06 01 05 05 07  03 02 30 0c 06 03 55 1d  |..+.......0...U.|
+000001b0  13 01 01 ff 04 02 30 00  30 19 06 03 55 1d 0e 04  |......0.0...U...|
+000001c0  12 04 10 9f 91 16 1f 43  43 3e 49 a6 de 6d b6 80  |.......CC>I..m..|
+000001d0  d7 9f 60 30 1b 06 03 55  1d 23 04 14 30 12 80 10  |..`0...U.#..0...|
+000001e0  48 13 49 4d 13 7e 16 31  bb a3 01 d5 ac ab 6e 7b  |H.IM.~.1......n{|
+000001f0  30 19 06 03 55 1d 11 04  12 30 10 82 0e 65 78 61  |0...U....0...exa|
+00000200  6d 70 6c 65 2e 67 6f 6c  61 6e 67 30 0d 06 09 2a  |mple.golang0...*|
+00000210  86 48 86 f7 0d 01 01 0b  05 00 03 81 81 00 9d 30  |.H.............0|
+00000220  cc 40 2b 5b 50 a0 61 cb  ba e5 53 58 e1 ed 83 28  |.@+[P.a...SX...(|
+00000230  a9 58 1a a9 38 a4 95 a1  ac 31 5a 1a 84 66 3d 43  |.X..8....1Z..f=C|
+00000240  d3 2d d9 0b f2 97 df d3  20 64 38 92 24 3a 00 bc  |.-...... d8.$:..|
+00000250  cf 9c 7d b7 40 20 01 5f  aa d3 16 61 09 a2 76 fd  |..}.@ ._...a..v.|
+00000260  13 c3 cc e1 0c 5c ee b1  87 82 f1 6c 04 ed 73 bb  |.....\.....l..s.|
+00000270  b3 43 77 8d 0c 1c f1 0f  a1 d8 40 83 61 c9 4c 72  |.Cw.......@.a.Lr|
+00000280  2b 9d ae db 46 06 06 4d  f4 c1 b3 3e c0 d1 bd 42  |+...F..M...>...B|
+00000290  d4 db fe 3d 13 60 84 5c  21 d3 3b e9 fa e7 16 03  |...=.`.\!.;.....|
+000002a0  03 00 ac 0c 00 00 a8 03  00 1d 20 2f e5 7d a3 47  |.......... /.}.G|
+000002b0  cd 62 43 15 28 da ac 5f  bb 29 07 30 ff f6 84 af  |.bC.(.._.).0....|
+000002c0  c4 cf c2 ed 90 99 5f 58  cb 3b 74 08 04 00 80 5f  |......_X.;t...._|
+000002d0  37 27 84 58 1e ea 1e 40  1b de a9 8f 04 d4 94 64  |7'.X...@.......d|
+000002e0  4e 27 c7 f1 b3 30 d0 53  f5 3d 57 50 d2 17 97 c8  |N'...0.S.=WP....|
+000002f0  3d 61 af a6 21 ab 1c 34  47 70 f8 b1 3b 9c 06 86  |=a..!..4Gp..;...|
+00000300  87 00 e2 13 50 83 91 ad  bc 84 bd b4 7b f3 4b ed  |....P.......{.K.|
+00000310  ca 81 0c 94 37 a8 ec 67  ca 9c f3 00 f6 af c2 92  |....7..g........|
+00000320  c4 8c 78 07 18 0e 43 24  1b 98 16 50 5c 2b 75 0e  |..x...C$...P\+u.|
+00000330  40 66 dc 40 cd 10 1a 51  25 f3 96 25 1a 3e 70 af  |@f.@...Q%..%.>p.|
+00000340  16 24 d0 1c 0e 33 f9 c1  74 cf b7 e2 28 ac 60 16  |.$...3..t...(.`.|
+00000350  03 03 00 04 0e 00 00 00                           |........|
+>>> Flow 3 (client to server)
+00000000  16 03 03 00 25 10 00 00  21 20 30 f2 bb f7 a7 ac  |....%...! 0.....|
+00000010  23 20 22 ee 73 0d 49 9c  b3 7b c1 9a db 2c 85 f3  |# ".s.I..{...,..|
+00000020  c0 82 31 60 bd 8b 14 4e  73 43 14 03 03 00 01 01  |..1`...NsC......|
+00000030  16 03 03 00 20 09 8d c7  86 ee cc f4 c7 36 a3 49  |.... ........6.I|
+00000040  d3 f7 a1 4a 68 a2 1e b4  fc cc a2 15 cb 01 92 d8  |...Jh...........|
+00000050  72 b0 d1 6f eb                                    |r..o.|
+>>> Flow 4 (server to client)
+00000000  16 03 03 00 8b 04 00 00  87 00 00 00 00 00 81 50  |...............P|
+00000010  46 ad c1 db a8 38 86 7b  2b bb fd d0 c3 42 3e 00  |F....8.{+....B>.|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 94  |................|
+00000030  6f e0 18 83 51 ed 14 ef  68 ca 42 c5 4c a2 ac 05  |o...Q...h.B.L...|
+00000040  9c 69 69 99 08 9f de a4  d4 e7 37 ab 14 38 4c 47  |.ii.......7..8LG|
+00000050  70 f0 97 1d db 2d 0a 14  c2 1e f0 16 9f 6d 37 02  |p....-.......m7.|
+00000060  4b f1 16 be 98 3f df 74  83 7c 19 85 61 49 38 16  |K....?.t.|..aI8.|
+00000070  ee 35 7a e2 3f 74 fe 8d  e3 07 93 a1 5e fa f2 02  |.5z.?t......^...|
+00000080  e5 c8 60 3f 11 83 8b 0e  32 52 f1 aa 52 b7 0a 89  |..`?....2R..R...|
+00000090  14 03 03 00 01 01 16 03  03 00 20 9e 65 15 cf 45  |.......... .e..E|
+000000a0  a5 03 69 c9 b1 d8 9e 92  a3 a2 b0 df 2e 62 b1 3a  |..i..........b.:|
+000000b0  17 78 cd e5 1d f3 51 42  7e 4e 25 17 03 03 00 1d  |.x....QB~N%.....|
+000000c0  d9 ae d0 fa b7 90 a9 2f  28 8d 1d 6f 54 1f c0 1e  |......./(..oT...|
+000000d0  4d ae b6 91 f0 e8 84 cf  86 11 22 25 ea 15 03 03  |M........."%....|
+000000e0  00 12 0e 71 f2 11 9e 9f  58 ad c0 d8 fc fa 34 bc  |...q....X.....4.|
+000000f0  02 5a 60 00                                       |.Z`.|
index fdfb175463781defa168e7e9bb12a0ac0dc8b20c..2d8a2eb8e8a5d0b45e41341076d12e9e02a37637 100644 (file)
@@ -1,7 +1,7 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 9d 01 00 00  99 03 03 7f fc 15 86 d1  |................|
-00000010  83 09 78 47 8d cd 7b 88  b3 86 52 27 bc da bc 8d  |..xG..{...R'....|
-00000020  0e 5d 35 44 21 17 7b d9  67 b9 fb 00 00 04 cc a8  |.]5D!.{.g.......|
+00000000  16 03 01 00 9d 01 00 00  99 03 03 24 15 a8 f2 f5  |...........$....|
+00000010  53 02 78 f0 4c f7 82 3c  68 7d a0 b1 9a 0f 29 32  |S.x.L..<h}....)2|
+00000020  9c 38 cc e7 92 95 63 f2  30 53 46 00 00 04 cc a8  |.8....c.0SF.....|
 00000030  00 ff 01 00 00 6c 00 0b  00 04 03 00 01 02 00 0a  |.....l..........|
 00000040  00 0c 00 0a 00 1d 00 17  00 1e 00 19 00 18 00 23  |...............#|
 00000050  00 00 00 10 00 10 00 0e  06 70 72 6f 74 6f 32 06  |.........proto2.|
 00000090  03 03 02 03 03 01 02 01  03 02 02 02 04 02 05 02  |................|
 000000a0  06 02                                             |..|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 3b 02 00 00  37 03 03 00 00 00 00 00  |....;...7.......|
-00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 44 4f 57 4e 47  52 44 01 00 cc a8 00 00  |...DOWNGRD......|
-00000030  0f 00 23 00 00 ff 01 00  01 00 00 0b 00 02 01 00  |..#.............|
-00000040  16 03 03 02 59 0b 00 02  55 00 02 52 00 02 4f 30  |....Y...U..R..O0|
-00000050  82 02 4b 30 82 01 b4 a0  03 02 01 02 02 09 00 e8  |..K0............|
-00000060  f0 9d 3f e2 5b ea a6 30  0d 06 09 2a 86 48 86 f7  |..?.[..0...*.H..|
-00000070  0d 01 01 0b 05 00 30 1f  31 0b 30 09 06 03 55 04  |......0.1.0...U.|
-00000080  0a 13 02 47 6f 31 10 30  0e 06 03 55 04 03 13 07  |...Go1.0...U....|
-00000090  47 6f 20 52 6f 6f 74 30  1e 17 0d 31 36 30 31 30  |Go Root0...16010|
-000000a0  31 30 30 30 30 30 30 5a  17 0d 32 35 30 31 30 31  |1000000Z..250101|
-000000b0  30 30 30 30 30 30 5a 30  1a 31 0b 30 09 06 03 55  |000000Z0.1.0...U|
-000000c0  04 0a 13 02 47 6f 31 0b  30 09 06 03 55 04 03 13  |....Go1.0...U...|
-000000d0  02 47 6f 30 81 9f 30 0d  06 09 2a 86 48 86 f7 0d  |.Go0..0...*.H...|
-000000e0  01 01 01 05 00 03 81 8d  00 30 81 89 02 81 81 00  |.........0......|
-000000f0  db 46 7d 93 2e 12 27 06  48 bc 06 28 21 ab 7e c4  |.F}...'.H..(!.~.|
-00000100  b6 a2 5d fe 1e 52 45 88  7a 36 47 a5 08 0d 92 42  |..]..RE.z6G....B|
-00000110  5b c2 81 c0 be 97 79 98  40 fb 4f 6d 14 fd 2b 13  |[.....y.@.Om..+.|
-00000120  8b c2 a5 2e 67 d8 d4 09  9e d6 22 38 b7 4a 0b 74  |....g....."8.J.t|
-00000130  73 2b c2 34 f1 d1 93 e5  96 d9 74 7b f3 58 9f 6c  |s+.4......t{.X.l|
-00000140  61 3c c0 b0 41 d4 d9 2b  2b 24 23 77 5b 1c 3b bd  |a<..A..++$#w[.;.|
-00000150  75 5d ce 20 54 cf a1 63  87 1d 1e 24 c4 f3 1d 1a  |u]. T..c...$....|
-00000160  50 8b aa b6 14 43 ed 97  a7 75 62 f4 14 c8 52 d7  |P....C...ub...R.|
-00000170  02 03 01 00 01 a3 81 93  30 81 90 30 0e 06 03 55  |........0..0...U|
-00000180  1d 0f 01 01 ff 04 04 03  02 05 a0 30 1d 06 03 55  |...........0...U|
-00000190  1d 25 04 16 30 14 06 08  2b 06 01 05 05 07 03 01  |.%..0...+.......|
-000001a0  06 08 2b 06 01 05 05 07  03 02 30 0c 06 03 55 1d  |..+.......0...U.|
-000001b0  13 01 01 ff 04 02 30 00  30 19 06 03 55 1d 0e 04  |......0.0...U...|
-000001c0  12 04 10 9f 91 16 1f 43  43 3e 49 a6 de 6d b6 80  |.......CC>I..m..|
-000001d0  d7 9f 60 30 1b 06 03 55  1d 23 04 14 30 12 80 10  |..`0...U.#..0...|
-000001e0  48 13 49 4d 13 7e 16 31  bb a3 01 d5 ac ab 6e 7b  |H.IM.~.1......n{|
-000001f0  30 19 06 03 55 1d 11 04  12 30 10 82 0e 65 78 61  |0...U....0...exa|
-00000200  6d 70 6c 65 2e 67 6f 6c  61 6e 67 30 0d 06 09 2a  |mple.golang0...*|
-00000210  86 48 86 f7 0d 01 01 0b  05 00 03 81 81 00 9d 30  |.H.............0|
-00000220  cc 40 2b 5b 50 a0 61 cb  ba e5 53 58 e1 ed 83 28  |.@+[P.a...SX...(|
-00000230  a9 58 1a a9 38 a4 95 a1  ac 31 5a 1a 84 66 3d 43  |.X..8....1Z..f=C|
-00000240  d3 2d d9 0b f2 97 df d3  20 64 38 92 24 3a 00 bc  |.-...... d8.$:..|
-00000250  cf 9c 7d b7 40 20 01 5f  aa d3 16 61 09 a2 76 fd  |..}.@ ._...a..v.|
-00000260  13 c3 cc e1 0c 5c ee b1  87 82 f1 6c 04 ed 73 bb  |.....\.....l..s.|
-00000270  b3 43 77 8d 0c 1c f1 0f  a1 d8 40 83 61 c9 4c 72  |.Cw.......@.a.Lr|
-00000280  2b 9d ae db 46 06 06 4d  f4 c1 b3 3e c0 d1 bd 42  |+...F..M...>...B|
-00000290  d4 db fe 3d 13 60 84 5c  21 d3 3b e9 fa e7 16 03  |...=.`.\!.;.....|
-000002a0  03 00 ac 0c 00 00 a8 03  00 1d 20 2f e5 7d a3 47  |.......... /.}.G|
-000002b0  cd 62 43 15 28 da ac 5f  bb 29 07 30 ff f6 84 af  |.bC.(.._.).0....|
-000002c0  c4 cf c2 ed 90 99 5f 58  cb 3b 74 08 04 00 80 b8  |......_X.;t.....|
-000002d0  a8 88 ac 85 ea 59 ac f1  41 e8 2d a2 76 3c 3b 4f  |.....Y..A.-.v<;O|
-000002e0  58 90 b7 03 74 4b 7a a7  5a 65 ea 08 9c cf e9 4d  |X...tKz.Ze.....M|
-000002f0  b4 8a ef f3 e1 d8 0a 83  0f 50 29 0b 59 77 90 e9  |.........P).Yw..|
-00000300  f3 e8 ca 6c b5 da e5 2b  95 47 e7 ed ff d6 3b 30  |...l...+.G....;0|
-00000310  45 61 2c af 5c 8c 4c df  bd c4 dc 28 dd d2 31 fa  |Ea,.\.L....(..1.|
-00000320  be 65 2b a4 cd 7c 41 29  4c 99 07 97 5c 2a 3c a7  |.e+..|A)L...\*<.|
-00000330  4d 9c ed 72 eb a1 a4 9e  db eb a0 cf c7 c2 b1 3b  |M..r...........;|
-00000340  5a d9 f8 f8 8e d5 07 81  f6 65 aa 0d 4f 4d 11 16  |Z........e..OM..|
-00000350  03 03 00 04 0e 00 00 00                           |........|
->>> Flow 3 (client to server)
-00000000  16 03 03 00 25 10 00 00  21 20 5f d2 13 b1 79 f6  |....%...! _...y.|
-00000010  f3 2a 21 f5 89 a3 22 29  73 30 14 60 1d 1e 77 8a  |.*!...")s0.`..w.|
-00000020  f4 1a 92 3f b0 04 06 98  1a 1e 14 03 03 00 01 01  |...?............|
-00000030  16 03 03 00 20 63 10 89  c0 c0 56 37 40 8c e8 5e  |.... c....V7@..^|
-00000040  7f f0 f0 e3 a0 8e d5 20  33 5f dd c3 16 e8 eb 6c  |....... 3_.....l|
-00000050  c3 a8 75 6d dc                                    |..um.|
->>> Flow 4 (server to client)
-00000000  16 03 03 00 8b 04 00 00  87 00 00 00 00 00 81 50  |...............P|
-00000010  46 ad c1 db a8 38 86 7b  2b bb fd d0 c3 42 3e 00  |F....8.{+....B>.|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 94  |................|
-00000030  6f e0 18 83 51 ed 14 ef  68 ca 42 c5 4c e3 f1 12  |o...Q...h.B.L...|
-00000040  a1 17 a6 ee 99 af e8 06  65 d0 6d c1 4f ce 92 7c  |........e.m.O..||
-00000050  40 df 41 c1 90 e3 e0 d8  a1 95 da 38 25 26 ea b5  |@.A........8%&..|
-00000060  ca a9 42 5f 8c 55 d4 d2  73 a6 a2 b6 22 49 38 16  |..B_.U..s..."I8.|
-00000070  ec 70 52 f9 c0 12 18 9e  9b 4d e3 6d 49 b7 3b c0  |.pR......M.mI.;.|
-00000080  e9 53 9d 06 96 fc a9 06  8c 2a 7a c5 7d 48 47 ef  |.S.......*z.}HG.|
-00000090  14 03 03 00 01 01 16 03  03 00 20 19 27 38 37 bf  |.......... .'87.|
-000000a0  07 4e 2f 77 b9 73 4b dd  c8 f8 4c c5 f1 35 86 2b  |.N/w.sK...L..5.+|
-000000b0  97 7e 0f 89 4b bf db 81  76 8a 41 17 03 03 00 1d  |.~..K...v.A.....|
-000000c0  6d b8 c3 eb b1 5a f3 06  97 04 61 fc 82 74 5d a0  |m....Z....a..t].|
-000000d0  73 57 75 6e 66 53 3e 12  5e 0d 60 31 52 15 03 03  |sWunfS>.^.`1R...|
-000000e0  00 12 e4 93 fb 7b cb ee  d6 70 ac af 5f 8b 82 9b  |.....{...p.._...|
-000000f0  e5 0b 68 9c                                       |..h.|
+00000000  15 03 03 00 02 02 78                              |......x|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-NotConfigured b/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-NotConfigured
new file mode 100644 (file)
index 0000000..e1c991b
--- /dev/null
@@ -0,0 +1,91 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 9d 01 00 00  99 03 03 92 d8 d4 4f 2e  |..............O.|
+00000010  82 ad e9 4f a2 c3 f7 23  da 2e dc 23 c0 87 fc 33  |...O...#...#...3|
+00000020  14 63 f1 da 98 a8 af 70  3a 7e f3 00 00 04 cc a8  |.c.....p:~......|
+00000030  00 ff 01 00 00 6c 00 0b  00 04 03 00 01 02 00 0a  |.....l..........|
+00000040  00 0c 00 0a 00 1d 00 17  00 1e 00 19 00 18 00 23  |...............#|
+00000050  00 00 00 10 00 10 00 0e  06 70 72 6f 74 6f 32 06  |.........proto2.|
+00000060  70 72 6f 74 6f 31 00 16  00 00 00 17 00 00 00 0d  |proto1..........|
+00000070  00 30 00 2e 04 03 05 03  06 03 08 07 08 08 08 09  |.0..............|
+00000080  08 0a 08 0b 08 04 08 05  08 06 04 01 05 01 06 01  |................|
+00000090  03 03 02 03 03 01 02 01  03 02 02 02 04 02 05 02  |................|
+000000a0  06 02                                             |..|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 3b 02 00 00  37 03 03 00 00 00 00 00  |....;...7.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 44 4f 57 4e 47  52 44 01 00 cc a8 00 00  |...DOWNGRD......|
+00000030  0f 00 23 00 00 ff 01 00  01 00 00 0b 00 02 01 00  |..#.............|
+00000040  16 03 03 02 59 0b 00 02  55 00 02 52 00 02 4f 30  |....Y...U..R..O0|
+00000050  82 02 4b 30 82 01 b4 a0  03 02 01 02 02 09 00 e8  |..K0............|
+00000060  f0 9d 3f e2 5b ea a6 30  0d 06 09 2a 86 48 86 f7  |..?.[..0...*.H..|
+00000070  0d 01 01 0b 05 00 30 1f  31 0b 30 09 06 03 55 04  |......0.1.0...U.|
+00000080  0a 13 02 47 6f 31 10 30  0e 06 03 55 04 03 13 07  |...Go1.0...U....|
+00000090  47 6f 20 52 6f 6f 74 30  1e 17 0d 31 36 30 31 30  |Go Root0...16010|
+000000a0  31 30 30 30 30 30 30 5a  17 0d 32 35 30 31 30 31  |1000000Z..250101|
+000000b0  30 30 30 30 30 30 5a 30  1a 31 0b 30 09 06 03 55  |000000Z0.1.0...U|
+000000c0  04 0a 13 02 47 6f 31 0b  30 09 06 03 55 04 03 13  |....Go1.0...U...|
+000000d0  02 47 6f 30 81 9f 30 0d  06 09 2a 86 48 86 f7 0d  |.Go0..0...*.H...|
+000000e0  01 01 01 05 00 03 81 8d  00 30 81 89 02 81 81 00  |.........0......|
+000000f0  db 46 7d 93 2e 12 27 06  48 bc 06 28 21 ab 7e c4  |.F}...'.H..(!.~.|
+00000100  b6 a2 5d fe 1e 52 45 88  7a 36 47 a5 08 0d 92 42  |..]..RE.z6G....B|
+00000110  5b c2 81 c0 be 97 79 98  40 fb 4f 6d 14 fd 2b 13  |[.....y.@.Om..+.|
+00000120  8b c2 a5 2e 67 d8 d4 09  9e d6 22 38 b7 4a 0b 74  |....g....."8.J.t|
+00000130  73 2b c2 34 f1 d1 93 e5  96 d9 74 7b f3 58 9f 6c  |s+.4......t{.X.l|
+00000140  61 3c c0 b0 41 d4 d9 2b  2b 24 23 77 5b 1c 3b bd  |a<..A..++$#w[.;.|
+00000150  75 5d ce 20 54 cf a1 63  87 1d 1e 24 c4 f3 1d 1a  |u]. T..c...$....|
+00000160  50 8b aa b6 14 43 ed 97  a7 75 62 f4 14 c8 52 d7  |P....C...ub...R.|
+00000170  02 03 01 00 01 a3 81 93  30 81 90 30 0e 06 03 55  |........0..0...U|
+00000180  1d 0f 01 01 ff 04 04 03  02 05 a0 30 1d 06 03 55  |...........0...U|
+00000190  1d 25 04 16 30 14 06 08  2b 06 01 05 05 07 03 01  |.%..0...+.......|
+000001a0  06 08 2b 06 01 05 05 07  03 02 30 0c 06 03 55 1d  |..+.......0...U.|
+000001b0  13 01 01 ff 04 02 30 00  30 19 06 03 55 1d 0e 04  |......0.0...U...|
+000001c0  12 04 10 9f 91 16 1f 43  43 3e 49 a6 de 6d b6 80  |.......CC>I..m..|
+000001d0  d7 9f 60 30 1b 06 03 55  1d 23 04 14 30 12 80 10  |..`0...U.#..0...|
+000001e0  48 13 49 4d 13 7e 16 31  bb a3 01 d5 ac ab 6e 7b  |H.IM.~.1......n{|
+000001f0  30 19 06 03 55 1d 11 04  12 30 10 82 0e 65 78 61  |0...U....0...exa|
+00000200  6d 70 6c 65 2e 67 6f 6c  61 6e 67 30 0d 06 09 2a  |mple.golang0...*|
+00000210  86 48 86 f7 0d 01 01 0b  05 00 03 81 81 00 9d 30  |.H.............0|
+00000220  cc 40 2b 5b 50 a0 61 cb  ba e5 53 58 e1 ed 83 28  |.@+[P.a...SX...(|
+00000230  a9 58 1a a9 38 a4 95 a1  ac 31 5a 1a 84 66 3d 43  |.X..8....1Z..f=C|
+00000240  d3 2d d9 0b f2 97 df d3  20 64 38 92 24 3a 00 bc  |.-...... d8.$:..|
+00000250  cf 9c 7d b7 40 20 01 5f  aa d3 16 61 09 a2 76 fd  |..}.@ ._...a..v.|
+00000260  13 c3 cc e1 0c 5c ee b1  87 82 f1 6c 04 ed 73 bb  |.....\.....l..s.|
+00000270  b3 43 77 8d 0c 1c f1 0f  a1 d8 40 83 61 c9 4c 72  |.Cw.......@.a.Lr|
+00000280  2b 9d ae db 46 06 06 4d  f4 c1 b3 3e c0 d1 bd 42  |+...F..M...>...B|
+00000290  d4 db fe 3d 13 60 84 5c  21 d3 3b e9 fa e7 16 03  |...=.`.\!.;.....|
+000002a0  03 00 ac 0c 00 00 a8 03  00 1d 20 2f e5 7d a3 47  |.......... /.}.G|
+000002b0  cd 62 43 15 28 da ac 5f  bb 29 07 30 ff f6 84 af  |.bC.(.._.).0....|
+000002c0  c4 cf c2 ed 90 99 5f 58  cb 3b 74 08 04 00 80 8c  |......_X.;t.....|
+000002d0  cb 8c f6 6c dd 02 5f c9  13 7e c2 26 26 41 7a 1a  |...l.._..~.&&Az.|
+000002e0  25 c7 3e 22 11 30 32 c0  67 a5 53 32 1e 32 21 cb  |%.>".02.g.S2.2!.|
+000002f0  ff 0a b7 e1 7a 98 26 e9  bf 05 30 f6 13 38 ee 1d  |....z.&...0..8..|
+00000300  90 56 a6 0d e0 65 a8 02  0e 08 3e c0 31 ff dd fa  |.V...e....>.1...|
+00000310  05 3a 22 7c f8 ce 65 43  0c b6 c4 9a e4 ed 22 eb  |.:"|..eC......".|
+00000320  c4 46 b2 3d 1d 9c c1 e7  d4 6a 79 4f cf 8f 1c 45  |.F.=.....jyO...E|
+00000330  52 51 b3 d1 a4 0d 0d df  4e 19 15 e6 af 2e 5a d5  |RQ......N.....Z.|
+00000340  8a 2e 3c 48 8a f7 86 e5  53 0e 35 9a 8a c6 dd 16  |..<H....S.5.....|
+00000350  03 03 00 04 0e 00 00 00                           |........|
+>>> Flow 3 (client to server)
+00000000  16 03 03 00 25 10 00 00  21 20 b7 d6 2f 99 8f c7  |....%...! ../...|
+00000010  bc 48 b8 4f 01 f8 2c ff  75 e5 fe 10 c6 2d 2d d5  |.H.O..,.u....--.|
+00000020  43 2b c3 14 cb d0 b2 7a  e9 71 14 03 03 00 01 01  |C+.....z.q......|
+00000030  16 03 03 00 20 c9 88 f1  a0 1a 9b 8a 14 00 33 f0  |.... .........3.|
+00000040  e8 01 f3 c2 66 06 98 44  4d 35 89 8f 1b 65 d0 cf  |....f..DM5...e..|
+00000050  eb 7d 9f b1 df                                    |.}...|
+>>> Flow 4 (server to client)
+00000000  16 03 03 00 8b 04 00 00  87 00 00 00 00 00 81 50  |...............P|
+00000010  46 ad c1 db a8 38 86 7b  2b bb fd d0 c3 42 3e 00  |F....8.{+....B>.|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 94  |................|
+00000030  6f e0 18 83 51 ed 14 ef  68 ca 42 c5 4c 76 fb ec  |o...Q...h.B.Lv..|
+00000040  0d 89 48 e7 19 98 64 df  59 8f df 50 ce 28 e8 3c  |..H...d.Y..P.(.<|
+00000050  b6 f8 5a ae bc 6b 2e a2  d6 23 05 f6 7f 36 ea 55  |..Z..k...#...6.U|
+00000060  13 54 9e 9c 31 df d0 56  00 1f a7 6a b2 49 38 16  |.T..1..V...j.I8.|
+00000070  7f d0 78 12 95 86 11 ca  98 63 07 4a 81 a5 d3 bd  |..x......c.J....|
+00000080  dc 9e 54 9c 25 f2 55 d5  fd cf 36 94 99 e0 c5 82  |..T.%.U...6.....|
+00000090  14 03 03 00 01 01 16 03  03 00 20 e6 d9 c2 bb ca  |.......... .....|
+000000a0  02 d3 79 a4 fb b0 00 7d  e2 47 46 d3 e7 b4 fe be  |..y....}.GF.....|
+000000b0  b3 8f c4 98 b7 f7 25 bc  cc 3f a8 17 03 03 00 1d  |......%..?......|
+000000c0  ad f3 27 a0 c4 a4 5b 7b  40 11 a4 35 e6 10 03 63  |..'...[{@..5...c|
+000000d0  13 d3 1c ce 75 8f 09 8b  85 6c 93 b1 9f 15 03 03  |....u....l......|
+000000e0  00 12 79 0c dd 21 72 68  b8 30 45 5d 45 39 a9 c4  |..y..!rh.0E]E9..|
+000000f0  a6 d7 12 99                                       |....|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA b/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA
deleted file mode 100644 (file)
index 63e0edb..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
->>> Flow 1 (client to server)
-00000000  16 03 01 00 cb 01 00 00  c7 03 03 3f 5d 09 25 4e  |...........?].%N|
-00000010  82 83 13 89 ba 89 43 d5  43 4f f1 c3 2f 08 77 39  |......C.CO../.w9|
-00000020  bf eb c7 1d 4b d6 85 c8  17 2f 83 00 00 38 c0 2c  |....K..../...8.,|
-00000030  c0 30 00 9f cc a9 cc a8  cc aa c0 2b c0 2f 00 9e  |.0.........+./..|
-00000040  c0 24 c0 28 00 6b c0 23  c0 27 00 67 c0 0a c0 14  |.$.(.k.#.'.g....|
-00000050  00 39 c0 09 c0 13 00 33  00 9d 00 9c 00 3d 00 3c  |.9.....3.....=.<|
-00000060  00 35 00 2f 00 ff 01 00  00 66 00 00 00 0e 00 0c  |.5./.....f......|
-00000070  00 00 09 31 32 37 2e 30  2e 30 2e 31 00 0b 00 04  |...127.0.0.1....|
-00000080  03 00 01 02 00 0a 00 0c  00 0a 00 1d 00 17 00 1e  |................|
-00000090  00 19 00 18 00 16 00 00  00 17 00 00 00 0d 00 30  |...............0|
-000000a0  00 2e 04 03 05 03 06 03  08 07 08 08 08 09 08 0a  |................|
-000000b0  08 0b 08 04 08 05 08 06  04 01 05 01 06 01 03 03  |................|
-000000c0  02 03 03 01 02 01 03 02  02 02 04 02 05 02 06 02  |................|
->>> Flow 2 (server to client)
-00000000  16 03 03 00 37 02 00 00  33 03 03 00 00 00 00 00  |....7...3.......|
-00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 44 4f 57 4e 47  52 44 01 00 c0 0a 00 00  |...DOWNGRD......|
-00000030  0b ff 01 00 01 00 00 0b  00 02 01 00 16 03 03 02  |................|
-00000040  0e 0b 00 02 0a 00 02 07  00 02 04 30 82 02 00 30  |...........0...0|
-00000050  82 01 62 02 09 00 b8 bf  2d 47 a0 d2 eb f4 30 09  |..b.....-G....0.|
-00000060  06 07 2a 86 48 ce 3d 04  01 30 45 31 0b 30 09 06  |..*.H.=..0E1.0..|
-00000070  03 55 04 06 13 02 41 55  31 13 30 11 06 03 55 04  |.U....AU1.0...U.|
-00000080  08 13 0a 53 6f 6d 65 2d  53 74 61 74 65 31 21 30  |...Some-State1!0|
-00000090  1f 06 03 55 04 0a 13 18  49 6e 74 65 72 6e 65 74  |...U....Internet|
-000000a0  20 57 69 64 67 69 74 73  20 50 74 79 20 4c 74 64  | Widgits Pty Ltd|
-000000b0  30 1e 17 0d 31 32 31 31  32 32 31 35 30 36 33 32  |0...121122150632|
-000000c0  5a 17 0d 32 32 31 31 32  30 31 35 30 36 33 32 5a  |Z..221120150632Z|
-000000d0  30 45 31 0b 30 09 06 03  55 04 06 13 02 41 55 31  |0E1.0...U....AU1|
-000000e0  13 30 11 06 03 55 04 08  13 0a 53 6f 6d 65 2d 53  |.0...U....Some-S|
-000000f0  74 61 74 65 31 21 30 1f  06 03 55 04 0a 13 18 49  |tate1!0...U....I|
-00000100  6e 74 65 72 6e 65 74 20  57 69 64 67 69 74 73 20  |nternet Widgits |
-00000110  50 74 79 20 4c 74 64 30  81 9b 30 10 06 07 2a 86  |Pty Ltd0..0...*.|
-00000120  48 ce 3d 02 01 06 05 2b  81 04 00 23 03 81 86 00  |H.=....+...#....|
-00000130  04 00 c4 a1 ed be 98 f9  0b 48 73 36 7e c3 16 56  |.........Hs6~..V|
-00000140  11 22 f2 3d 53 c3 3b 4d  21 3d cd 6b 75 e6 f6 b0  |.".=S.;M!=.ku...|
-00000150  dc 9a df 26 c1 bc b2 87  f0 72 32 7c b3 64 2f 1c  |...&.....r2|.d/.|
-00000160  90 bc ea 68 23 10 7e fe  e3 25 c0 48 3a 69 e0 28  |...h#.~..%.H:i.(|
-00000170  6d d3 37 00 ef 04 62 dd  0d a0 9c 70 62 83 d8 81  |m.7...b....pb...|
-00000180  d3 64 31 aa 9e 97 31 bd  96 b0 68 c0 9b 23 de 76  |.d1...1...h..#.v|
-00000190  64 3f 1a 5c 7f e9 12 0e  58 58 b6 5f 70 dd 9b d8  |d?.\....XX._p...|
-000001a0  ea d5 d7 f5 d5 cc b9 b6  9f 30 66 5b 66 9a 20 e2  |.........0f[f. .|
-000001b0  27 e5 bf fe 3b 30 09 06  07 2a 86 48 ce 3d 04 01  |'...;0...*.H.=..|
-000001c0  03 81 8c 00 30 81 88 02  42 01 88 a2 4f eb e2 45  |....0...B...O..E|
-000001d0  c5 48 7d 1b ac f5 ed 98  9d ae 47 70 c0 5e 1b b6  |.H}.......Gp.^..|
-000001e0  2f bd f1 b6 4d b7 61 40  d3 11 a2 ce ee 0b 7e 92  |/...M.a@......~.|
-000001f0  7e ff 76 9d c3 3b 7e a5  3f ce fa 10 e2 59 ec 47  |~.v..;~.?....Y.G|
-00000200  2d 7c ac da 4e 97 0e 15  a0 6f d0 02 42 01 4d fc  |-|..N....o..B.M.|
-00000210  be 67 13 9c 2d 05 0e bd  3f a3 8c 25 c1 33 13 83  |.g..-...?..%.3..|
-00000220  0d 94 06 bb d4 37 7a f6  ec 7a c9 86 2e dd d7 11  |.....7z..z......|
-00000230  69 7f 85 7c 56 de fb 31  78 2b e4 c7 78 0d ae cb  |i..|V..1x+..x...|
-00000240  be 9e 4e 36 24 31 7b 6a  0f 39 95 12 07 8f 2a 16  |..N6$1{j.9....*.|
-00000250  03 03 00 b7 0c 00 00 b3  03 00 1d 20 2f e5 7d a3  |........... /.}.|
-00000260  47 cd 62 43 15 28 da ac  5f bb 29 07 30 ff f6 84  |G.bC.(.._.).0...|
-00000270  af c4 cf c2 ed 90 99 5f  58 cb 3b 74 04 03 00 8b  |......._X.;t....|
-00000280  30 81 88 02 42 01 5c 2a  30 4f 9f dc df a8 33 06  |0...B.\*0O....3.|
-00000290  3b bc 35 46 6a 9c a3 a1  26 ec 42 29 bf 63 b3 9b  |;.5Fj...&.B).c..|
-000002a0  8c bf 7b 07 8d 28 eb 41  68 7a 8a 1b f3 de a9 dc  |..{..(.Ahz......|
-000002b0  1e d1 21 3c 4d 24 df 89  90 b6 f2 fb ad 60 d2 27  |..!<M$.......`.'|
-000002c0  96 6d a2 b6 9b 48 e6 02  42 00 f1 c8 c2 f4 ee 4a  |.m...H..B......J|
-000002d0  8f 08 c5 09 05 e9 bf 7f  aa b6 3e 56 e9 98 46 b4  |..........>V..F.|
-000002e0  b4 e5 90 72 ed af 71 0d  fb e6 39 2f d5 4b 73 ba  |...r..q...9/.Ks.|
-000002f0  85 d2 a4 bf 99 74 d7 81  eb 3e 69 4d f0 12 1e 3c  |.....t...>iM...<|
-00000300  53 ca f0 35 85 ef ff ed  cc 0f f7 16 03 03 00 04  |S..5............|
-00000310  0e 00 00 00                                       |....|
->>> Flow 3 (client to server)
-00000000  16 03 03 00 25 10 00 00  21 20 b8 a6 ed 33 20 59  |....%...! ...3 Y|
-00000010  76 0b 7c 87 53 f1 12 c1  46 d9 db 68 c0 6f d6 30  |v.|.S...F..h.o.0|
-00000020  ea e0 64 04 54 7a 4c 95  03 41 14 03 03 00 01 01  |..d.TzL..A......|
-00000030  16 03 03 00 40 c0 70 29  39 a0 8a bd 59 58 88 44  |....@.p)9...YX.D|
-00000040  ea 10 b4 79 3e 0e 72 b7  2a 03 6d 4d 5a 24 f5 c0  |...y>.r.*.mMZ$..|
-00000050  4e e5 19 f0 fb 66 ca 97  89 4b 67 dc bb 19 cd 0b  |N....f...Kg.....|
-00000060  6e 74 01 d3 a4 9a ab af  8e 44 10 99 ac ff 9e 9e  |nt.......D......|
-00000070  17 04 56 78 55                                    |..VxU|
->>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 40 00 00 00 00 00  |..........@.....|
-00000010  00 00 00 00 00 00 00 00  00 00 00 01 a0 6b 2c c5  |.............k,.|
-00000020  7e 83 70 b5 2c 8c 43 b6  8b 2e 18 2a 1d be 11 6d  |~.p.,.C....*...m|
-00000030  13 f9 ba b5 de db 01 2a  64 d9 5b 24 c9 61 a1 4d  |.......*d.[$.a.M|
-00000040  11 bb fc b1 86 61 b0 04  a9 cd 1e 17 03 03 00 40  |.....a.........@|
-00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000060  d8 98 85 b4 cb 61 39 69  2f b1 1f 24 c1 5a 4f e3  |.....a9i/..$.ZO.|
-00000070  0b 20 5d 6c 3f 3f 82 3a  a3 8a b3 cf e9 41 bb 60  |. ]l??.:.....A.`|
-00000080  ed b6 67 a0 76 39 ab 93  a5 35 d0 42 b3 a7 4c 92  |..g.v9...5.B..L.|
-00000090  15 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
-000000a0  00 00 00 00 00 c7 0d 06  b2 2b 73 ab ed 16 88 6f  |.........+s....o|
-000000b0  62 77 fb 48 e4 5e 6d 7e  24 02 b6 08 fa 46 c8 76  |bw.H.^m~$....F.v|
-000000c0  18 fc f4 c4 08                                    |.....|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA b/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA
deleted file mode 100644 (file)
index 802aa1a..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
->>> Flow 1 (client to server)
-00000000  16 03 01 00 cb 01 00 00  c7 03 03 27 8a e9 f3 58  |...........'...X|
-00000010  5a 08 90 d6 d4 97 23 b6  a7 92 73 3a a3 3c c1 a1  |Z.....#...s:.<..|
-00000020  ca 06 23 c8 ed 4a 19 26  73 c9 62 00 00 38 c0 2c  |..#..J.&s.b..8.,|
-00000030  c0 30 00 9f cc a9 cc a8  cc aa c0 2b c0 2f 00 9e  |.0.........+./..|
-00000040  c0 24 c0 28 00 6b c0 23  c0 27 00 67 c0 0a c0 14  |.$.(.k.#.'.g....|
-00000050  00 39 c0 09 c0 13 00 33  00 9d 00 9c 00 3d 00 3c  |.9.....3.....=.<|
-00000060  00 35 00 2f 00 ff 01 00  00 66 00 00 00 0e 00 0c  |.5./.....f......|
-00000070  00 00 09 31 32 37 2e 30  2e 30 2e 31 00 0b 00 04  |...127.0.0.1....|
-00000080  03 00 01 02 00 0a 00 0c  00 0a 00 1d 00 17 00 1e  |................|
-00000090  00 19 00 18 00 16 00 00  00 17 00 00 00 0d 00 30  |...............0|
-000000a0  00 2e 04 03 05 03 06 03  08 07 08 08 08 09 08 0a  |................|
-000000b0  08 0b 08 04 08 05 08 06  04 01 05 01 06 01 03 03  |................|
-000000c0  02 03 03 01 02 01 03 02  02 02 04 02 05 02 06 02  |................|
->>> Flow 2 (server to client)
-00000000  16 03 03 00 37 02 00 00  33 03 03 00 00 00 00 00  |....7...3.......|
-00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 44 4f 57 4e 47  52 44 01 00 c0 14 00 00  |...DOWNGRD......|
-00000030  0b ff 01 00 01 00 00 0b  00 02 01 00 16 03 03 02  |................|
-00000040  59 0b 00 02 55 00 02 52  00 02 4f 30 82 02 4b 30  |Y...U..R..O0..K0|
-00000050  82 01 b4 a0 03 02 01 02  02 09 00 e8 f0 9d 3f e2  |..............?.|
-00000060  5b ea a6 30 0d 06 09 2a  86 48 86 f7 0d 01 01 0b  |[..0...*.H......|
-00000070  05 00 30 1f 31 0b 30 09  06 03 55 04 0a 13 02 47  |..0.1.0...U....G|
-00000080  6f 31 10 30 0e 06 03 55  04 03 13 07 47 6f 20 52  |o1.0...U....Go R|
-00000090  6f 6f 74 30 1e 17 0d 31  36 30 31 30 31 30 30 30  |oot0...160101000|
-000000a0  30 30 30 5a 17 0d 32 35  30 31 30 31 30 30 30 30  |000Z..2501010000|
-000000b0  30 30 5a 30 1a 31 0b 30  09 06 03 55 04 0a 13 02  |00Z0.1.0...U....|
-000000c0  47 6f 31 0b 30 09 06 03  55 04 03 13 02 47 6f 30  |Go1.0...U....Go0|
-000000d0  81 9f 30 0d 06 09 2a 86  48 86 f7 0d 01 01 01 05  |..0...*.H.......|
-000000e0  00 03 81 8d 00 30 81 89  02 81 81 00 db 46 7d 93  |.....0.......F}.|
-000000f0  2e 12 27 06 48 bc 06 28  21 ab 7e c4 b6 a2 5d fe  |..'.H..(!.~...].|
-00000100  1e 52 45 88 7a 36 47 a5  08 0d 92 42 5b c2 81 c0  |.RE.z6G....B[...|
-00000110  be 97 79 98 40 fb 4f 6d  14 fd 2b 13 8b c2 a5 2e  |..y.@.Om..+.....|
-00000120  67 d8 d4 09 9e d6 22 38  b7 4a 0b 74 73 2b c2 34  |g....."8.J.ts+.4|
-00000130  f1 d1 93 e5 96 d9 74 7b  f3 58 9f 6c 61 3c c0 b0  |......t{.X.la<..|
-00000140  41 d4 d9 2b 2b 24 23 77  5b 1c 3b bd 75 5d ce 20  |A..++$#w[.;.u]. |
-00000150  54 cf a1 63 87 1d 1e 24  c4 f3 1d 1a 50 8b aa b6  |T..c...$....P...|
-00000160  14 43 ed 97 a7 75 62 f4  14 c8 52 d7 02 03 01 00  |.C...ub...R.....|
-00000170  01 a3 81 93 30 81 90 30  0e 06 03 55 1d 0f 01 01  |....0..0...U....|
-00000180  ff 04 04 03 02 05 a0 30  1d 06 03 55 1d 25 04 16  |.......0...U.%..|
-00000190  30 14 06 08 2b 06 01 05  05 07 03 01 06 08 2b 06  |0...+.........+.|
-000001a0  01 05 05 07 03 02 30 0c  06 03 55 1d 13 01 01 ff  |......0...U.....|
-000001b0  04 02 30 00 30 19 06 03  55 1d 0e 04 12 04 10 9f  |..0.0...U.......|
-000001c0  91 16 1f 43 43 3e 49 a6  de 6d b6 80 d7 9f 60 30  |...CC>I..m....`0|
-000001d0  1b 06 03 55 1d 23 04 14  30 12 80 10 48 13 49 4d  |...U.#..0...H.IM|
-000001e0  13 7e 16 31 bb a3 01 d5  ac ab 6e 7b 30 19 06 03  |.~.1......n{0...|
-000001f0  55 1d 11 04 12 30 10 82  0e 65 78 61 6d 70 6c 65  |U....0...example|
-00000200  2e 67 6f 6c 61 6e 67 30  0d 06 09 2a 86 48 86 f7  |.golang0...*.H..|
-00000210  0d 01 01 0b 05 00 03 81  81 00 9d 30 cc 40 2b 5b  |...........0.@+[|
-00000220  50 a0 61 cb ba e5 53 58  e1 ed 83 28 a9 58 1a a9  |P.a...SX...(.X..|
-00000230  38 a4 95 a1 ac 31 5a 1a  84 66 3d 43 d3 2d d9 0b  |8....1Z..f=C.-..|
-00000240  f2 97 df d3 20 64 38 92  24 3a 00 bc cf 9c 7d b7  |.... d8.$:....}.|
-00000250  40 20 01 5f aa d3 16 61  09 a2 76 fd 13 c3 cc e1  |@ ._...a..v.....|
-00000260  0c 5c ee b1 87 82 f1 6c  04 ed 73 bb b3 43 77 8d  |.\.....l..s..Cw.|
-00000270  0c 1c f1 0f a1 d8 40 83  61 c9 4c 72 2b 9d ae db  |......@.a.Lr+...|
-00000280  46 06 06 4d f4 c1 b3 3e  c0 d1 bd 42 d4 db fe 3d  |F..M...>...B...=|
-00000290  13 60 84 5c 21 d3 3b e9  fa e7 16 03 03 00 ac 0c  |.`.\!.;.........|
-000002a0  00 00 a8 03 00 1d 20 2f  e5 7d a3 47 cd 62 43 15  |...... /.}.G.bC.|
-000002b0  28 da ac 5f bb 29 07 30  ff f6 84 af c4 cf c2 ed  |(.._.).0........|
-000002c0  90 99 5f 58 cb 3b 74 08  04 00 80 42 86 d0 0a 5b  |.._X.;t....B...[|
-000002d0  d7 97 20 4d be 16 b8 eb  51 66 28 3b f9 45 35 f5  |.. M....Qf(;.E5.|
-000002e0  de 1d 28 c9 36 63 5b 7b  f6 a7 64 79 fb 39 20 c3  |..(.6c[{..dy.9 .|
-000002f0  dd db 38 3e af 89 ce 91  f7 bd 51 b4 5e 01 d8 9b  |..8>......Q.^...|
-00000300  54 62 58 24 3b c2 43 59  a4 11 1a 2b 67 c5 5f 79  |TbX$;.CY...+g._y|
-00000310  fe 68 9d c7 e6 8b 36 8b  f9 cb 00 b0 b3 0f 52 fb  |.h....6.......R.|
-00000320  fe a5 e6 c6 26 9b d1 a2  17 4e e2 58 7f b2 80 78  |....&....N.X...x|
-00000330  10 b4 0a 47 e1 18 92 d4  a5 5a 86 06 36 ca f7 b6  |...G.....Z..6...|
-00000340  1c 83 81 0e eb 32 7d fe  06 c5 03 16 03 03 00 04  |.....2}.........|
-00000350  0e 00 00 00                                       |....|
->>> Flow 3 (client to server)
-00000000  16 03 03 00 25 10 00 00  21 20 14 7f fb 7d 0c ef  |....%...! ...}..|
-00000010  48 c4 8f 75 24 19 5f ee  5f 51 08 35 74 cf c3 ea  |H..u$._._Q.5t...|
-00000020  67 20 c4 f9 49 b2 cf 69  5a 77 14 03 03 00 01 01  |g ..I..iZw......|
-00000030  16 03 03 00 40 2b d2 f4  dc 36 98 ef 1d 43 f9 3e  |....@+...6...C.>|
-00000040  83 33 c0 71 a6 e3 ac f1  3c cc 94 e4 d0 fe 81 bc  |.3.q....<.......|
-00000050  94 56 15 eb 6a 7b 17 33  e1 a0 ef d5 7a 86 af ea  |.V..j{.3....z...|
-00000060  1f bb d5 8c 80 56 d5 e4  08 cd 68 bf c0 53 c2 56  |.....V....h..S.V|
-00000070  aa b3 38 1e 4e                                    |..8.N|
->>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 40 00 00 00 00 00  |..........@.....|
-00000010  00 00 00 00 00 00 00 00  00 00 00 45 07 c3 ba 8c  |...........E....|
-00000020  d8 9f b6 f1 6a 14 bb b1  4e 84 3f 25 6a 3d ef f6  |....j...N.?%j=..|
-00000030  88 89 1a 91 22 ef e3 ed  ba 2a a3 7c 5b db e0 1d  |...."....*.|[...|
-00000040  b5 8d 7a ed e7 ad e1 31  b2 12 f5 17 03 03 00 40  |..z....1.......@|
-00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000060  a6 f3 0b 33 f7 7a 7c fb  fb b5 e6 eb 6e 0a 26 aa  |...3.z|.....n.&.|
-00000070  06 3b a6 bc 08 e5 3a b6  c9 a3 f3 77 28 93 45 08  |.;....:....w(.E.|
-00000080  1d 54 5e a3 92 cd 89 a3  e6 34 ec 52 70 c0 97 3c  |.T^......4.Rp..<|
-00000090  15 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
-000000a0  00 00 00 00 00 2d 0d 96  57 b8 6f 90 1e 84 4d 35  |.....-..W.o...M5|
-000000b0  91 52 42 6b 8d a3 6b 21  22 60 1a c9 38 7f 5a ef  |.RBk..k!"`..8.Z.|
-000000c0  6e dd 84 06 79                                    |n...y|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv13-ALPN-Fallback b/libgo/go/crypto/tls/testdata/Server-TLSv13-ALPN-Fallback
new file mode 100644 (file)
index 0000000..6203e68
--- /dev/null
@@ -0,0 +1,100 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 eb 01 00 00  e7 03 03 1c d3 8e 3b d9  |..............;.|
+00000010  fe 7d e7 f9 9f fa c6 51  c3 8c 1b dd dc 87 95 f4  |.}.....Q........|
+00000020  39 23 67 e4 d6 bd 94 93  fc 88 4e 20 c3 c0 e2 c1  |9#g.......N ....|
+00000030  3d 12 ec 4c 0a 3f 40 51  13 24 61 11 c0 5d 09 f9  |=..L.?@Q.$a..]..|
+00000040  08 d6 3e cd e7 b3 51 c3  06 8f b4 42 00 04 13 03  |..>...Q....B....|
+00000050  00 ff 01 00 00 9a 00 0b  00 04 03 00 01 02 00 0a  |................|
+00000060  00 0c 00 0a 00 1d 00 17  00 1e 00 19 00 18 00 23  |...............#|
+00000070  00 00 00 10 00 19 00 17  06 70 72 6f 74 6f 33 08  |.........proto3.|
+00000080  68 74 74 70 2f 31 2e 31  06 70 72 6f 74 6f 34 00  |http/1.1.proto4.|
+00000090  16 00 00 00 17 00 00 00  0d 00 1e 00 1c 04 03 05  |................|
+000000a0  03 06 03 08 07 08 08 08  09 08 0a 08 0b 08 04 08  |................|
+000000b0  05 08 06 04 01 05 01 06  01 00 2b 00 03 02 03 04  |..........+.....|
+000000c0  00 2d 00 02 01 01 00 33  00 26 00 24 00 1d 00 20  |.-.....3.&.$... |
+000000d0  f4 05 eb 4a 7a 73 20 18  74 aa 14 2a 0c 35 63 29  |...Jzs .t..*.5c)|
+000000e0  cb f2 ad d1 a2 3d bd 9d  02 b4 62 00 bc eb 10 58  |.....=....b....X|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 7a 02 00 00  76 03 03 00 00 00 00 00  |....z...v.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 20 c3 c0 e2 c1  |........... ....|
+00000030  3d 12 ec 4c 0a 3f 40 51  13 24 61 11 c0 5d 09 f9  |=..L.?@Q.$a..]..|
+00000040  08 d6 3e cd e7 b3 51 c3  06 8f b4 42 13 03 00 00  |..>...Q....B....|
+00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 2f  |..+.....3.$... /|
+00000060  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
+00000070  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74 14  |.........._X.;t.|
+00000080  03 03 00 01 01 17 03 03  00 17 fb 75 d8 5c 50 35  |...........u.\P5|
+00000090  55 82 ba 65 1e 63 73 b8  c1 e9 d7 f5 28 68 3c c1  |U..e.cs.....(h<.|
+000000a0  5d 17 03 03 02 6d 56 c9  a9 09 73 6a bc fd 1a 3c  |]....mV...sj...<|
+000000b0  6a f8 3e 32 99 83 e8 f6  01 9e 5e 30 e8 53 7f 72  |j.>2......^0.S.r|
+000000c0  fd 86 72 a8 9e 47 25 67  c1 f1 9a 03 c0 9d 6f 9d  |..r..G%g......o.|
+000000d0  bd ed 29 30 8f 3c 01 ce  49 bb 5f dd 58 9a ae 80  |..)0.<..I._.X...|
+000000e0  5c 2d 81 fc ea 7b 03 03  3d 5d bb 92 23 73 67 89  |\-...{..=]..#sg.|
+000000f0  2e f0 ec 08 20 8a 36 eb  43 a6 a1 68 d0 39 95 37  |.... .6.C..h.9.7|
+00000100  6b 15 a9 0e 46 20 92 51  9c 04 bf 3b 07 97 84 cb  |k...F .Q...;....|
+00000110  1f 30 38 37 2e ff e7 0f  f5 14 93 5a 84 f1 f7 10  |.087.......Z....|
+00000120  c2 a5 0d bb 97 96 ef 4a  e0 13 c0 63 72 2b 60 f3  |.......J...cr+`.|
+00000130  59 b5 57 aa 5f d1 da a9  0e dd 9c dd c2 cb 61 fe  |Y.W._.........a.|
+00000140  e2 69 8e db 5d 70 6c 3a  33 e0 9e db 9a 31 26 6a  |.i..]pl:3....1&j|
+00000150  2b 9e 19 8e bb 5d 06 48  ea c0 a1 c6 11 24 fb c4  |+....].H.....$..|
+00000160  ce ae 48 54 64 81 d1 84  38 a6 e0 7a 7b 74 2b bc  |..HTd...8..z{t+.|
+00000170  ce 07 8b b6 04 1f 5b 4c  36 29 68 0c 8c c7 32 15  |......[L6)h...2.|
+00000180  93 e0 10 52 c2 27 23 96  c5 0c 9c e9 e2 a9 08 7d  |...R.'#........}|
+00000190  25 68 65 f5 4e 44 eb a9  85 78 13 e1 0d 86 5e dc  |%he.ND...x....^.|
+000001a0  fd e5 c6 dd 65 46 8e 2f  32 82 83 0b dd 67 f8 42  |....eF./2....g.B|
+000001b0  65 87 3b 08 fe b1 f5 12  e9 74 21 04 12 6d 75 35  |e.;......t!..mu5|
+000001c0  b2 eb 93 95 72 10 fa 56  96 77 c3 0c 17 8c 9e f6  |....r..V.w......|
+000001d0  77 19 28 37 96 3e 73 98  f4 d2 91 4f 40 db 76 56  |w.(7.>s....O@.vV|
+000001e0  ce b5 a8 7a b8 86 d0 9a  ba b5 8b 40 c2 63 e1 cf  |...z.......@.c..|
+000001f0  49 29 2c 5d 1a 9b 8b 56  cb 93 ca 2c c0 d0 15 b7  |I),]...V...,....|
+00000200  8a f1 6a d5 0a a8 81 57  b1 6e 10 cd a5 ff b1 4d  |..j....W.n.....M|
+00000210  47 c6 9b 35 f1 5f 83 91  22 f6 88 68 65 b3 b9 c9  |G..5._.."..he...|
+00000220  02 dc 4b f7 13 39 06 e6  3a ec 94 ef 51 15 05 72  |..K..9..:...Q..r|
+00000230  1d f4 9d 3b da ca 8d 2c  64 be 9b 45 99 2c 63 cc  |...;...,d..E.,c.|
+00000240  22 b3 8b 93 ad f6 2c f0  d2 d9 11 3f 5b c0 40 fa  |".....,....?[.@.|
+00000250  90 6e a0 76 b2 43 b9 4c  72 c4 24 28 a2 bf 56 d6  |.n.v.C.Lr.$(..V.|
+00000260  d2 a7 2a d1 8c 5e 1d eb  f8 be d0 43 da 7a c7 88  |..*..^.....C.z..|
+00000270  61 67 a2 69 85 23 43 3e  d4 88 f2 33 c3 5b 38 0a  |ag.i.#C>...3.[8.|
+00000280  1e de 28 3b 3b 19 de 95  2f 84 c0 37 88 80 59 2f  |..(;;.../..7..Y/|
+00000290  a6 ee 93 1a 69 08 c3 df  7c cf da c3 9b 96 70 d9  |....i...|.....p.|
+000002a0  60 c5 e9 0f 42 f6 1a f2  58 5e f2 32 61 6a b2 a3  |`...B...X^.2aj..|
+000002b0  1f 97 fa 08 6c 3f 4b 83  1f 04 66 80 8a 26 3a 7f  |....l?K...f..&:.|
+000002c0  24 30 ec 10 ae 7d 19 ff  39 91 ca 97 4e ed 0a d7  |$0...}..9...N...|
+000002d0  64 3b 6b 50 29 33 0d b2  10 bc 83 63 3c fb 9a 82  |d;kP)3.....c<...|
+000002e0  3b 7f bc 04 40 f1 33 64  4a 80 cd 01 f9 f4 c6 89  |;...@.3dJ.......|
+000002f0  65 27 25 f9 cf 4f 7e c8  6e d9 0e ec 47 4a 51 29  |e'%..O~.n...GJQ)|
+00000300  2f be 34 50 bd 9b d2 d8  b7 ea bb 0b a1 e0 20 1b  |/.4P.......... .|
+00000310  02 9c f2 17 03 03 00 99  61 dc 0b 3a 30 de 39 f6  |........a..:0.9.|
+00000320  f3 db f8 6c 3b fa 4e 1e  7e 62 a5 ae 73 ba e1 41  |...l;.N.~b..s..A|
+00000330  58 77 2a c1 7a 0c 50 bb  0c 57 b4 c4 25 bf 2f 9f  |Xw*.z.P..W..%./.|
+00000340  38 91 e2 65 22 9d ca ac  18 58 7e 81 2d fd 74 24  |8..e"....X~.-.t$|
+00000350  28 69 76 11 df 9d 23 b8  be ae 8b e0 93 8e 5d df  |(iv...#.......].|
+00000360  0a 64 d0 b7 02 68 aa 86  01 0d 55 11 3b 76 70 c6  |.d...h....U.;vp.|
+00000370  83 0c 5e 0a e3 37 a5 8b  ad 25 50 b9 e8 5c 6b 04  |..^..7...%P..\k.|
+00000380  b4 51 ec 9c d3 fa c6 b7  9c f0 46 aa 73 da 3c 0d  |.Q........F.s.<.|
+00000390  d3 bd 32 81 d4 d2 f1 1a  b0 92 f3 73 3e 54 2b 05  |..2........s>T+.|
+000003a0  92 24 34 75 df d6 18 a0  6a 82 95 4c 9b fc 7e b6  |.$4u....j..L..~.|
+000003b0  8e 17 03 03 00 35 8f 34  0e 3b 91 d8 e7 74 24 71  |.....5.4.;...t$q|
+000003c0  0e 7b f3 12 bb 76 2f 31  12 17 b8 9e 24 ce f9 2f  |.{...v/1....$../|
+000003d0  3f 5d f2 13 4b 2e 9b 1e  c4 78 03 a6 c8 07 11 a3  |?]..K....x......|
+000003e0  98 79 61 6e 4f 44 6e 18  ee c4 9b 17 03 03 00 93  |.yanODn.........|
+000003f0  64 dd 52 a9 d9 51 63 6a  a0 a3 c2 75 6b 5d 1d 54  |d.R..Qcj...uk].T|
+00000400  ce d4 53 7e 14 8e d9 26  93 28 78 65 16 1b 95 77  |..S~...&.(xe...w|
+00000410  68 0a 46 f1 82 36 bb 8a  fa 0d df 54 8c 3d 83 e0  |h.F..6.....T.=..|
+00000420  d7 de 2d 96 e9 c4 d7 22  d3 97 8e ae 90 f8 fc e6  |..-...."........|
+00000430  a6 4b 78 98 4c c5 28 87  91 46 fa f4 1c 8d 0e ec  |.Kx.L.(..F......|
+00000440  0d 71 40 9a 04 49 b4 e8  5b 62 6f cd 16 c1 d5 fb  |.q@..I..[bo.....|
+00000450  73 2a 96 8f e5 a2 f4 11  1e df 2d 40 45 6b d5 a9  |s*........-@Ek..|
+00000460  e4 e3 f7 93 fc fa d7 20  af d5 f7 b4 0e 09 ad d5  |....... ........|
+00000470  26 87 b8 6c e2 20 95 fb  c0 70 3e 38 be b7 b1 9f  |&..l. ...p>8....|
+00000480  70 da c1                                          |p..|
+>>> Flow 3 (client to server)
+00000000  14 03 03 00 01 01 17 03  03 00 35 29 d2 b9 bb 9b  |..........5)....|
+00000010  de 6c 5d 22 23 c1 fe 99  4c c5 33 bf fd 70 36 6b  |.l]"#...L.3..p6k|
+00000020  f1 a5 92 e8 bf 7c 3d 6e  ef 6a 44 73 bc cb 27 1c  |.....|=n.jDs..'.|
+00000030  09 5d bf 99 4c 19 24 c3  3b 30 91 b5 e3 b6 63 45  |.]..L.$.;0....cE|
+>>> Flow 4 (server to client)
+00000000  17 03 03 00 1e 52 55 85  7c b8 87 dd c7 b2 d9 5b  |.....RU.|......[|
+00000010  18 1d bb ac bf b6 ab 76  82 be 64 0e b2 7b 2c 0f  |.......v..d..{,.|
+00000020  aa 17 92 17 03 03 00 13  79 0a 60 b1 46 20 33 74  |........y.`.F 3t|
+00000030  ed 12 a0 23 de 68 88 fc  6f dd 8e                 |...#.h..o..|
index 0b5dc9b1c634243a821cb7aa4aa7ad4f94d8d113..b51ff258c5175d85cacc526b0734770fbc9a13b1 100644 (file)
@@ -1,9 +1,9 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 e2 01 00 00  de 03 03 ea ab 77 e1 48  |.............w.H|
-00000010  64 70 23 5c af b3 a7 3d  60 93 a0 30 0a 8c 98 61  |dp#\...=`..0...a|
-00000020  3a ab bc a9 11 c1 2f f5  ed d7 63 20 d4 29 26 9d  |:...../...c .)&.|
-00000030  64 37 72 d1 2c 7d 09 3b  94 67 f9 1c 19 c3 7e 17  |d7r.,}.;.g....~.|
-00000040  ec 80 5f 09 38 c1 15 4d  59 45 5c c3 00 04 13 03  |.._.8..MYE\.....|
+00000000  16 03 01 00 e2 01 00 00  de 03 03 9f 73 81 5f 56  |............s._V|
+00000010  a9 02 5f 8c 33 db dc 2a  92 d0 5e 7c e9 e6 01 d7  |.._.3..*..^|....|
+00000020  67 b6 bb 74 da bb d0 c1  11 08 20 20 9f bd d6 f8  |g..t......  ....|
+00000030  d7 8c e5 32 15 1d 4a 4c  36 ce 72 90 cb 68 ca dc  |...2..JL6.r..h..|
+00000040  ea b3 57 93 9a 12 e6 0e  9a bd 91 1a 00 04 13 03  |..W.............|
 00000050  00 ff 01 00 00 91 00 0b  00 04 03 00 01 02 00 0a  |................|
 00000060  00 0c 00 0a 00 1d 00 17  00 1e 00 19 00 18 00 23  |...............#|
 00000070  00 00 00 10 00 10 00 0e  06 70 72 6f 74 6f 32 06  |.........proto2.|
 00000090  00 1e 00 1c 04 03 05 03  06 03 08 07 08 08 08 09  |................|
 000000a0  08 0a 08 0b 08 04 08 05  08 06 04 01 05 01 06 01  |................|
 000000b0  00 2b 00 03 02 03 04 00  2d 00 02 01 01 00 33 00  |.+......-.....3.|
-000000c0  26 00 24 00 1d 00 20 68  64 e8 c1 4a c5 d5 b8 91  |&.$... hd..J....|
-000000d0  a0 20 c7 aa 8a 41 90 d6  d0 5e ed 6c ed e4 77 aa  |. ...A...^.l..w.|
-000000e0  ec 33 93 e3 d5 b7 55                              |.3....U|
+000000c0  26 00 24 00 1d 00 20 79  79 04 d3 03 58 93 22 5d  |&.$... yy...X."]|
+000000d0  06 69 1a 03 11 4e 65 e5  30 85 29 02 22 c8 11 6d  |.i...Ne.0.)."..m|
+000000e0  21 86 d4 4d 58 93 74                              |!..MX.t|
 >>> Flow 2 (server to client)
 00000000  16 03 03 00 7a 02 00 00  76 03 03 00 00 00 00 00  |....z...v.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 20 d4 29 26 9d  |........... .)&.|
-00000030  64 37 72 d1 2c 7d 09 3b  94 67 f9 1c 19 c3 7e 17  |d7r.,}.;.g....~.|
-00000040  ec 80 5f 09 38 c1 15 4d  59 45 5c c3 13 03 00 00  |.._.8..MYE\.....|
+00000020  00 00 00 00 00 00 00 00  00 00 00 20 9f bd d6 f8  |........... ....|
+00000030  d7 8c e5 32 15 1d 4a 4c  36 ce 72 90 cb 68 ca dc  |...2..JL6.r..h..|
+00000040  ea b3 57 93 9a 12 e6 0e  9a bd 91 1a 13 03 00 00  |..W.............|
 00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 2f  |..+.....3.$... /|
 00000060  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
 00000070  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74 14  |.........._X.;t.|
-00000080  03 03 00 01 01 17 03 03  00 17 c0 d3 a2 c3 42 b4  |..............B.|
-00000090  39 f1 b6 f1 0a ac f3 76  dd 36 15 eb d7 3b 3f 63  |9......v.6...;?c|
-000000a0  0b 17 03 03 02 6d f2 02  6d 15 de 46 b3 30 ef 57  |.....m..m..F.0.W|
-000000b0  e5 a3 35 11 5c c3 b4 2e  ad 74 ca db d2 90 eb b4  |..5.\....t......|
-000000c0  ba 14 7e b0 65 68 e8 31  76 2a 28 e4 be bb d1 c3  |..~.eh.1v*(.....|
-000000d0  45 cb ba 07 eb 27 d9 5e  4a 45 52 10 62 f0 8f b2  |E....'.^JER.b...|
-000000e0  7c ad 0f 63 5c 39 f7 6e  f2 68 3e bc fd ec fe fa  ||..c\9.n.h>.....|
-000000f0  9b ba 45 96 2b 94 27 34  2c 78 c8 5f 40 e3 f9 20  |..E.+.'4,x._@.. |
-00000100  51 15 3d dc 70 d1 50 7c  26 6b 51 3f 47 61 0b e6  |Q.=.p.P|&kQ?Ga..|
-00000110  04 ee 49 19 27 f0 91 c5  0f 15 0a 90 a6 0c 14 f2  |..I.'...........|
-00000120  2f f1 42 28 be a0 7a ce  16 14 bf ff 34 34 a8 d8  |/.B(..z.....44..|
-00000130  61 e6 26 6a 00 62 a0 82  53 c6 27 30 89 81 8d fb  |a.&j.b..S.'0....|
-00000140  9e 97 bc a0 ce 2f a1 e2  bf 9e fe d2 cc 11 4e 00  |...../........N.|
-00000150  89 d1 e8 3b ab 58 e4 66  0a 87 00 b1 c1 a0 2d b0  |...;.X.f......-.|
-00000160  96 b3 13 9b d3 c0 16 6b  87 e8 e3 9e 6c 30 1b 67  |.......k....l0.g|
-00000170  c1 53 a5 4b 55 44 4e 27  6e ea 7c 7d 9f 44 b4 ca  |.S.KUDN'n.|}.D..|
-00000180  15 6f e5 d1 7f 18 e4 12  66 2d d5 a2 47 0c 73 26  |.o......f-..G.s&|
-00000190  b0 bf 93 5b 46 9c 3f 78  69 05 a1 38 0f 61 ea d6  |...[F.?xi..8.a..|
-000001a0  61 97 80 c5 72 be 6d be  2d e5 a2 9e d8 b3 bf 8d  |a...r.m.-.......|
-000001b0  a4 53 ba 6d fe c8 8d ac  c1 4a 6e 76 bf 72 1e 5a  |.S.m.....Jnv.r.Z|
-000001c0  0a 51 f3 c8 1f 11 91 36  f0 f5 ba 68 e8 69 c3 77  |.Q.....6...h.i.w|
-000001d0  52 63 dc b3 93 80 0d fd  9a 7d 7f f8 47 f8 62 2a  |Rc.......}..G.b*|
-000001e0  3d 4f 1b 46 9f cb 07 b6  96 00 b1 08 e7 32 50 41  |=O.F.........2PA|
-000001f0  83 da 20 c2 b0 c0 33 33  3f f2 f9 84 f0 64 9f 37  |.. ...33?....d.7|
-00000200  4b b6 7b ab 2e e9 50 8b  6a 61 da 12 51 54 13 25  |K.{...P.ja..QT.%|
-00000210  46 5d 90 06 ef 88 4e be  64 67 80 02 1f 25 9c 28  |F]....N.dg...%.(|
-00000220  07 b3 24 2b 10 81 c1 72  7c 94 97 b3 5a 16 bc cf  |..$+...r|...Z...|
-00000230  52 44 41 2c d7 ba e9 9f  4c d7 28 e6 b7 bb b0 fd  |RDA,....L.(.....|
-00000240  17 b2 0b 83 33 ed 2f c7  2d 42 37 fd 0a d0 4b c7  |....3./.-B7...K.|
-00000250  97 61 17 d6 cd cd 0f e0  0d dd ab 40 fb 00 4d 81  |.a.........@..M.|
-00000260  da 7d 1d 0e 48 d9 a7 6c  ba 2a 21 49 18 0f a4 7c  |.}..H..l.*!I...||
-00000270  af 0d 1b ca 94 f1 6c 78  59 ad 50 e4 1c 7b 37 45  |......lxY.P..{7E|
-00000280  e8 1b 73 ad 96 8d 98 d6  07 26 07 fd a8 e6 8c 39  |..s......&.....9|
-00000290  f1 5a 10 ef 04 97 fe d3  be cb f2 c1 5b 27 e8 d0  |.Z..........['..|
-000002a0  f9 b3 16 b9 82 6d e8 be  54 c7 cf 44 a4 8a fd 75  |.....m..T..D...u|
-000002b0  96 2a f1 65 2b d3 8f f5  86 a3 bf 12 74 c1 e4 d8  |.*.e+.......t...|
-000002c0  a9 db c9 43 05 07 b1 51  dc 20 29 d0 c0 9a 6d 10  |...C...Q. )...m.|
-000002d0  83 5f 87 a6 ab 03 58 43  1f 35 1c af dd 37 10 1b  |._....XC.5...7..|
-000002e0  16 50 52 e5 3c f5 3c ae  4f 92 7e dc 47 2e b3 9c  |.PR.<.<.O.~.G...|
-000002f0  1f d2 a0 31 8b 32 21 35  52 af bd f1 0b 2c 4e 6f  |...1.2!5R....,No|
-00000300  59 32 d8 db d6 9f b8 bd  bc a0 3b 77 41 43 46 fb  |Y2........;wACF.|
-00000310  2b 0e 82 17 03 03 00 99  0a 63 cd 1f fa 90 4d 95  |+........c....M.|
-00000320  17 d8 81 36 5c 62 17 33  6c 8d 9d 9f 26 3e 3a 2f  |...6\b.3l...&>:/|
-00000330  65 84 23 56 46 25 f6 1c  dd ea 6f 21 b4 05 d8 19  |e.#VF%....o!....|
-00000340  a3 c9 4b b1 03 78 39 32  00 97 6c d5 6e e3 ff 45  |..K..x92..l.n..E|
-00000350  ac 2a 10 71 21 ad d3 b9  73 b7 77 0e a8 79 fd 50  |.*.q!...s.w..y.P|
-00000360  a9 f1 41 39 2d 05 3d 92  3c 69 0a d7 7d 11 da f0  |..A9-.=.<i..}...|
-00000370  fe 83 a6 c8 79 96 33 9c  df 12 1c 39 90 da d3 94  |....y.3....9....|
-00000380  7e 4a 5d 1c 31 b2 5c ea  33 2c 40 56 3a 80 86 0c  |~J].1.\.3,@V:...|
-00000390  93 bf 0f 56 b6 67 2e 4c  7f 9f 0c d5 58 9f 9d d6  |...V.g.L....X...|
-000003a0  db e1 74 13 eb 7c a6 a5  1a 65 64 37 66 74 68 3a  |..t..|...ed7fth:|
-000003b0  73 17 03 03 00 35 53 63  0b ce 12 f7 f5 39 1d 20  |s....5Sc.....9. |
-000003c0  41 89 5f a0 d2 fa 84 a3  2b e2 95 f4 9b e8 14 66  |A._.....+......f|
-000003d0  2c c7 01 ad e9 ba 6c 11  86 c9 00 93 49 c1 af 30  |,.....l.....I..0|
-000003e0  13 a7 59 16 a2 32 43 63  eb c2 64 17 03 03 00 93  |..Y..2Cc..d.....|
-000003f0  20 da 02 66 ca 8d fa b5  4d 6a 0d e7 c6 a9 7b e2  | ..f....Mj....{.|
-00000400  1c e8 61 c4 59 a2 30 f4  1b 27 c9 05 2e a1 33 93  |..a.Y.0..'....3.|
-00000410  43 8a 70 15 9b 26 19 e3  0a a6 31 d9 ce 46 f7 78  |C.p..&....1..F.x|
-00000420  bd 88 c4 ff 73 eb a0 3c  42 01 b0 6d 55 2c 61 7b  |....s..<B..mU,a{|
-00000430  d6 87 2f 50 6e 64 ae 73  69 a2 04 dc ec 3a e7 a5  |../Pnd.si....:..|
-00000440  5c 24 df eb e8 bc 7b b9  df 3e a4 d8 26 1a ff 4b  |\$....{..>..&..K|
-00000450  a6 ce 93 36 ea a1 fd d9  78 61 a3 0e 08 72 da 03  |...6....xa...r..|
-00000460  5d 0c 27 48 75 61 25 ef  77 39 39 e5 8e 87 2e 86  |].'Hua%.w99.....|
-00000470  d5 70 d3 3b f4 b4 75 b1  44 d1 5f fe 9c d8 18 7d  |.p.;..u.D._....}|
-00000480  f9 89 20                                          |.. |
->>> Flow 3 (client to server)
-00000000  14 03 03 00 01 01 17 03  03 00 35 a8 ab 13 71 ec  |..........5...q.|
-00000010  af a7 4a 48 65 6d 02 ea  8a 0f d1 4d 2a 97 b6 11  |..JHem.....M*...|
-00000020  6d 53 5f be a4 b3 a7 20  d4 d3 aa 90 62 30 26 3f  |mS_.... ....b0&?|
-00000030  be c8 ed fc 6f 44 cc a5  3a 7f 4d 95 51 ed dc 80  |....oD..:.M.Q...|
->>> Flow 4 (server to client)
-00000000  17 03 03 00 1e 6a f5 e4  df 1b 2a 5a 87 68 b1 a7  |.....j....*Z.h..|
-00000010  1d b8 ef 04 b4 ac b9 50  b3 95 1c 12 d7 44 ca 46  |.......P.....D.F|
-00000020  ea 26 2a 17 03 03 00 13  a4 6b 4d 27 81 62 b0 3c  |.&*......kM'.b.<|
-00000030  d0 be d1 34 46 4c 7b 6c  71 24 d8                 |...4FL{lq$.|
+00000080  03 03 00 01 01 17 03 03  00 13 7c ab 7f dd 94 cf  |..........|.....|
+00000090  d7 98 34 16 75 02 63 37  fa 4f 19 4e 18           |..4.u.c7.O.N.|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv13-ALPN-NotConfigured b/libgo/go/crypto/tls/testdata/Server-TLSv13-ALPN-NotConfigured
new file mode 100644 (file)
index 0000000..e0830d3
--- /dev/null
@@ -0,0 +1,100 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 e2 01 00 00  de 03 03 9f 49 a7 46 f8  |............I.F.|
+00000010  72 04 47 a1 8e 4f 89 c3  cd 89 92 2f 7a 8a 07 37  |r.G..O...../z..7|
+00000020  8c 25 10 42 26 07 8b a2  71 3e 92 20 4c 83 1b 70  |.%.B&...q>. L..p|
+00000030  45 c3 79 68 c3 83 a7 05  c2 22 06 c6 91 da 8b 96  |E.yh....."......|
+00000040  4c 9d 89 c2 ec b8 49 87  17 3f 6c ae 00 04 13 03  |L.....I..?l.....|
+00000050  00 ff 01 00 00 91 00 0b  00 04 03 00 01 02 00 0a  |................|
+00000060  00 0c 00 0a 00 1d 00 17  00 1e 00 19 00 18 00 23  |...............#|
+00000070  00 00 00 10 00 10 00 0e  06 70 72 6f 74 6f 32 06  |.........proto2.|
+00000080  70 72 6f 74 6f 31 00 16  00 00 00 17 00 00 00 0d  |proto1..........|
+00000090  00 1e 00 1c 04 03 05 03  06 03 08 07 08 08 08 09  |................|
+000000a0  08 0a 08 0b 08 04 08 05  08 06 04 01 05 01 06 01  |................|
+000000b0  00 2b 00 03 02 03 04 00  2d 00 02 01 01 00 33 00  |.+......-.....3.|
+000000c0  26 00 24 00 1d 00 20 f4  91 87 6a ac cd 25 5e f1  |&.$... ...j..%^.|
+000000d0  0d 25 fb af a4 d4 fb 16  32 63 af 04 2d 21 d7 2f  |.%......2c..-!./|
+000000e0  61 f2 c2 d4 c4 6c 2b                              |a....l+|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 7a 02 00 00  76 03 03 00 00 00 00 00  |....z...v.......|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 20 4c 83 1b 70  |........... L..p|
+00000030  45 c3 79 68 c3 83 a7 05  c2 22 06 c6 91 da 8b 96  |E.yh....."......|
+00000040  4c 9d 89 c2 ec b8 49 87  17 3f 6c ae 13 03 00 00  |L.....I..?l.....|
+00000050  2e 00 2b 00 02 03 04 00  33 00 24 00 1d 00 20 2f  |..+.....3.$... /|
+00000060  e5 7d a3 47 cd 62 43 15  28 da ac 5f bb 29 07 30  |.}.G.bC.(.._.).0|
+00000070  ff f6 84 af c4 cf c2 ed  90 99 5f 58 cb 3b 74 14  |.........._X.;t.|
+00000080  03 03 00 01 01 17 03 03  00 17 60 79 16 61 4f 6c  |..........`y.aOl|
+00000090  9e 2e ce fd cc f5 29 67  38 e7 53 67 92 b1 5f 9d  |......)g8.Sg.._.|
+000000a0  db 17 03 03 02 6d 54 d9  d6 a1 8e c2 1b 70 3f 3d  |.....mT......p?=|
+000000b0  a2 2e 0f a5 37 96 e1 68  66 69 cc f8 e9 06 4d bc  |....7..hfi....M.|
+000000c0  c2 9a 6e 0f ea d4 73 59  6a 59 28 79 7f 44 0c 32  |..n...sYjY(y.D.2|
+000000d0  29 22 51 d1 fb 00 c7 33  44 8b 19 71 98 8a 03 44  |)"Q....3D..q...D|
+000000e0  e0 95 ad 8f 91 66 e6 15  b8 99 b3 f8 2f 02 e9 a0  |.....f....../...|
+000000f0  4a 25 ec 3f 36 56 0c eb  0a a3 e0 d3 79 a1 b3 9e  |J%.?6V......y...|
+00000100  dc 42 08 76 a4 c3 55 91  06 11 e7 0c 94 dd 71 fc  |.B.v..U.......q.|
+00000110  bf 8a 87 d2 97 07 a3 b9  36 7e 58 ff ef b3 a3 f4  |........6~X.....|
+00000120  6e f1 23 d6 50 e3 23 d3  dc e7 20 ce 9d 84 17 cf  |n.#.P.#... .....|
+00000130  2d 5f b1 f9 8d 36 41 7d  ba 3b 93 63 2f bc be f0  |-_...6A}.;.c/...|
+00000140  a1 3a bb 5f b3 99 03 13  fb d2 2c 1a 8c cc 32 02  |.:._......,...2.|
+00000150  ef 93 b4 58 a8 f8 b1 42  52 24 c2 73 01 cb 5a fb  |...X...BR$.s..Z.|
+00000160  9f fc 38 08 d7 f9 0d d7  20 fa dc 8b 1a 8c 73 0f  |..8..... .....s.|
+00000170  f8 79 b2 84 e1 49 2d 8e  6d 46 16 38 0e 02 2a 2c  |.y...I-.mF.8..*,|
+00000180  f4 44 89 da f1 7a 01 55  9e 93 a8 d6 d5 f5 72 28  |.D...z.U......r(|
+00000190  47 2b 4f 17 7e a5 01 fd  ad 85 e0 6d f9 82 e8 cd  |G+O.~......m....|
+000001a0  09 18 84 8c 9d 4f 4e a1  43 ff d6 3d 55 05 fc 56  |.....ON.C..=U..V|
+000001b0  e6 d6 b6 61 4a c7 c7 9c  62 64 26 1d 33 1e 4f d5  |...aJ...bd&.3.O.|
+000001c0  5e ee 1f a9 ad 24 e4 7f  05 cc 02 7a f7 e0 c2 ce  |^....$.....z....|
+000001d0  b8 11 c9 a1 fd c5 d8 0e  ef f8 c9 6a 2d 49 30 63  |...........j-I0c|
+000001e0  e3 9b 43 bf 87 e1 5f 55  39 fa 80 ec 84 55 59 5d  |..C..._U9....UY]|
+000001f0  52 76 4c f4 70 eb 43 6a  b2 07 d5 29 4c 58 39 04  |RvL.p.Cj...)LX9.|
+00000200  46 42 70 8d 28 61 7c d5  7a 3a 2e a0 9f 74 49 2d  |FBp.(a|.z:...tI-|
+00000210  33 8d 39 18 70 8d 3c 50  4f 62 07 77 2d 15 1f 4b  |3.9.p.<POb.w-..K|
+00000220  22 01 c6 cb ac 2f 2d 9a  cf a6 9b 0e 24 99 41 64  |"..../-.....$.Ad|
+00000230  3e f2 9f 5f 17 7b d7 b8  3c b6 6d 24 5b 91 8c 13  |>.._.{..<.m$[...|
+00000240  1a 40 4e 80 7f 44 12 57  c9 03 57 c6 9b 54 0d 39  |.@N..D.W..W..T.9|
+00000250  91 88 72 3e c8 f9 18 eb  34 7c 0a eb 2d c8 56 1c  |..r>....4|..-.V.|
+00000260  84 8a 62 a2 3a 0a 52 b8  5a b6 5d 54 78 ae 05 b2  |..b.:.R.Z.]Tx...|
+00000270  f4 6c 2d 5e 92 94 6b f3  1e 93 13 1a 65 74 60 e3  |.l-^..k.....et`.|
+00000280  dd 15 36 62 2b 71 b1 bb  59 19 08 af 8e 9b d0 47  |..6b+q..Y......G|
+00000290  05 7b a3 89 ac 68 cf a0  32 ba 4a 2b 9e 5f a5 dc  |.{...h..2.J+._..|
+000002a0  b3 00 79 a8 1c f6 11 b8  6d 9c 51 b7 f1 f6 b2 13  |..y.....m.Q.....|
+000002b0  56 57 4e ac 97 ff 5a b8  52 33 0c c1 3d 52 81 6e  |VWN...Z.R3..=R.n|
+000002c0  85 ba b2 04 4b eb 41 aa  03 ff ae 63 93 72 3a 5f  |....K.A....c.r:_|
+000002d0  65 81 f9 6a 2a e4 70 f8  b3 59 31 51 62 ad 25 24  |e..j*.p..Y1Qb.%$|
+000002e0  82 0c b5 ad 7c 87 21 97  07 c0 c1 6d f0 22 97 0d  |....|.!....m."..|
+000002f0  28 cf a7 4d 74 d2 9c ac  d7 15 83 26 f7 2f 76 d4  |(..Mt......&./v.|
+00000300  ad cf e7 ef 1c f4 3e 1f  b4 f4 4f 76 6a 98 15 01  |......>...Ovj...|
+00000310  cd 17 8b 17 03 03 00 99  0b 15 9d 16 c6 2a 52 53  |.............*RS|
+00000320  33 d7 01 db 8a 49 1d d6  83 b7 28 a4 07 f0 73 5e  |3....I....(...s^|
+00000330  60 03 2c 6f 3f e0 88 a1  76 22 d6 23 0a df ca 86  |`.,o?...v".#....|
+00000340  b0 44 b9 1d 9a d7 53 f2  2b 57 a1 65 01 d4 e7 b4  |.D....S.+W.e....|
+00000350  9e 22 00 d2 20 da cd 55  7d 61 86 86 19 81 f9 ed  |.".. ..U}a......|
+00000360  f8 af c4 69 54 1d 35 0a  6f 9e 69 40 13 08 82 dd  |...iT.5.o.i@....|
+00000370  59 11 31 f2 81 a7 4b f1  bd d9 f2 5c 29 22 16 49  |Y.1...K....\)".I|
+00000380  86 62 8c a8 b8 89 58 96  cc d1 e4 e8 5e ef 6c b7  |.b....X.....^.l.|
+00000390  00 71 3d ab 92 b8 78 56  a7 25 5e a0 c4 d8 8c 02  |.q=...xV.%^.....|
+000003a0  c4 c8 eb d3 be 68 21 05  5c 5f 9c b0 ec 20 99 ff  |.....h!.\_... ..|
+000003b0  00 17 03 03 00 35 c9 c1  5e 25 1c b9 64 8e c2 fd  |.....5..^%..d...|
+000003c0  50 87 48 e6 02 36 75 31  67 f6 82 3c 94 79 7d 0b  |P.H..6u1g..<.y}.|
+000003d0  cb 83 b1 f4 e1 00 5f a6  b6 2c 2d 63 40 ab 98 f9  |......_..,-c@...|
+000003e0  e3 8e 4a 7e d4 77 3d 55  90 10 75 17 03 03 00 93  |..J~.w=U..u.....|
+000003f0  47 c4 6e 19 29 c2 5e d5  93 b7 c2 cc 46 a9 49 9d  |G.n.).^.....F.I.|
+00000400  8a 3b 9a 35 bb 45 22 13  b6 eb c9 ec ba 44 3c 24  |.;.5.E"......D<$|
+00000410  f2 ed bd 76 11 cc af 00  b3 89 63 5d 79 32 cc d7  |...v......c]y2..|
+00000420  5c 34 f3 5e 64 36 92 5d  ac ac 33 74 f4 3d c4 b8  |\4.^d6.]..3t.=..|
+00000430  4d ac d0 49 4e 59 1c 16  74 8c 43 94 4b 13 b9 22  |M..INY..t.C.K.."|
+00000440  de d7 ee 30 09 63 f3 32  5f a2 9d a1 20 ea ee 91  |...0.c.2_... ...|
+00000450  ca d8 01 33 df 43 19 69  63 ee 6a 2c 80 99 ad f0  |...3.C.ic.j,....|
+00000460  5e 20 b6 b6 81 28 b6 9d  4a 9a 91 30 30 04 c1 70  |^ ...(..J..00..p|
+00000470  68 54 1e e0 72 00 4c fd  23 a8 41 a2 6a ab a3 01  |hT..r.L.#.A.j...|
+00000480  7a 40 1a                                          |z@.|
+>>> Flow 3 (client to server)
+00000000  14 03 03 00 01 01 17 03  03 00 35 20 1f 0d 20 a8  |..........5 .. .|
+00000010  34 c4 dc fa f9 d6 2b fe  01 eb f1 54 f0 14 c2 2d  |4.....+....T...-|
+00000020  bb 59 db 04 96 f2 18 8b  bd 7e b0 38 b7 15 b5 d8  |.Y.......~.8....|
+00000030  6b f2 80 25 40 f6 97 67  fb 9e 5a 5c ad 33 c6 5f  |k..%@..g..Z\.3._|
+>>> Flow 4 (server to client)
+00000000  17 03 03 00 1e 3a 8a fc  60 3a 99 ee b6 01 b7 fe  |.....:..`:......|
+00000010  54 a9 2d 34 28 ae af 3b  6a bd e0 32 6b df 87 fe  |T.-4(..;j..2k...|
+00000020  d0 97 8d 17 03 03 00 13  c6 89 d5 ae 4c fa d5 71  |............L..q|
+00000030  66 6e 07 b5 9b 00 e8 50  7e b9 5f                 |fn.....P~._|
index a389873d32ed1156ab1b03802aec73c59c2a1d85..b529c705237bbd8df526d6549583dda34b6232d0 100644 (file)
@@ -25,7 +25,6 @@ import (
        "net"
        "os"
        "strings"
-       "time"
 )
 
 // Server returns a new TLS server side connection
@@ -111,33 +110,24 @@ func (timeoutError) Temporary() bool { return true }
 //
 // DialWithDialer interprets a nil configuration as equivalent to the zero
 // configuration; see the documentation of Config for the defaults.
+//
+// DialWithDialer uses context.Background internally; to specify the context,
+// use Dialer.DialContext with NetDialer set to the desired dialer.
 func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*Conn, error) {
        return dial(context.Background(), dialer, network, addr, config)
 }
 
 func dial(ctx context.Context, netDialer *net.Dialer, network, addr string, config *Config) (*Conn, error) {
-       // We want the Timeout and Deadline values from dialer to cover the
-       // whole process: TCP connection and TLS handshake. This means that we
-       // also need to start our own timers now.
-       timeout := netDialer.Timeout
-
-       if !netDialer.Deadline.IsZero() {
-               deadlineTimeout := time.Until(netDialer.Deadline)
-               if timeout == 0 || deadlineTimeout < timeout {
-                       timeout = deadlineTimeout
-               }
+       if netDialer.Timeout != 0 {
+               var cancel context.CancelFunc
+               ctx, cancel = context.WithTimeout(ctx, netDialer.Timeout)
+               defer cancel()
        }
 
-       // hsErrCh is non-nil if we might not wait for Handshake to complete.
-       var hsErrCh chan error
-       if timeout != 0 || ctx.Done() != nil {
-               hsErrCh = make(chan error, 2)
-       }
-       if timeout != 0 {
-               timer := time.AfterFunc(timeout, func() {
-                       hsErrCh <- timeoutError{}
-               })
-               defer timer.Stop()
+       if !netDialer.Deadline.IsZero() {
+               var cancel context.CancelFunc
+               ctx, cancel = context.WithDeadline(ctx, netDialer.Deadline)
+               defer cancel()
        }
 
        rawConn, err := netDialer.DialContext(ctx, network, addr)
@@ -164,34 +154,10 @@ func dial(ctx context.Context, netDialer *net.Dialer, network, addr string, conf
        }
 
        conn := Client(rawConn, config)
-
-       if hsErrCh == nil {
-               err = conn.Handshake()
-       } else {
-               go func() {
-                       hsErrCh <- conn.Handshake()
-               }()
-
-               select {
-               case <-ctx.Done():
-                       err = ctx.Err()
-               case err = <-hsErrCh:
-                       if err != nil {
-                               // If the error was due to the context
-                               // closing, prefer the context's error, rather
-                               // than some random network teardown error.
-                               if e := ctx.Err(); e != nil {
-                                       err = e
-                               }
-                       }
-               }
-       }
-
-       if err != nil {
+       if err := conn.HandshakeContext(ctx); err != nil {
                rawConn.Close()
                return nil, err
        }
-
        return conn, nil
 }
 
@@ -224,6 +190,9 @@ type Dialer struct {
 // handshake, returning the resulting TLS connection.
 //
 // The returned Conn, if any, will always be of type *Conn.
+//
+// Dial uses context.Background internally; to specify the context,
+// use DialContext.
 func (d *Dialer) Dial(network, addr string) (net.Conn, error) {
        return d.DialContext(context.Background(), network, addr)
 }
index 9995538871e35d40e8350c91d29795ec0d8fa679..d8a43add1796f6ff4a04a6a5136097746effd59a 100644 (file)
@@ -18,6 +18,7 @@ import (
        "net"
        "os"
        "reflect"
+       "sort"
        "strings"
        "testing"
        "time"
@@ -1383,7 +1384,7 @@ func TestCipherSuites(t *testing.T) {
                }
        }
 
-       cipherSuiteByID := func(id uint16) *CipherSuite {
+       CipherSuiteByID := func(id uint16) *CipherSuite {
                for _, c := range CipherSuites() {
                        if c.ID == id {
                                return c
@@ -1398,15 +1399,12 @@ func TestCipherSuites(t *testing.T) {
        }
 
        for _, c := range cipherSuites {
-               cc := cipherSuiteByID(c.id)
+               cc := CipherSuiteByID(c.id)
                if cc == nil {
                        t.Errorf("%#04x: no CipherSuite entry", c.id)
                        continue
                }
 
-               if defaultOff := c.flags&suiteDefaultOff != 0; defaultOff != cc.Insecure {
-                       t.Errorf("%#04x: Insecure %v, expected %v", c.id, cc.Insecure, defaultOff)
-               }
                if tls12Only := c.flags&suiteTLS12 != 0; tls12Only && len(cc.SupportedVersions) != 1 {
                        t.Errorf("%#04x: suite is TLS 1.2 only, but SupportedVersions is %v", c.id, cc.SupportedVersions)
                } else if !tls12Only && len(cc.SupportedVersions) != 3 {
@@ -1418,7 +1416,7 @@ func TestCipherSuites(t *testing.T) {
                }
        }
        for _, c := range cipherSuitesTLS13 {
-               cc := cipherSuiteByID(c.id)
+               cc := CipherSuiteByID(c.id)
                if cc == nil {
                        t.Errorf("%#04x: no CipherSuite entry", c.id)
                        continue
@@ -1439,6 +1437,143 @@ func TestCipherSuites(t *testing.T) {
        if got := CipherSuiteName(0xabc); got != "0x0ABC" {
                t.Errorf("unexpected fallback CipherSuiteName: got %q, expected 0x0ABC", got)
        }
+
+       if len(cipherSuitesPreferenceOrder) != len(cipherSuites) {
+               t.Errorf("cipherSuitesPreferenceOrder is not the same size as cipherSuites")
+       }
+       if len(cipherSuitesPreferenceOrderNoAES) != len(cipherSuitesPreferenceOrder) {
+               t.Errorf("cipherSuitesPreferenceOrderNoAES is not the same size as cipherSuitesPreferenceOrder")
+       }
+
+       // Check that disabled suites are at the end of the preference lists, and
+       // that they are marked insecure.
+       for i, id := range disabledCipherSuites {
+               offset := len(cipherSuitesPreferenceOrder) - len(disabledCipherSuites)
+               if cipherSuitesPreferenceOrder[offset+i] != id {
+                       t.Errorf("disabledCipherSuites[%d]: not at the end of cipherSuitesPreferenceOrder", i)
+               }
+               if cipherSuitesPreferenceOrderNoAES[offset+i] != id {
+                       t.Errorf("disabledCipherSuites[%d]: not at the end of cipherSuitesPreferenceOrderNoAES", i)
+               }
+               c := CipherSuiteByID(id)
+               if c == nil {
+                       t.Errorf("%#04x: no CipherSuite entry", id)
+                       continue
+               }
+               if !c.Insecure {
+                       t.Errorf("%#04x: disabled by default but not marked insecure", id)
+               }
+       }
+
+       for i, prefOrder := range [][]uint16{cipherSuitesPreferenceOrder, cipherSuitesPreferenceOrderNoAES} {
+               // Check that insecure and HTTP/2 bad cipher suites are at the end of
+               // the preference lists.
+               var sawInsecure, sawBad bool
+               for _, id := range prefOrder {
+                       c := CipherSuiteByID(id)
+                       if c == nil {
+                               t.Errorf("%#04x: no CipherSuite entry", id)
+                               continue
+                       }
+
+                       if c.Insecure {
+                               sawInsecure = true
+                       } else if sawInsecure {
+                               t.Errorf("%#04x: secure suite after insecure one(s)", id)
+                       }
+
+                       if http2isBadCipher(id) {
+                               sawBad = true
+                       } else if sawBad {
+                               t.Errorf("%#04x: non-bad suite after bad HTTP/2 one(s)", id)
+                       }
+               }
+
+               // Check that the list is sorted according to the documented criteria.
+               isBetter := func(a, b int) bool {
+                       aSuite, bSuite := cipherSuiteByID(prefOrder[a]), cipherSuiteByID(prefOrder[b])
+                       aName, bName := CipherSuiteName(prefOrder[a]), CipherSuiteName(prefOrder[b])
+                       // * < RC4
+                       if !strings.Contains(aName, "RC4") && strings.Contains(bName, "RC4") {
+                               return true
+                       } else if strings.Contains(aName, "RC4") && !strings.Contains(bName, "RC4") {
+                               return false
+                       }
+                       // * < CBC_SHA256
+                       if !strings.Contains(aName, "CBC_SHA256") && strings.Contains(bName, "CBC_SHA256") {
+                               return true
+                       } else if strings.Contains(aName, "CBC_SHA256") && !strings.Contains(bName, "CBC_SHA256") {
+                               return false
+                       }
+                       // * < 3DES
+                       if !strings.Contains(aName, "3DES") && strings.Contains(bName, "3DES") {
+                               return true
+                       } else if strings.Contains(aName, "3DES") && !strings.Contains(bName, "3DES") {
+                               return false
+                       }
+                       // ECDHE < *
+                       if aSuite.flags&suiteECDHE != 0 && bSuite.flags&suiteECDHE == 0 {
+                               return true
+                       } else if aSuite.flags&suiteECDHE == 0 && bSuite.flags&suiteECDHE != 0 {
+                               return false
+                       }
+                       // AEAD < CBC
+                       if aSuite.aead != nil && bSuite.aead == nil {
+                               return true
+                       } else if aSuite.aead == nil && bSuite.aead != nil {
+                               return false
+                       }
+                       // AES < ChaCha20
+                       if strings.Contains(aName, "AES") && strings.Contains(bName, "CHACHA20") {
+                               return i == 0 // true for cipherSuitesPreferenceOrder
+                       } else if strings.Contains(aName, "CHACHA20") && strings.Contains(bName, "AES") {
+                               return i != 0 // true for cipherSuitesPreferenceOrderNoAES
+                       }
+                       // AES-128 < AES-256
+                       if strings.Contains(aName, "AES_128") && strings.Contains(bName, "AES_256") {
+                               return true
+                       } else if strings.Contains(aName, "AES_256") && strings.Contains(bName, "AES_128") {
+                               return false
+                       }
+                       // ECDSA < RSA
+                       if aSuite.flags&suiteECSign != 0 && bSuite.flags&suiteECSign == 0 {
+                               return true
+                       } else if aSuite.flags&suiteECSign == 0 && bSuite.flags&suiteECSign != 0 {
+                               return false
+                       }
+                       t.Fatalf("two ciphersuites are equal by all criteria: %v and %v", aName, bName)
+                       panic("unreachable")
+               }
+               if !sort.SliceIsSorted(prefOrder, isBetter) {
+                       t.Error("preference order is not sorted according to the rules")
+               }
+       }
+}
+
+// http2isBadCipher is copied from net/http.
+// TODO: if it ends up exposed somewhere, use that instead.
+func http2isBadCipher(cipher uint16) bool {
+       switch cipher {
+       case TLS_RSA_WITH_RC4_128_SHA,
+               TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+               TLS_RSA_WITH_AES_128_CBC_SHA,
+               TLS_RSA_WITH_AES_256_CBC_SHA,
+               TLS_RSA_WITH_AES_128_CBC_SHA256,
+               TLS_RSA_WITH_AES_128_GCM_SHA256,
+               TLS_RSA_WITH_AES_256_GCM_SHA384,
+               TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+               TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+               TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+               TLS_ECDHE_RSA_WITH_RC4_128_SHA,
+               TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
+               TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+               TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+               TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+               TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+               return true
+       default:
+               return false
+       }
 }
 
 type brokenSigner struct{ crypto.Signer }
index 9b776d4b8571e99a111eaf61852c4faf317e79c1..fcfbc1e561573d9ae59a7a4feb0704de5e06d975 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin && !ios
 // +build darwin,!ios
 
 // Package macOS provides cgo-less wrappers for Core Foundation and
@@ -11,6 +12,7 @@ package macOS
 
 import (
        "errors"
+       "internal/abi"
        "reflect"
        "runtime"
        "unsafe"
@@ -39,24 +41,22 @@ type CFString CFRef
 const kCFAllocatorDefault = 0
 const kCFStringEncodingUTF8 = 0x08000100
 
-//go:linkname x509_CFStringCreateWithBytes x509_CFStringCreateWithBytes
 //go:cgo_import_dynamic x509_CFStringCreateWithBytes CFStringCreateWithBytes "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
 
 // StringToCFString returns a copy of the UTF-8 contents of s as a new CFString.
 func StringToCFString(s string) CFString {
        p := unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&s)).Data)
-       ret := syscall(funcPC(x509_CFStringCreateWithBytes_trampoline), kCFAllocatorDefault, uintptr(p),
+       ret := syscall(abi.FuncPCABI0(x509_CFStringCreateWithBytes_trampoline), kCFAllocatorDefault, uintptr(p),
                uintptr(len(s)), uintptr(kCFStringEncodingUTF8), 0 /* isExternalRepresentation */, 0)
        runtime.KeepAlive(p)
        return CFString(ret)
 }
 func x509_CFStringCreateWithBytes_trampoline()
 
-//go:linkname x509_CFDictionaryGetValueIfPresent x509_CFDictionaryGetValueIfPresent
 //go:cgo_import_dynamic x509_CFDictionaryGetValueIfPresent CFDictionaryGetValueIfPresent "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
 
 func CFDictionaryGetValueIfPresent(dict CFRef, key CFString) (value CFRef, ok bool) {
-       ret := syscall(funcPC(x509_CFDictionaryGetValueIfPresent_trampoline), uintptr(dict), uintptr(key),
+       ret := syscall(abi.FuncPCABI0(x509_CFDictionaryGetValueIfPresent_trampoline), uintptr(dict), uintptr(key),
                uintptr(unsafe.Pointer(&value)), 0, 0, 0)
        if ret == 0 {
                return 0, false
@@ -67,12 +67,11 @@ func x509_CFDictionaryGetValueIfPresent_trampoline()
 
 const kCFNumberSInt32Type = 3
 
-//go:linkname x509_CFNumberGetValue x509_CFNumberGetValue
 //go:cgo_import_dynamic x509_CFNumberGetValue CFNumberGetValue "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
 
 func CFNumberGetValue(num CFRef) (int32, error) {
        var value int32
-       ret := syscall(funcPC(x509_CFNumberGetValue_trampoline), uintptr(num), uintptr(kCFNumberSInt32Type),
+       ret := syscall(abi.FuncPCABI0(x509_CFNumberGetValue_trampoline), uintptr(num), uintptr(kCFNumberSInt32Type),
                uintptr(unsafe.Pointer(&value)), 0, 0, 0)
        if ret == 0 {
                return 0, errors.New("CFNumberGetValue call failed")
@@ -81,65 +80,52 @@ func CFNumberGetValue(num CFRef) (int32, error) {
 }
 func x509_CFNumberGetValue_trampoline()
 
-//go:linkname x509_CFDataGetLength x509_CFDataGetLength
 //go:cgo_import_dynamic x509_CFDataGetLength CFDataGetLength "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
 
 func CFDataGetLength(data CFRef) int {
-       ret := syscall(funcPC(x509_CFDataGetLength_trampoline), uintptr(data), 0, 0, 0, 0, 0)
+       ret := syscall(abi.FuncPCABI0(x509_CFDataGetLength_trampoline), uintptr(data), 0, 0, 0, 0, 0)
        return int(ret)
 }
 func x509_CFDataGetLength_trampoline()
 
-//go:linkname x509_CFDataGetBytePtr x509_CFDataGetBytePtr
 //go:cgo_import_dynamic x509_CFDataGetBytePtr CFDataGetBytePtr "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
 
 func CFDataGetBytePtr(data CFRef) uintptr {
-       ret := syscall(funcPC(x509_CFDataGetBytePtr_trampoline), uintptr(data), 0, 0, 0, 0, 0)
+       ret := syscall(abi.FuncPCABI0(x509_CFDataGetBytePtr_trampoline), uintptr(data), 0, 0, 0, 0, 0)
        return ret
 }
 func x509_CFDataGetBytePtr_trampoline()
 
-//go:linkname x509_CFArrayGetCount x509_CFArrayGetCount
 //go:cgo_import_dynamic x509_CFArrayGetCount CFArrayGetCount "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
 
 func CFArrayGetCount(array CFRef) int {
-       ret := syscall(funcPC(x509_CFArrayGetCount_trampoline), uintptr(array), 0, 0, 0, 0, 0)
+       ret := syscall(abi.FuncPCABI0(x509_CFArrayGetCount_trampoline), uintptr(array), 0, 0, 0, 0, 0)
        return int(ret)
 }
 func x509_CFArrayGetCount_trampoline()
 
-//go:linkname x509_CFArrayGetValueAtIndex x509_CFArrayGetValueAtIndex
 //go:cgo_import_dynamic x509_CFArrayGetValueAtIndex CFArrayGetValueAtIndex "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
 
 func CFArrayGetValueAtIndex(array CFRef, index int) CFRef {
-       ret := syscall(funcPC(x509_CFArrayGetValueAtIndex_trampoline), uintptr(array), uintptr(index), 0, 0, 0, 0)
+       ret := syscall(abi.FuncPCABI0(x509_CFArrayGetValueAtIndex_trampoline), uintptr(array), uintptr(index), 0, 0, 0, 0)
        return CFRef(ret)
 }
 func x509_CFArrayGetValueAtIndex_trampoline()
 
-//go:linkname x509_CFEqual x509_CFEqual
 //go:cgo_import_dynamic x509_CFEqual CFEqual "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
 
 func CFEqual(a, b CFRef) bool {
-       ret := syscall(funcPC(x509_CFEqual_trampoline), uintptr(a), uintptr(b), 0, 0, 0, 0)
+       ret := syscall(abi.FuncPCABI0(x509_CFEqual_trampoline), uintptr(a), uintptr(b), 0, 0, 0, 0)
        return ret == 1
 }
 func x509_CFEqual_trampoline()
 
-//go:linkname x509_CFRelease x509_CFRelease
 //go:cgo_import_dynamic x509_CFRelease CFRelease "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
 
 func CFRelease(ref CFRef) {
-       syscall(funcPC(x509_CFRelease_trampoline), uintptr(ref), 0, 0, 0, 0, 0)
+       syscall(abi.FuncPCABI0(x509_CFRelease_trampoline), uintptr(ref), 0, 0, 0, 0, 0)
 }
 func x509_CFRelease_trampoline()
 
 // syscall is implemented in the runtime package (runtime/sys_darwin.go)
 func syscall(fn, a1, a2, a3, a4, a5, a6 uintptr) uintptr
-
-// funcPC returns the entry point for f. See comments in runtime/proc.go
-// for the function of the same name.
-//go:nosplit
-func funcPC(f func()) uintptr {
-       return **(**uintptr)(unsafe.Pointer(&f))
-}
index 5e39e936666292b44ebbedd87ba22faac4690da3..0f6fa42b7bf61baad76663f566719297bc953d6c 100644 (file)
@@ -2,12 +2,14 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin && !ios
 // +build darwin,!ios
 
 package macOS
 
 import (
        "errors"
+       "internal/abi"
        "strconv"
        "unsafe"
 )
@@ -63,11 +65,10 @@ var ErrNoTrustSettings = errors.New("no trust settings found")
 
 const errSecNoTrustSettings = -25263
 
-//go:linkname x509_SecTrustSettingsCopyCertificates x509_SecTrustSettingsCopyCertificates
 //go:cgo_import_dynamic x509_SecTrustSettingsCopyCertificates SecTrustSettingsCopyCertificates "/System/Library/Frameworks/Security.framework/Versions/A/Security"
 
 func SecTrustSettingsCopyCertificates(domain SecTrustSettingsDomain) (certArray CFRef, err error) {
-       ret := syscall(funcPC(x509_SecTrustSettingsCopyCertificates_trampoline), uintptr(domain),
+       ret := syscall(abi.FuncPCABI0(x509_SecTrustSettingsCopyCertificates_trampoline), uintptr(domain),
                uintptr(unsafe.Pointer(&certArray)), 0, 0, 0, 0)
        if int32(ret) == errSecNoTrustSettings {
                return 0, ErrNoTrustSettings
@@ -80,11 +81,10 @@ func x509_SecTrustSettingsCopyCertificates_trampoline()
 
 const kSecFormatX509Cert int32 = 9
 
-//go:linkname x509_SecItemExport x509_SecItemExport
 //go:cgo_import_dynamic x509_SecItemExport SecItemExport "/System/Library/Frameworks/Security.framework/Versions/A/Security"
 
 func SecItemExport(cert CFRef) (data CFRef, err error) {
-       ret := syscall(funcPC(x509_SecItemExport_trampoline), uintptr(cert), uintptr(kSecFormatX509Cert),
+       ret := syscall(abi.FuncPCABI0(x509_SecItemExport_trampoline), uintptr(cert), uintptr(kSecFormatX509Cert),
                0 /* flags */, 0 /* keyParams */, uintptr(unsafe.Pointer(&data)), 0)
        if ret != 0 {
                return 0, OSStatus{"SecItemExport", int32(ret)}
@@ -95,11 +95,10 @@ func x509_SecItemExport_trampoline()
 
 const errSecItemNotFound = -25300
 
-//go:linkname x509_SecTrustSettingsCopyTrustSettings x509_SecTrustSettingsCopyTrustSettings
 //go:cgo_import_dynamic x509_SecTrustSettingsCopyTrustSettings SecTrustSettingsCopyTrustSettings "/System/Library/Frameworks/Security.framework/Versions/A/Security"
 
 func SecTrustSettingsCopyTrustSettings(cert CFRef, domain SecTrustSettingsDomain) (trustSettings CFRef, err error) {
-       ret := syscall(funcPC(x509_SecTrustSettingsCopyTrustSettings_trampoline), uintptr(cert), uintptr(domain),
+       ret := syscall(abi.FuncPCABI0(x509_SecTrustSettingsCopyTrustSettings_trampoline), uintptr(cert), uintptr(domain),
                uintptr(unsafe.Pointer(&trustSettings)), 0, 0, 0)
        if int32(ret) == errSecItemNotFound {
                return 0, ErrNoTrustSettings
@@ -110,11 +109,10 @@ func SecTrustSettingsCopyTrustSettings(cert CFRef, domain SecTrustSettingsDomain
 }
 func x509_SecTrustSettingsCopyTrustSettings_trampoline()
 
-//go:linkname x509_SecPolicyCopyProperties x509_SecPolicyCopyProperties
 //go:cgo_import_dynamic x509_SecPolicyCopyProperties SecPolicyCopyProperties "/System/Library/Frameworks/Security.framework/Versions/A/Security"
 
 func SecPolicyCopyProperties(policy CFRef) CFRef {
-       ret := syscall(funcPC(x509_SecPolicyCopyProperties_trampoline), uintptr(policy), 0, 0, 0, 0, 0)
+       ret := syscall(abi.FuncPCABI0(x509_SecPolicyCopyProperties_trampoline), uintptr(policy), 0, 0, 0, 0, 0)
        return CFRef(ret)
 }
 func x509_SecPolicyCopyProperties_trampoline()
index 3826c82c380437ce638fa8ccae88f736839e91b6..c59a7dc1a62c7343fbc7126a9a965a6613b4e548 100644 (file)
@@ -614,7 +614,8 @@ var nameConstraintsTests = []nameConstraintsTest{
                },
        },
 
-       // #30: without SANs, a certificate with a CN is rejected in a constrained chain.
+       // #30: without SANs, a certificate with a CN is still accepted in a
+       // constrained chain, since we ignore the CN in VerifyHostname.
        {
                roots: []constraintsSpec{
                        {
@@ -630,7 +631,6 @@ var nameConstraintsTests = []nameConstraintsTest{
                        sans: []string{},
                        cn:   "foo.com",
                },
-               expectedError: "leaf doesn't have a SAN extension",
        },
 
        // #31: IPv6 addresses work in constraints: roots can permit them as
@@ -1595,26 +1595,6 @@ var nameConstraintsTests = []nameConstraintsTest{
                        cn:   "foo.bar",
                },
        },
-
-       // #85: without SANs, a certificate with a valid CN is accepted in a
-       // constrained chain if x509ignoreCN is set.
-       {
-               roots: []constraintsSpec{
-                       {
-                               ok: []string{"dns:foo.com", "dns:.foo.com"},
-                       },
-               },
-               intermediates: [][]constraintsSpec{
-                       {
-                               {},
-                       },
-               },
-               leaf: leafSpec{
-                       sans: []string{},
-                       cn:   "foo.com",
-               },
-               ignoreCN: true,
-       },
 }
 
 func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) {
@@ -1865,10 +1845,6 @@ func parseEKUs(ekuStrs []string) (ekus []ExtKeyUsage, unknowns []asn1.ObjectIden
 }
 
 func TestConstraintCases(t *testing.T) {
-       defer func(savedIgnoreCN bool) {
-               ignoreCN = savedIgnoreCN
-       }(ignoreCN)
-
        privateKeys := sync.Pool{
                New: func() interface{} {
                        priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
@@ -1960,7 +1936,6 @@ func TestConstraintCases(t *testing.T) {
                        }
                }
 
-               ignoreCN = test.ignoreCN
                verifyOpts := VerifyOptions{
                        Roots:         rootPool,
                        Intermediates: intermediatePool,
@@ -1999,7 +1974,6 @@ func TestConstraintCases(t *testing.T) {
                for _, key := range keys {
                        privateKeys.Put(key)
                }
-               keys = keys[:0]
        }
 }
 
diff --git a/libgo/go/crypto/x509/parser.go b/libgo/go/crypto/x509/parser.go
new file mode 100644 (file)
index 0000000..f085162
--- /dev/null
@@ -0,0 +1,1006 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+package x509
+
+import (
+       "bytes"
+       "crypto/dsa"
+       "crypto/ecdsa"
+       "crypto/ed25519"
+       "crypto/elliptic"
+       "crypto/rsa"
+       "crypto/x509/pkix"
+       "encoding/asn1"
+       "errors"
+       "fmt"
+       "math/big"
+       "net"
+       "net/url"
+       "strconv"
+       "strings"
+       "time"
+       "unicode/utf16"
+       "unicode/utf8"
+
+       "golang.org/x/crypto/cryptobyte"
+       cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1"
+)
+
+// isPrintable reports whether the given b is in the ASN.1 PrintableString set.
+// This is a simplified version of encoding/asn1.isPrintable.
+func isPrintable(b byte) bool {
+       return 'a' <= b && b <= 'z' ||
+               'A' <= b && b <= 'Z' ||
+               '0' <= b && b <= '9' ||
+               '\'' <= b && b <= ')' ||
+               '+' <= b && b <= '/' ||
+               b == ' ' ||
+               b == ':' ||
+               b == '=' ||
+               b == '?' ||
+               // This is technically not allowed in a PrintableString.
+               // However, x509 certificates with wildcard strings don't
+               // always use the correct string type so we permit it.
+               b == '*' ||
+               // This is not technically allowed either. However, not
+               // only is it relatively common, but there are also a
+               // handful of CA certificates that contain it. At least
+               // one of which will not expire until 2027.
+               b == '&'
+}
+
+// parseASN1String parses the ASN.1 string types T61String, PrintableString,
+// UTF8String, BMPString, and IA5String. This is mostly copied from the
+// respective encoding/asn1.parse... methods, rather than just increasing
+// the API surface of that package.
+func parseASN1String(tag cryptobyte_asn1.Tag, value []byte) (string, error) {
+       switch tag {
+       case cryptobyte_asn1.T61String:
+               return string(value), nil
+       case cryptobyte_asn1.PrintableString:
+               for _, b := range value {
+                       if !isPrintable(b) {
+                               return "", errors.New("invalid PrintableString")
+                       }
+               }
+               return string(value), nil
+       case cryptobyte_asn1.UTF8String:
+               if !utf8.Valid(value) {
+                       return "", errors.New("invalid UTF-8 string")
+               }
+               return string(value), nil
+       case cryptobyte_asn1.Tag(asn1.TagBMPString):
+               if len(value)%2 != 0 {
+                       return "", errors.New("invalid BMPString")
+               }
+
+               // Strip terminator if present.
+               if l := len(value); l >= 2 && value[l-1] == 0 && value[l-2] == 0 {
+                       value = value[:l-2]
+               }
+
+               s := make([]uint16, 0, len(value)/2)
+               for len(value) > 0 {
+                       s = append(s, uint16(value[0])<<8+uint16(value[1]))
+                       value = value[2:]
+               }
+
+               return string(utf16.Decode(s)), nil
+       case cryptobyte_asn1.IA5String:
+               s := string(value)
+               if isIA5String(s) != nil {
+                       return "", errors.New("invalid IA5String")
+               }
+               return s, nil
+       }
+       return "", fmt.Errorf("unsupported string type: %v", tag)
+}
+
+// parseName parses a DER encoded Name as defined in RFC 5280. We may
+// want to export this function in the future for use in crypto/tls.
+func parseName(raw cryptobyte.String) (*pkix.RDNSequence, error) {
+       if !raw.ReadASN1(&raw, cryptobyte_asn1.SEQUENCE) {
+               return nil, errors.New("x509: invalid RDNSequence")
+       }
+
+       var rdnSeq pkix.RDNSequence
+       for !raw.Empty() {
+               var rdnSet pkix.RelativeDistinguishedNameSET
+               var set cryptobyte.String
+               if !raw.ReadASN1(&set, cryptobyte_asn1.SET) {
+                       return nil, errors.New("x509: invalid RDNSequence")
+               }
+               for !set.Empty() {
+                       var atav cryptobyte.String
+                       if !set.ReadASN1(&atav, cryptobyte_asn1.SEQUENCE) {
+                               return nil, errors.New("x509: invalid RDNSequence: invalid attribute")
+                       }
+                       var attr pkix.AttributeTypeAndValue
+                       if !atav.ReadASN1ObjectIdentifier(&attr.Type) {
+                               return nil, errors.New("x509: invalid RDNSequence: invalid attribute type")
+                       }
+                       var rawValue cryptobyte.String
+                       var valueTag cryptobyte_asn1.Tag
+                       if !atav.ReadAnyASN1(&rawValue, &valueTag) {
+                               return nil, errors.New("x509: invalid RDNSequence: invalid attribute value")
+                       }
+                       var err error
+                       attr.Value, err = parseASN1String(valueTag, rawValue)
+                       if err != nil {
+                               return nil, fmt.Errorf("x509: invalid RDNSequence: invalid attribute value: %s", err)
+                       }
+                       rdnSet = append(rdnSet, attr)
+               }
+
+               rdnSeq = append(rdnSeq, rdnSet)
+       }
+
+       return &rdnSeq, nil
+}
+
+func parseAI(der cryptobyte.String) (pkix.AlgorithmIdentifier, error) {
+       ai := pkix.AlgorithmIdentifier{}
+       if !der.ReadASN1ObjectIdentifier(&ai.Algorithm) {
+               return ai, errors.New("x509: malformed OID")
+       }
+       if der.Empty() {
+               return ai, nil
+       }
+       var params cryptobyte.String
+       var tag cryptobyte_asn1.Tag
+       if !der.ReadAnyASN1Element(&params, &tag) {
+               return ai, errors.New("x509: malformed parameters")
+       }
+       ai.Parameters.Tag = int(tag)
+       ai.Parameters.FullBytes = params
+       return ai, nil
+}
+
+func parseValidity(der cryptobyte.String) (time.Time, time.Time, error) {
+       extract := func() (time.Time, error) {
+               var t time.Time
+               switch {
+               case der.PeekASN1Tag(cryptobyte_asn1.UTCTime):
+                       // TODO(rolandshoemaker): once #45411 is fixed, the following code
+                       // should be replaced with a call to der.ReadASN1UTCTime.
+                       var utc cryptobyte.String
+                       if !der.ReadASN1(&utc, cryptobyte_asn1.UTCTime) {
+                               return t, errors.New("x509: malformed UTCTime")
+                       }
+                       s := string(utc)
+
+                       formatStr := "0601021504Z0700"
+                       var err error
+                       t, err = time.Parse(formatStr, s)
+                       if err != nil {
+                               formatStr = "060102150405Z0700"
+                               t, err = time.Parse(formatStr, s)
+                       }
+                       if err != nil {
+                               return t, err
+                       }
+
+                       if serialized := t.Format(formatStr); serialized != s {
+                               return t, errors.New("x509: malformed UTCTime")
+                       }
+
+                       if t.Year() >= 2050 {
+                               // UTCTime only encodes times prior to 2050. See https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1
+                               t = t.AddDate(-100, 0, 0)
+                       }
+               case der.PeekASN1Tag(cryptobyte_asn1.GeneralizedTime):
+                       if !der.ReadASN1GeneralizedTime(&t) {
+                               return t, errors.New("x509: malformed GeneralizedTime")
+                       }
+               default:
+                       return t, errors.New("x509: unsupported time format")
+               }
+               return t, nil
+       }
+
+       notBefore, err := extract()
+       if err != nil {
+               return time.Time{}, time.Time{}, err
+       }
+       notAfter, err := extract()
+       if err != nil {
+               return time.Time{}, time.Time{}, err
+       }
+
+       return notBefore, notAfter, nil
+}
+
+func parseExtension(der cryptobyte.String) (pkix.Extension, error) {
+       var ext pkix.Extension
+       if !der.ReadASN1ObjectIdentifier(&ext.Id) {
+               return ext, errors.New("x509: malformed extention OID field")
+       }
+       if der.PeekASN1Tag(cryptobyte_asn1.BOOLEAN) {
+               if !der.ReadASN1Boolean(&ext.Critical) {
+                       return ext, errors.New("x509: malformed extention critical field")
+               }
+       }
+       var val cryptobyte.String
+       if !der.ReadASN1(&val, cryptobyte_asn1.OCTET_STRING) {
+               return ext, errors.New("x509: malformed extention value field")
+       }
+       ext.Value = val
+       return ext, nil
+}
+
+func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{}, error) {
+       der := cryptobyte.String(keyData.PublicKey.RightAlign())
+       switch algo {
+       case RSA:
+               // RSA public keys must have a NULL in the parameters.
+               // See RFC 3279, Section 2.3.1.
+               if !bytes.Equal(keyData.Algorithm.Parameters.FullBytes, asn1.NullBytes) {
+                       return nil, errors.New("x509: RSA key missing NULL parameters")
+               }
+
+               p := &pkcs1PublicKey{N: new(big.Int)}
+               if !der.ReadASN1(&der, cryptobyte_asn1.SEQUENCE) {
+                       return nil, errors.New("x509: invalid RSA public key")
+               }
+               if !der.ReadASN1Integer(p.N) {
+                       return nil, errors.New("x509: invalid RSA modulus")
+               }
+               if !der.ReadASN1Integer(&p.E) {
+                       return nil, errors.New("x509: invalid RSA public exponent")
+               }
+
+               if p.N.Sign() <= 0 {
+                       return nil, errors.New("x509: RSA modulus is not a positive number")
+               }
+               if p.E <= 0 {
+                       return nil, errors.New("x509: RSA public exponent is not a positive number")
+               }
+
+               pub := &rsa.PublicKey{
+                       E: p.E,
+                       N: p.N,
+               }
+               return pub, nil
+       case ECDSA:
+               paramsDer := cryptobyte.String(keyData.Algorithm.Parameters.FullBytes)
+               namedCurveOID := new(asn1.ObjectIdentifier)
+               if !paramsDer.ReadASN1ObjectIdentifier(namedCurveOID) {
+                       return nil, errors.New("x509: invalid ECDSA parameters")
+               }
+               namedCurve := namedCurveFromOID(*namedCurveOID)
+               if namedCurve == nil {
+                       return nil, errors.New("x509: unsupported elliptic curve")
+               }
+               x, y := elliptic.Unmarshal(namedCurve, der)
+               if x == nil {
+                       return nil, errors.New("x509: failed to unmarshal elliptic curve point")
+               }
+               pub := &ecdsa.PublicKey{
+                       Curve: namedCurve,
+                       X:     x,
+                       Y:     y,
+               }
+               return pub, nil
+       case Ed25519:
+               // RFC 8410, Section 3
+               // > For all of the OIDs, the parameters MUST be absent.
+               if len(keyData.Algorithm.Parameters.FullBytes) != 0 {
+                       return nil, errors.New("x509: Ed25519 key encoded with illegal parameters")
+               }
+               if len(der) != ed25519.PublicKeySize {
+                       return nil, errors.New("x509: wrong Ed25519 public key size")
+               }
+               return ed25519.PublicKey(der), nil
+       case DSA:
+               y := new(big.Int)
+               if !der.ReadASN1Integer(y) {
+                       return nil, errors.New("x509: invalid DSA public key")
+               }
+               pub := &dsa.PublicKey{
+                       Y: y,
+                       Parameters: dsa.Parameters{
+                               P: new(big.Int),
+                               Q: new(big.Int),
+                               G: new(big.Int),
+                       },
+               }
+               paramsDer := cryptobyte.String(keyData.Algorithm.Parameters.FullBytes)
+               if !paramsDer.ReadASN1(&paramsDer, cryptobyte_asn1.SEQUENCE) ||
+                       !paramsDer.ReadASN1Integer(pub.Parameters.P) ||
+                       !paramsDer.ReadASN1Integer(pub.Parameters.Q) ||
+                       !paramsDer.ReadASN1Integer(pub.Parameters.G) {
+                       return nil, errors.New("x509: invalid DSA parameters")
+               }
+               if pub.Y.Sign() <= 0 || pub.Parameters.P.Sign() <= 0 ||
+                       pub.Parameters.Q.Sign() <= 0 || pub.Parameters.G.Sign() <= 0 {
+                       return nil, errors.New("x509: zero or negative DSA parameter")
+               }
+               return pub, nil
+       default:
+               return nil, nil
+       }
+}
+
+func parseKeyUsageExtension(der cryptobyte.String) (KeyUsage, error) {
+       var usageBits asn1.BitString
+       if !der.ReadASN1BitString(&usageBits) {
+               return 0, errors.New("x509: invalid key usage")
+       }
+
+       var usage int
+       for i := 0; i < 9; i++ {
+               if usageBits.At(i) != 0 {
+                       usage |= 1 << uint(i)
+               }
+       }
+       return KeyUsage(usage), nil
+}
+
+func parseBasicConstraintsExtension(der cryptobyte.String) (bool, int, error) {
+       var isCA bool
+       if !der.ReadASN1(&der, cryptobyte_asn1.SEQUENCE) {
+               return false, 0, errors.New("x509: invalid basic constraints a")
+       }
+       if der.PeekASN1Tag(cryptobyte_asn1.BOOLEAN) {
+               if !der.ReadASN1Boolean(&isCA) {
+                       return false, 0, errors.New("x509: invalid basic constraints b")
+               }
+       }
+       maxPathLen := -1
+       if !der.Empty() && der.PeekASN1Tag(cryptobyte_asn1.INTEGER) {
+               if !der.ReadASN1Integer(&maxPathLen) {
+                       return false, 0, errors.New("x509: invalid basic constraints c")
+               }
+       }
+
+       // TODO: map out.MaxPathLen to 0 if it has the -1 default value? (Issue 19285)
+       return isCA, maxPathLen, nil
+}
+
+func forEachSAN(der cryptobyte.String, callback func(tag int, data []byte) error) error {
+       if !der.ReadASN1(&der, cryptobyte_asn1.SEQUENCE) {
+               return errors.New("x509: invalid subject alternative names")
+       }
+       for !der.Empty() {
+               var san cryptobyte.String
+               var tag cryptobyte_asn1.Tag
+               if !der.ReadAnyASN1(&san, &tag) {
+                       return errors.New("x509: invalid subject alternative name")
+               }
+               if err := callback(int(tag^0x80), san); err != nil {
+                       return err
+               }
+       }
+
+       return nil
+}
+
+func parseSANExtension(der cryptobyte.String) (dnsNames, emailAddresses []string, ipAddresses []net.IP, uris []*url.URL, err error) {
+       err = forEachSAN(der, func(tag int, data []byte) error {
+               switch tag {
+               case nameTypeEmail:
+                       email := string(data)
+                       if err := isIA5String(email); err != nil {
+                               return errors.New("x509: SAN rfc822Name is malformed")
+                       }
+                       emailAddresses = append(emailAddresses, email)
+               case nameTypeDNS:
+                       name := string(data)
+                       if err := isIA5String(name); err != nil {
+                               return errors.New("x509: SAN dNSName is malformed")
+                       }
+                       dnsNames = append(dnsNames, string(name))
+               case nameTypeURI:
+                       uriStr := string(data)
+                       if err := isIA5String(uriStr); err != nil {
+                               return errors.New("x509: SAN uniformResourceIdentifier is malformed")
+                       }
+                       uri, err := url.Parse(uriStr)
+                       if err != nil {
+                               return fmt.Errorf("x509: cannot parse URI %q: %s", uriStr, err)
+                       }
+                       if len(uri.Host) > 0 {
+                               if _, ok := domainToReverseLabels(uri.Host); !ok {
+                                       return fmt.Errorf("x509: cannot parse URI %q: invalid domain", uriStr)
+                               }
+                       }
+                       uris = append(uris, uri)
+               case nameTypeIP:
+                       switch len(data) {
+                       case net.IPv4len, net.IPv6len:
+                               ipAddresses = append(ipAddresses, data)
+                       default:
+                               return errors.New("x509: cannot parse IP address of length " + strconv.Itoa(len(data)))
+                       }
+               }
+
+               return nil
+       })
+
+       return
+}
+
+func parseExtKeyUsageExtension(der cryptobyte.String) ([]ExtKeyUsage, []asn1.ObjectIdentifier, error) {
+       var extKeyUsages []ExtKeyUsage
+       var unknownUsages []asn1.ObjectIdentifier
+       if !der.ReadASN1(&der, cryptobyte_asn1.SEQUENCE) {
+               return nil, nil, errors.New("x509: invalid extended key usages")
+       }
+       for !der.Empty() {
+               var eku asn1.ObjectIdentifier
+               if !der.ReadASN1ObjectIdentifier(&eku) {
+                       return nil, nil, errors.New("x509: invalid extended key usages")
+               }
+               if extKeyUsage, ok := extKeyUsageFromOID(eku); ok {
+                       extKeyUsages = append(extKeyUsages, extKeyUsage)
+               } else {
+                       unknownUsages = append(unknownUsages, eku)
+               }
+       }
+       return extKeyUsages, unknownUsages, nil
+}
+
+func parseCertificatePoliciesExtension(der cryptobyte.String) ([]asn1.ObjectIdentifier, error) {
+       var oids []asn1.ObjectIdentifier
+       if !der.ReadASN1(&der, cryptobyte_asn1.SEQUENCE) {
+               return nil, errors.New("x509: invalid certificate policies")
+       }
+       for !der.Empty() {
+               var cp cryptobyte.String
+               if !der.ReadASN1(&cp, cryptobyte_asn1.SEQUENCE) {
+                       return nil, errors.New("x509: invalid certificate policies")
+               }
+               var oid asn1.ObjectIdentifier
+               if !cp.ReadASN1ObjectIdentifier(&oid) {
+                       return nil, errors.New("x509: invalid certificate policies")
+               }
+               oids = append(oids, oid)
+       }
+
+       return oids, nil
+}
+
+// isValidIPMask reports whether mask consists of zero or more 1 bits, followed by zero bits.
+func isValidIPMask(mask []byte) bool {
+       seenZero := false
+
+       for _, b := range mask {
+               if seenZero {
+                       if b != 0 {
+                               return false
+                       }
+
+                       continue
+               }
+
+               switch b {
+               case 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe:
+                       seenZero = true
+               case 0xff:
+               default:
+                       return false
+               }
+       }
+
+       return true
+}
+
+func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandled bool, err error) {
+       // RFC 5280, 4.2.1.10
+
+       // NameConstraints ::= SEQUENCE {
+       //      permittedSubtrees       [0]     GeneralSubtrees OPTIONAL,
+       //      excludedSubtrees        [1]     GeneralSubtrees OPTIONAL }
+       //
+       // GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
+       //
+       // GeneralSubtree ::= SEQUENCE {
+       //      base                    GeneralName,
+       //      minimum         [0]     BaseDistance DEFAULT 0,
+       //      maximum         [1]     BaseDistance OPTIONAL }
+       //
+       // BaseDistance ::= INTEGER (0..MAX)
+
+       outer := cryptobyte.String(e.Value)
+       var toplevel, permitted, excluded cryptobyte.String
+       var havePermitted, haveExcluded bool
+       if !outer.ReadASN1(&toplevel, cryptobyte_asn1.SEQUENCE) ||
+               !outer.Empty() ||
+               !toplevel.ReadOptionalASN1(&permitted, &havePermitted, cryptobyte_asn1.Tag(0).ContextSpecific().Constructed()) ||
+               !toplevel.ReadOptionalASN1(&excluded, &haveExcluded, cryptobyte_asn1.Tag(1).ContextSpecific().Constructed()) ||
+               !toplevel.Empty() {
+               return false, errors.New("x509: invalid NameConstraints extension")
+       }
+
+       if !havePermitted && !haveExcluded || len(permitted) == 0 && len(excluded) == 0 {
+               // From RFC 5280, Section 4.2.1.10:
+               //   “either the permittedSubtrees field
+               //   or the excludedSubtrees MUST be
+               //   present”
+               return false, errors.New("x509: empty name constraints extension")
+       }
+
+       getValues := func(subtrees cryptobyte.String) (dnsNames []string, ips []*net.IPNet, emails, uriDomains []string, err error) {
+               for !subtrees.Empty() {
+                       var seq, value cryptobyte.String
+                       var tag cryptobyte_asn1.Tag
+                       if !subtrees.ReadASN1(&seq, cryptobyte_asn1.SEQUENCE) ||
+                               !seq.ReadAnyASN1(&value, &tag) {
+                               return nil, nil, nil, nil, fmt.Errorf("x509: invalid NameConstraints extension")
+                       }
+
+                       var (
+                               dnsTag   = cryptobyte_asn1.Tag(2).ContextSpecific()
+                               emailTag = cryptobyte_asn1.Tag(1).ContextSpecific()
+                               ipTag    = cryptobyte_asn1.Tag(7).ContextSpecific()
+                               uriTag   = cryptobyte_asn1.Tag(6).ContextSpecific()
+                       )
+
+                       switch tag {
+                       case dnsTag:
+                               domain := string(value)
+                               if err := isIA5String(domain); err != nil {
+                                       return nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + err.Error())
+                               }
+
+                               trimmedDomain := domain
+                               if len(trimmedDomain) > 0 && trimmedDomain[0] == '.' {
+                                       // constraints can have a leading
+                                       // period to exclude the domain
+                                       // itself, but that's not valid in a
+                                       // normal domain name.
+                                       trimmedDomain = trimmedDomain[1:]
+                               }
+                               if _, ok := domainToReverseLabels(trimmedDomain); !ok {
+                                       return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse dnsName constraint %q", domain)
+                               }
+                               dnsNames = append(dnsNames, domain)
+
+                       case ipTag:
+                               l := len(value)
+                               var ip, mask []byte
+
+                               switch l {
+                               case 8:
+                                       ip = value[:4]
+                                       mask = value[4:]
+
+                               case 32:
+                                       ip = value[:16]
+                                       mask = value[16:]
+
+                               default:
+                                       return nil, nil, nil, nil, fmt.Errorf("x509: IP constraint contained value of length %d", l)
+                               }
+
+                               if !isValidIPMask(mask) {
+                                       return nil, nil, nil, nil, fmt.Errorf("x509: IP constraint contained invalid mask %x", mask)
+                               }
+
+                               ips = append(ips, &net.IPNet{IP: net.IP(ip), Mask: net.IPMask(mask)})
+
+                       case emailTag:
+                               constraint := string(value)
+                               if err := isIA5String(constraint); err != nil {
+                                       return nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + err.Error())
+                               }
+
+                               // If the constraint contains an @ then
+                               // it specifies an exact mailbox name.
+                               if strings.Contains(constraint, "@") {
+                                       if _, ok := parseRFC2821Mailbox(constraint); !ok {
+                                               return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse rfc822Name constraint %q", constraint)
+                                       }
+                               } else {
+                                       // Otherwise it's a domain name.
+                                       domain := constraint
+                                       if len(domain) > 0 && domain[0] == '.' {
+                                               domain = domain[1:]
+                                       }
+                                       if _, ok := domainToReverseLabels(domain); !ok {
+                                               return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse rfc822Name constraint %q", constraint)
+                                       }
+                               }
+                               emails = append(emails, constraint)
+
+                       case uriTag:
+                               domain := string(value)
+                               if err := isIA5String(domain); err != nil {
+                                       return nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + err.Error())
+                               }
+
+                               if net.ParseIP(domain) != nil {
+                                       return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse URI constraint %q: cannot be IP address", domain)
+                               }
+
+                               trimmedDomain := domain
+                               if len(trimmedDomain) > 0 && trimmedDomain[0] == '.' {
+                                       // constraints can have a leading
+                                       // period to exclude the domain itself,
+                                       // but that's not valid in a normal
+                                       // domain name.
+                                       trimmedDomain = trimmedDomain[1:]
+                               }
+                               if _, ok := domainToReverseLabels(trimmedDomain); !ok {
+                                       return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse URI constraint %q", domain)
+                               }
+                               uriDomains = append(uriDomains, domain)
+
+                       default:
+                               unhandled = true
+                       }
+               }
+
+               return dnsNames, ips, emails, uriDomains, nil
+       }
+
+       if out.PermittedDNSDomains, out.PermittedIPRanges, out.PermittedEmailAddresses, out.PermittedURIDomains, err = getValues(permitted); err != nil {
+               return false, err
+       }
+       if out.ExcludedDNSDomains, out.ExcludedIPRanges, out.ExcludedEmailAddresses, out.ExcludedURIDomains, err = getValues(excluded); err != nil {
+               return false, err
+       }
+       out.PermittedDNSDomainsCritical = e.Critical
+
+       return unhandled, nil
+}
+
+func processExtensions(out *Certificate) error {
+       var err error
+       for _, e := range out.Extensions {
+               unhandled := false
+
+               if len(e.Id) == 4 && e.Id[0] == 2 && e.Id[1] == 5 && e.Id[2] == 29 {
+                       switch e.Id[3] {
+                       case 15:
+                               out.KeyUsage, err = parseKeyUsageExtension(e.Value)
+                               if err != nil {
+                                       return err
+                               }
+                       case 19:
+                               out.IsCA, out.MaxPathLen, err = parseBasicConstraintsExtension(e.Value)
+                               if err != nil {
+                                       return err
+                               }
+                               out.BasicConstraintsValid = true
+                               out.MaxPathLenZero = out.MaxPathLen == 0
+                       case 17:
+                               out.DNSNames, out.EmailAddresses, out.IPAddresses, out.URIs, err = parseSANExtension(e.Value)
+                               if err != nil {
+                                       return err
+                               }
+
+                               if len(out.DNSNames) == 0 && len(out.EmailAddresses) == 0 && len(out.IPAddresses) == 0 && len(out.URIs) == 0 {
+                                       // If we didn't parse anything then we do the critical check, below.
+                                       unhandled = true
+                               }
+
+                       case 30:
+                               unhandled, err = parseNameConstraintsExtension(out, e)
+                               if err != nil {
+                                       return err
+                               }
+
+                       case 31:
+                               // RFC 5280, 4.2.1.13
+
+                               // CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
+                               //
+                               // DistributionPoint ::= SEQUENCE {
+                               //     distributionPoint       [0]     DistributionPointName OPTIONAL,
+                               //     reasons                 [1]     ReasonFlags OPTIONAL,
+                               //     cRLIssuer               [2]     GeneralNames OPTIONAL }
+                               //
+                               // DistributionPointName ::= CHOICE {
+                               //     fullName                [0]     GeneralNames,
+                               //     nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
+                               val := cryptobyte.String(e.Value)
+                               if !val.ReadASN1(&val, cryptobyte_asn1.SEQUENCE) {
+                                       return errors.New("x509: invalid CRL distribution points")
+                               }
+                               for !val.Empty() {
+                                       var dpDER cryptobyte.String
+                                       if !val.ReadASN1(&dpDER, cryptobyte_asn1.SEQUENCE) {
+                                               return errors.New("x509: invalid CRL distribution point")
+                                       }
+                                       var dpNameDER cryptobyte.String
+                                       var dpNamePresent bool
+                                       if !dpDER.ReadOptionalASN1(&dpNameDER, &dpNamePresent, cryptobyte_asn1.Tag(0).Constructed().ContextSpecific()) {
+                                               return errors.New("x509: invalid CRL distribution point")
+                                       }
+                                       if !dpNamePresent {
+                                               continue
+                                       }
+                                       if !dpNameDER.ReadASN1(&dpNameDER, cryptobyte_asn1.Tag(0).Constructed().ContextSpecific()) {
+                                               return errors.New("x509: invalid CRL distribution point")
+                                       }
+                                       for !dpNameDER.Empty() {
+                                               if !dpNameDER.PeekASN1Tag(cryptobyte_asn1.Tag(6).ContextSpecific()) {
+                                                       break
+                                               }
+                                               var uri cryptobyte.String
+                                               if !dpNameDER.ReadASN1(&uri, cryptobyte_asn1.Tag(6).ContextSpecific()) {
+                                                       return errors.New("x509: invalid CRL distribution point")
+                                               }
+                                               out.CRLDistributionPoints = append(out.CRLDistributionPoints, string(uri))
+                                       }
+                               }
+
+                       case 35:
+                               // RFC 5280, 4.2.1.1
+                               val := cryptobyte.String(e.Value)
+                               var akid cryptobyte.String
+                               if !val.ReadASN1(&akid, cryptobyte_asn1.SEQUENCE) {
+                                       return errors.New("x509: invalid authority key identifier")
+                               }
+                               if akid.PeekASN1Tag(cryptobyte_asn1.Tag(0).ContextSpecific()) {
+                                       if !akid.ReadASN1(&akid, cryptobyte_asn1.Tag(0).ContextSpecific()) {
+                                               return errors.New("x509: invalid authority key identifier")
+                                       }
+                                       out.AuthorityKeyId = akid
+                               }
+                       case 37:
+                               out.ExtKeyUsage, out.UnknownExtKeyUsage, err = parseExtKeyUsageExtension(e.Value)
+                               if err != nil {
+                                       return err
+                               }
+                       case 14:
+                               // RFC 5280, 4.2.1.2
+                               val := cryptobyte.String(e.Value)
+                               var skid cryptobyte.String
+                               if !val.ReadASN1(&skid, cryptobyte_asn1.OCTET_STRING) {
+                                       return errors.New("x509: invalid subject key identifier")
+                               }
+                               out.SubjectKeyId = skid
+                       case 32:
+                               out.PolicyIdentifiers, err = parseCertificatePoliciesExtension(e.Value)
+                               if err != nil {
+                                       return err
+                               }
+                       default:
+                               // Unknown extensions are recorded if critical.
+                               unhandled = true
+                       }
+               } else if e.Id.Equal(oidExtensionAuthorityInfoAccess) {
+                       // RFC 5280 4.2.2.1: Authority Information Access
+                       val := cryptobyte.String(e.Value)
+                       if !val.ReadASN1(&val, cryptobyte_asn1.SEQUENCE) {
+                               return errors.New("x509: invalid authority info access")
+                       }
+                       for !val.Empty() {
+                               var aiaDER cryptobyte.String
+                               if !val.ReadASN1(&aiaDER, cryptobyte_asn1.SEQUENCE) {
+                                       return errors.New("x509: invalid authority info access")
+                               }
+                               var method asn1.ObjectIdentifier
+                               if !aiaDER.ReadASN1ObjectIdentifier(&method) {
+                                       return errors.New("x509: invalid authority info access")
+                               }
+                               if !aiaDER.PeekASN1Tag(cryptobyte_asn1.Tag(6).ContextSpecific()) {
+                                       continue
+                               }
+                               if !aiaDER.ReadASN1(&aiaDER, cryptobyte_asn1.Tag(6).ContextSpecific()) {
+                                       return errors.New("x509: invalid authority info access")
+                               }
+                               switch {
+                               case method.Equal(oidAuthorityInfoAccessOcsp):
+                                       out.OCSPServer = append(out.OCSPServer, string(aiaDER))
+                               case method.Equal(oidAuthorityInfoAccessIssuers):
+                                       out.IssuingCertificateURL = append(out.IssuingCertificateURL, string(aiaDER))
+                               }
+                       }
+               } else {
+                       // Unknown extensions are recorded if critical.
+                       unhandled = true
+               }
+
+               if e.Critical && unhandled {
+                       out.UnhandledCriticalExtensions = append(out.UnhandledCriticalExtensions, e.Id)
+               }
+       }
+
+       return nil
+}
+
+func parseCertificate(der []byte) (*Certificate, error) {
+       cert := &Certificate{}
+
+       input := cryptobyte.String(der)
+       // we read the SEQUENCE including length and tag bytes so that
+       // we can populate Certificate.Raw, before unwrapping the
+       // SEQUENCE so it can be operated on
+       if !input.ReadASN1Element(&input, cryptobyte_asn1.SEQUENCE) {
+               return nil, errors.New("x509: malformed certificate")
+       }
+       cert.Raw = input
+       if !input.ReadASN1(&input, cryptobyte_asn1.SEQUENCE) {
+               return nil, errors.New("x509: malformed certificate")
+       }
+
+       var tbs cryptobyte.String
+       // do the same trick again as above to extract the raw
+       // bytes for Certificate.RawTBSCertificate
+       if !input.ReadASN1Element(&tbs, cryptobyte_asn1.SEQUENCE) {
+               return nil, errors.New("x509: malformed tbs certificate")
+       }
+       cert.RawTBSCertificate = tbs
+       if !tbs.ReadASN1(&tbs, cryptobyte_asn1.SEQUENCE) {
+               return nil, errors.New("x509: malformed tbs certificate")
+       }
+
+       if !tbs.ReadOptionalASN1Integer(&cert.Version, cryptobyte_asn1.Tag(0).Constructed().ContextSpecific(), 0) {
+               return nil, errors.New("x509: malformed version")
+       }
+       if cert.Version < 0 {
+               return nil, errors.New("x509: malformed version")
+       }
+       // for backwards compat reasons Version is one-indexed,
+       // rather than zero-indexed as defined in 5280
+       cert.Version++
+       if cert.Version > 3 {
+               return nil, errors.New("x509: invalid version")
+       }
+
+       serial := new(big.Int)
+       if !tbs.ReadASN1Integer(serial) {
+               return nil, errors.New("x509: malformed serial number")
+       }
+       // we ignore the presence of negative serial numbers because
+       // of their prevalence, despite them being invalid
+       // TODO(rolandshoemaker): revist this decision, there are currently
+       // only 10 trusted certificates with negative serial numbers
+       // according to censys.io.
+       cert.SerialNumber = serial
+
+       var sigAISeq cryptobyte.String
+       if !tbs.ReadASN1(&sigAISeq, cryptobyte_asn1.SEQUENCE) {
+               return nil, errors.New("x509: malformed signature algorithm identifier")
+       }
+       // Before parsing the inner algorithm identifier, extract
+       // the outer algorithm identifier and make sure that they
+       // match.
+       var outerSigAISeq cryptobyte.String
+       if !input.ReadASN1(&outerSigAISeq, cryptobyte_asn1.SEQUENCE) {
+               return nil, errors.New("x509: malformed algorithm identifier")
+       }
+       if !bytes.Equal(outerSigAISeq, sigAISeq) {
+               return nil, errors.New("x509: inner and outer signature algorithm identifiers don't match")
+       }
+       sigAI, err := parseAI(sigAISeq)
+       if err != nil {
+               return nil, err
+       }
+       cert.SignatureAlgorithm = getSignatureAlgorithmFromAI(sigAI)
+
+       var issuerSeq cryptobyte.String
+       if !tbs.ReadASN1Element(&issuerSeq, cryptobyte_asn1.SEQUENCE) {
+               return nil, errors.New("x509: malformed issuer")
+       }
+       cert.RawIssuer = issuerSeq
+       issuerRDNs, err := parseName(issuerSeq)
+       if err != nil {
+               return nil, err
+       }
+       cert.Issuer.FillFromRDNSequence(issuerRDNs)
+
+       var validity cryptobyte.String
+       if !tbs.ReadASN1(&validity, cryptobyte_asn1.SEQUENCE) {
+               return nil, errors.New("x509: malformed validity")
+       }
+       cert.NotBefore, cert.NotAfter, err = parseValidity(validity)
+       if err != nil {
+               return nil, err
+       }
+
+       var subjectSeq cryptobyte.String
+       if !tbs.ReadASN1Element(&subjectSeq, cryptobyte_asn1.SEQUENCE) {
+               return nil, errors.New("x509: malformed issuer")
+       }
+       cert.RawSubject = subjectSeq
+       subjectRDNs, err := parseName(subjectSeq)
+       if err != nil {
+               return nil, err
+       }
+       cert.Subject.FillFromRDNSequence(subjectRDNs)
+
+       var spki cryptobyte.String
+       if !tbs.ReadASN1Element(&spki, cryptobyte_asn1.SEQUENCE) {
+               return nil, errors.New("x509: malformed spki")
+       }
+       cert.RawSubjectPublicKeyInfo = spki
+       if !spki.ReadASN1(&spki, cryptobyte_asn1.SEQUENCE) {
+               return nil, errors.New("x509: malformed spki")
+       }
+       var pkAISeq cryptobyte.String
+       if !spki.ReadASN1(&pkAISeq, cryptobyte_asn1.SEQUENCE) {
+               return nil, errors.New("x509: malformed public key algorithm identifier")
+       }
+       pkAI, err := parseAI(pkAISeq)
+       if err != nil {
+               return nil, err
+       }
+       cert.PublicKeyAlgorithm = getPublicKeyAlgorithmFromOID(pkAI.Algorithm)
+       var spk asn1.BitString
+       if !spki.ReadASN1BitString(&spk) {
+               return nil, errors.New("x509: malformed subjectPublicKey")
+       }
+       cert.PublicKey, err = parsePublicKey(cert.PublicKeyAlgorithm, &publicKeyInfo{
+               Algorithm: pkAI,
+               PublicKey: spk,
+       })
+       if err != nil {
+               return nil, err
+       }
+
+       if cert.Version > 1 {
+               if !tbs.SkipOptionalASN1(cryptobyte_asn1.Tag(1).Constructed().ContextSpecific()) {
+                       return nil, errors.New("x509: malformed issuerUniqueID")
+               }
+               if !tbs.SkipOptionalASN1(cryptobyte_asn1.Tag(2).Constructed().ContextSpecific()) {
+                       return nil, errors.New("x509: malformed subjectUniqueID")
+               }
+               if cert.Version == 3 {
+                       var extensions cryptobyte.String
+                       var present bool
+                       if !tbs.ReadOptionalASN1(&extensions, &present, cryptobyte_asn1.Tag(3).Constructed().ContextSpecific()) {
+                               return nil, errors.New("x509: malformed extensions")
+                       }
+                       if present {
+                               if !extensions.ReadASN1(&extensions, cryptobyte_asn1.SEQUENCE) {
+                                       return nil, errors.New("x509: malformed extensions")
+                               }
+                               for !extensions.Empty() {
+                                       var extension cryptobyte.String
+                                       if !extensions.ReadASN1(&extension, cryptobyte_asn1.SEQUENCE) {
+                                               return nil, errors.New("x509: malformed extension")
+                                       }
+                                       ext, err := parseExtension(extension)
+                                       if err != nil {
+                                               return nil, err
+                                       }
+                                       cert.Extensions = append(cert.Extensions, ext)
+                               }
+                               err = processExtensions(cert)
+                               if err != nil {
+                                       return nil, err
+                               }
+                       }
+               }
+       }
+
+       var signature asn1.BitString
+       if !input.ReadASN1BitString(&signature) {
+               return nil, errors.New("x509: malformed signature")
+       }
+       cert.Signature = signature.RightAlign()
+
+       return cert, nil
+}
+
+// ParseCertificate parses a single certificate from the given ASN.1 DER data.
+func ParseCertificate(der []byte) (*Certificate, error) {
+       cert, err := parseCertificate(der)
+       if err != nil {
+               return nil, err
+       }
+       if len(der) != len(cert.Raw) {
+               return nil, errors.New("x509: trailing data")
+       }
+       return cert, err
+}
+
+// ParseCertificates parses one or more certificates from the given ASN.1 DER
+// data. The certificates must be concatenated with no intermediate padding.
+func ParseCertificates(der []byte) ([]*Certificate, error) {
+       var certs []*Certificate
+       for len(der) > 0 {
+               cert, err := parseCertificate(der)
+               if err != nil {
+                       return nil, err
+               }
+               certs = append(certs, cert)
+               der = der[len(cert.Raw):]
+       }
+       return certs, nil
+}
index cc53f7aefcabcbe8229c13e42d44d6707af99812..eef9c047b2e3144a47b9b71234e6a32b177634a2 100644 (file)
@@ -8,7 +8,7 @@ package x509
 // argument to the latest security_certificates version from
 // https://opensource.apple.com/source/security_certificates/
 // and run "go generate". See https://golang.org/issue/38843.
-//go:generate go run root_ios_gen.go -version 55188.40.9
+//go:generate go run root_ios_gen.go -version 55188.120.1.0.1
 
 import "sync"
 
index f04b6bd0d66991537d791bf278d1270308cc6b6f..6712ea32a68414681c5cd0658dc12f930107327f 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build dragonfly || freebsd || netbsd || openbsd
 // +build dragonfly freebsd netbsd openbsd
 
 package x509
@@ -17,6 +18,7 @@ var certFiles = []string{
 // Possible directories with certificate files; stop after successfully
 // reading at least one file from a directory.
 var certDirectories = []string{
+       "/etc/ssl/certs",         // FreeBSD 12.2+
        "/usr/local/share/certs", // FreeBSD
        "/etc/openssl/certs",     // NetBSD
 }
index c9ea7e80f375d8febe266f2d5ed163faf62e30c9..05593bb1055b50d06df34ec12455385621f3b856 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !ios
 // +build !ios
 
 package x509
index d2dfb62b77c6a9ab56300c2fd9b60ab44b8f280a..9bc62f8abb6802747da47494632341f5c37a7d73 100644 (file)
@@ -1,8 +1,8 @@
-// Code generated by root_ios_gen.go -version 55188.40.9; DO NOT EDIT.
+// Code generated by root_ios_gen.go -version 55188.120.1.0.1; DO NOT EDIT.
 // Update the version in root.go and regenerate with "go generate".
 
-// +build ios
-// +build !x509omitbundledroots
+//go:build ios && !x509omitbundledroots
+// +build ios,!x509omitbundledroots
 
 package x509
 
@@ -2223,6 +2223,41 @@ uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX
 kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs
 ewv4n4Q=
 -----END CERTIFICATE-----
+# "GlobalSign"
+# 2C AB EA FE 37 D0 6C A2 2A BA 73 91 C0 03 3D 25
+# 98 29 52 C4 53 64 73 49 76 3A 3A B5 AD 6C CF 69
+-----BEGIN CERTIFICATE-----
+MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg
+MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh
+bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx
+MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET
+MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI
+xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k
+ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD
+aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw
+LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw
+1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX
+k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2
+SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h
+bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n
+WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY
+rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce
+MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD
+AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu
+bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN
+nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt
+Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61
+55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj
+vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf
+cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz
+oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp
+nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs
+pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v
+JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R
+8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4
+5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA=
+-----END CERTIFICATE-----
 # "GlobalSign Root CA"
 # EB D4 10 40 E4 BB 3E C7 42 C9 E3 81 D3 1E F2 A4
 # 1A 48 B6 68 5C 96 E7 CE F3 C1 DF 6C D4 33 1C 99
index 8bc6e7d9c478da46dc5e9edb1bfbfa6f6f01284a..05bd672d5d8355a4bb32fd70e64c121edbdf5614 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 // Generates root_ios.go.
index 4e537a4fe5e021fac4afdc03ea287666fc4eeaed..f2c2c0af3803851cca5811c627cff5f1979366d8 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build js && wasm
 // +build js,wasm
 
 package x509
index 0055b3b86272093cd3b25836010aeaa6442e7f15..81f2f112d07da5e2933a008d5518e76d774135d8 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ((darwin && arm64) || (darwin && amd64 && ios)) && x509omitbundledroots
 // +build darwin,arm64 darwin,amd64,ios
 // +build x509omitbundledroots
 
index 5ab6c931deb619a7eb4da4b39bea942817cbbc41..158bd7f91aebedc7195d4cbbd96f6fd6446ca612 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ((darwin && arm64) || (darwin && amd64 && ios)) && x509omitbundledroots
 // +build darwin,arm64 darwin,amd64,ios
 // +build x509omitbundledroots
 
index 2dc4aaf5d7a794cea03ae9251f7fbcbe9bab094b..2bdb2fe7136aced8f87c1a344ffe77bd9c737050 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build plan9
 // +build plan9
 
 package x509
index 3d09663386953395550e63af80e1958f296aaafb..4ed95e47bafe56c51d73dd2efb84b1d0fd03dc13 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris
 // +build aix dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris
 
 package x509
index 878ed7c2faf20b03b39a6d3b5e3ce02d31e9a01b..7118f12d744cdf5e4a8515d47496652eb3297f6a 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build dragonfly || freebsd || linux || netbsd || openbsd || solaris
 // +build dragonfly freebsd linux netbsd openbsd solaris
 
 package x509
@@ -146,11 +147,7 @@ func TestLoadSystemCertsLoadColonSeparatedDirs(t *testing.T) {
                os.Setenv(certFileEnv, origFile)
        }()
 
-       tmpDir, err := os.MkdirTemp(os.TempDir(), "x509-issue35325")
-       if err != nil {
-               t.Fatalf("Failed to create temporary directory: %v", err)
-       }
-       defer os.RemoveAll(tmpDir)
+       tmpDir := t.TempDir()
 
        rootPEMs := []string{
                geoTrustRoot,
index 46afb2698a919ddb64131ee9d5df0958f2063309..9ef11466a470a3730ea08614a4a0dd8e907d723f 100644 (file)
@@ -10,7 +10,6 @@ import (
        "fmt"
        "net"
        "net/url"
-       "os"
        "reflect"
        "runtime"
        "strings"
@@ -18,9 +17,6 @@ import (
        "unicode/utf8"
 )
 
-// ignoreCN disables interpreting Common Name as a hostname. See issue 24151.
-var ignoreCN = !strings.Contains(os.Getenv("GODEBUG"), "x509ignoreCN=0")
-
 type InvalidReason int
 
 const (
@@ -43,14 +39,7 @@ const (
        // NameMismatch results when the subject name of a parent certificate
        // does not match the issuer name in the child.
        NameMismatch
-       // NameConstraintsWithoutSANs results when a leaf certificate doesn't
-       // contain a Subject Alternative Name extension, but a CA certificate
-       // contains name constraints, and the Common Name can be interpreted as
-       // a hostname.
-       //
-       // This error is only returned when legacy Common Name matching is enabled
-       // by setting the GODEBUG environment variable to "x509ignoreCN=1". This
-       // setting might be removed in the future.
+       // NameConstraintsWithoutSANs is a legacy error and is no longer returned.
        NameConstraintsWithoutSANs
        // UnconstrainedName results when a CA certificate contains permitted
        // name constraints, but leaf certificate contains a name of an
@@ -110,15 +99,7 @@ func (h HostnameError) Error() string {
        c := h.Certificate
 
        if !c.hasSANExtension() && matchHostnames(c.Subject.CommonName, h.Host) {
-               if !ignoreCN && !validHostnamePattern(c.Subject.CommonName) {
-                       // This would have validated, if it weren't for the validHostname check on Common Name.
-                       return "x509: Common Name is not a valid hostname: " + c.Subject.CommonName
-               }
-               if ignoreCN && validHostnamePattern(c.Subject.CommonName) {
-                       // This would have validated if x509ignoreCN=0 were set.
-                       return "x509: certificate relies on legacy Common Name field, " +
-                               "use SANs or temporarily enable Common Name matching with GODEBUG=x509ignoreCN=0"
-               }
+               return "x509: certificate relies on legacy Common Name field, use SANs instead"
        }
 
        var valid string
@@ -134,11 +115,7 @@ func (h HostnameError) Error() string {
                        valid += san.String()
                }
        } else {
-               if c.commonNameAsHostname() {
-                       valid = c.Subject.CommonName
-               } else {
-                       valid = strings.Join(c.DNSNames, ", ")
-               }
+               valid = strings.Join(c.DNSNames, ", ")
        }
 
        if len(valid) == 0 {
@@ -620,15 +597,8 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
                leaf = currentChain[0]
        }
 
-       checkNameConstraints := (certType == intermediateCertificate || certType == rootCertificate) && c.hasNameConstraints()
-       if checkNameConstraints && leaf.commonNameAsHostname() {
-               // This is the deprecated, legacy case of depending on the commonName as
-               // a hostname. We don't enforce name constraints against the CN, but
-               // VerifyHostname will look for hostnames in there if there are no SANs.
-               // In order to ensure VerifyHostname will not accept an unchecked name,
-               // return an error here.
-               return CertificateInvalidError{c, NameConstraintsWithoutSANs, ""}
-       } else if checkNameConstraints && leaf.hasSANExtension() {
+       if (certType == intermediateCertificate || certType == rootCertificate) &&
+               c.hasNameConstraints() && leaf.hasSANExtension() {
                err := forEachSAN(leaf.getSANExtension(), func(tag int, data []byte) error {
                        switch tag {
                        case nameTypeEmail:
@@ -837,7 +807,7 @@ func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate
 }
 
 // maxChainSignatureChecks is the maximum number of CheckSignatureFrom calls
-// that an invocation of buildChains will (tranistively) make. Most chains are
+// that an invocation of buildChains will (transitively) make. Most chains are
 // less than 15 certificates long, so this leaves space for multiple chains and
 // for failed checks due to different intermediates having the same Subject.
 const maxChainSignatureChecks = 100
@@ -960,18 +930,6 @@ func validHostname(host string, isPattern bool) bool {
        return true
 }
 
-// commonNameAsHostname reports whether the Common Name field should be
-// considered the hostname that the certificate is valid for. This is a legacy
-// behavior, disabled by default or if the Subject Alt Name extension is present.
-//
-// It applies the strict validHostname check to the Common Name field, so that
-// certificates without SANs can still be validated against CAs with name
-// constraints if there is no risk the CN would be matched as a hostname.
-// See NameConstraintsWithoutSANs and issue 24151.
-func (c *Certificate) commonNameAsHostname() bool {
-       return !ignoreCN && !c.hasSANExtension() && validHostnamePattern(c.Subject.CommonName)
-}
-
 func matchExactly(hostA, hostB string) bool {
        if hostA == "" || hostA == "." || hostB == "" || hostB == "." {
                return false
@@ -1046,10 +1004,7 @@ func toLowerCaseASCII(in string) string {
 // against the DNSNames field. If the names are valid hostnames, the certificate
 // fields can have a wildcard as the left-most label.
 //
-// The legacy Common Name field is ignored unless it's a valid hostname, the
-// certificate doesn't have any Subject Alternative Names, and the GODEBUG
-// environment variable is set to "x509ignoreCN=0". Support for Common Name is
-// deprecated will be entirely removed in the future.
+// Note that the legacy Common Name field is ignored.
 func (c *Certificate) VerifyHostname(h string) error {
        // IP addresses may be written in [ ].
        candidateIP := h
@@ -1067,15 +1022,10 @@ func (c *Certificate) VerifyHostname(h string) error {
                return HostnameError{c, candidateIP}
        }
 
-       names := c.DNSNames
-       if c.commonNameAsHostname() {
-               names = []string{c.Subject.CommonName}
-       }
-
        candidateName := toLowerCaseASCII(h) // Save allocations inside the loop.
        validCandidateName := validHostnameInput(candidateName)
 
-       for _, match := range names {
+       for _, match := range c.DNSNames {
                // Ideally, we'd only match valid hostnames according to RFC 6125 like
                // browsers (more or less) do, but in practice Go is used in a wider
                // array of contexts and can't even assume DNS resolution. Instead,
index 8e0a7bef4755026d8188bfdffc0dad5702e40a3e..9954a670da0bd16cfd3b5e594c6e2b63da5941f6 100644 (file)
@@ -30,7 +30,6 @@ type verifyTest struct {
        systemSkip    bool
        systemLax     bool
        keyUsages     []ExtKeyUsage
-       ignoreCN      bool
 
        errorCallback  func(*testing.T, error)
        expectedChains [][]string
@@ -297,8 +296,6 @@ var verifyTests = []verifyTest{
                errorCallback: expectNotAuthorizedError,
        },
        {
-               // If any SAN extension is present (even one without any DNS
-               // names), the CN should be ignored.
                name:        "IgnoreCNWithSANs",
                leaf:        ignoreCNWithSANLeaf,
                dnsName:     "foo.example.com",
@@ -325,7 +322,6 @@ var verifyTests = []verifyTest{
                // verify error.
                name:          "CriticalExtLeaf",
                leaf:          criticalExtLeafWithExt,
-               dnsName:       "example.com",
                intermediates: []string{criticalExtIntermediate},
                roots:         []string{criticalExtRoot},
                currentTime:   1486684488,
@@ -338,7 +334,6 @@ var verifyTests = []verifyTest{
                // cause a verify error.
                name:          "CriticalExtIntermediate",
                leaf:          criticalExtLeaf,
-               dnsName:       "example.com",
                intermediates: []string{criticalExtIntermediateWithExt},
                roots:         []string{criticalExtRoot},
                currentTime:   1486684488,
@@ -347,18 +342,6 @@ var verifyTests = []verifyTest{
                errorCallback: expectUnhandledCriticalExtension,
        },
        {
-               // Test that invalid CN are ignored.
-               name:        "InvalidCN",
-               leaf:        invalidCNWithoutSAN,
-               dnsName:     "foo,invalid",
-               roots:       []string{invalidCNRoot},
-               currentTime: 1540000000,
-               systemSkip:  true, // does not chain to a system root
-
-               errorCallback: expectHostnameError("Common Name is not a valid hostname"),
-       },
-       {
-               // Test that valid CN are respected.
                name:        "ValidCN",
                leaf:        validCNWithoutSAN,
                dnsName:     "foo.example.com",
@@ -366,42 +349,6 @@ var verifyTests = []verifyTest{
                currentTime: 1540000000,
                systemSkip:  true, // does not chain to a system root
 
-               expectedChains: [][]string{
-                       {"foo.example.com", "Test root"},
-               },
-       },
-       // Replicate CN tests with ignoreCN = true
-       {
-               name:        "IgnoreCNWithSANs/ignoreCN",
-               leaf:        ignoreCNWithSANLeaf,
-               dnsName:     "foo.example.com",
-               roots:       []string{ignoreCNWithSANRoot},
-               currentTime: 1486684488,
-               systemSkip:  true, // does not chain to a system root
-               ignoreCN:    true,
-
-               errorCallback: expectHostnameError("certificate is not valid for any names"),
-       },
-       {
-               name:        "InvalidCN/ignoreCN",
-               leaf:        invalidCNWithoutSAN,
-               dnsName:     "foo,invalid",
-               roots:       []string{invalidCNRoot},
-               currentTime: 1540000000,
-               systemSkip:  true, // does not chain to a system root
-               ignoreCN:    true,
-
-               errorCallback: expectHostnameError("certificate is not valid for any names"),
-       },
-       {
-               name:        "ValidCN/ignoreCN",
-               leaf:        validCNWithoutSAN,
-               dnsName:     "foo.example.com",
-               roots:       []string{invalidCNRoot},
-               currentTime: 1540000000,
-               systemSkip:  true, // does not chain to a system root
-               ignoreCN:    true,
-
                errorCallback: expectHostnameError("certificate relies on legacy Common Name field"),
        },
        {
@@ -503,9 +450,6 @@ func certificateFromPEM(pemBytes string) (*Certificate, error) {
 }
 
 func testVerify(t *testing.T, test verifyTest, useSystemRoots bool) {
-       defer func(savedIgnoreCN bool) { ignoreCN = savedIgnoreCN }(ignoreCN)
-
-       ignoreCN = test.ignoreCN
        opts := VerifyOptions{
                Intermediates: NewCertPool(),
                DNSName:       test.dnsName,
@@ -1589,16 +1533,6 @@ oCGMjNwwCgYIKoZIzj0EAwIDRwAwRAIgDSiwgIn8g1lpruYH0QD1GYeoWVunfmrI
 XzZZl0eW/ugCICgOfXeZ2GGy3wIC0352BaC3a8r5AAb2XSGNe+e9wNN6
 -----END CERTIFICATE-----`
 
-const invalidCNWithoutSAN = `-----BEGIN CERTIFICATE-----
-MIIBJDCBywIUB7q8t9mrDAL+UB1OFaMN5BEWFKIwCgYIKoZIzj0EAwIwFDESMBAG
-A1UECwwJVGVzdCByb290MB4XDTE4MDcxMTE4MzUyMVoXDTI4MDcwODE4MzUyMVow
-FjEUMBIGA1UEAwwLZm9vLGludmFsaWQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC
-AASnpnwiM6dHfwiTLV9hNS7aRWd28pdzGLABEkoa1bdvQTy7BWn0Bl3/6yunhQtM
-90VOgUB6qcYdu7rZuSazylCQMAoGCCqGSM49BAMCA0gAMEUCIQCFlnW2cjxnEqB/
-hgSB0t3IZ1DXX4XAVFT85mtFCJPTKgIgYIY+1iimTtrdbpWJzAB2eBwDgIWmWgvr
-xfOcLt/vbvo=
------END CERTIFICATE-----`
-
 const validCNWithoutSAN = `-----BEGIN CERTIFICATE-----
 MIIBJzCBzwIUB7q8t9mrDAL+UB1OFaMN5BEWFKQwCgYIKoZIzj0EAwIwFDESMBAG
 A1UECwwJVGVzdCByb290MB4XDTE4MDcxMTE4NDcyNFoXDTI4MDcwODE4NDcyNFow
index 8c0299b11e9b5ad606591c38304cc8f2c3684437..4304ab54e1a7052f7a7c40e6eb589900db7c56e9 100644 (file)
@@ -8,7 +8,6 @@ package x509
 import (
        "bytes"
        "crypto"
-       "crypto/dsa"
        "crypto/ecdsa"
        "crypto/ed25519"
        "crypto/elliptic"
@@ -24,7 +23,6 @@ import (
        "net"
        "net/url"
        "strconv"
-       "strings"
        "time"
        "unicode"
 
@@ -914,676 +912,6 @@ type distributionPointName struct {
        RelativeName pkix.RDNSequence `asn1:"optional,tag:1"`
 }
 
-func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{}, error) {
-       asn1Data := keyData.PublicKey.RightAlign()
-       switch algo {
-       case RSA:
-               // RSA public keys must have a NULL in the parameters.
-               // See RFC 3279, Section 2.3.1.
-               if !bytes.Equal(keyData.Algorithm.Parameters.FullBytes, asn1.NullBytes) {
-                       return nil, errors.New("x509: RSA key missing NULL parameters")
-               }
-
-               p := new(pkcs1PublicKey)
-               rest, err := asn1.Unmarshal(asn1Data, p)
-               if err != nil {
-                       return nil, err
-               }
-               if len(rest) != 0 {
-                       return nil, errors.New("x509: trailing data after RSA public key")
-               }
-
-               if p.N.Sign() <= 0 {
-                       return nil, errors.New("x509: RSA modulus is not a positive number")
-               }
-               if p.E <= 0 {
-                       return nil, errors.New("x509: RSA public exponent is not a positive number")
-               }
-
-               pub := &rsa.PublicKey{
-                       E: p.E,
-                       N: p.N,
-               }
-               return pub, nil
-       case DSA:
-               var p *big.Int
-               rest, err := asn1.Unmarshal(asn1Data, &p)
-               if err != nil {
-                       return nil, err
-               }
-               if len(rest) != 0 {
-                       return nil, errors.New("x509: trailing data after DSA public key")
-               }
-               paramsData := keyData.Algorithm.Parameters.FullBytes
-               params := new(dsaAlgorithmParameters)
-               rest, err = asn1.Unmarshal(paramsData, params)
-               if err != nil {
-                       return nil, err
-               }
-               if len(rest) != 0 {
-                       return nil, errors.New("x509: trailing data after DSA parameters")
-               }
-               if p.Sign() <= 0 || params.P.Sign() <= 0 || params.Q.Sign() <= 0 || params.G.Sign() <= 0 {
-                       return nil, errors.New("x509: zero or negative DSA parameter")
-               }
-               pub := &dsa.PublicKey{
-                       Parameters: dsa.Parameters{
-                               P: params.P,
-                               Q: params.Q,
-                               G: params.G,
-                       },
-                       Y: p,
-               }
-               return pub, nil
-       case ECDSA:
-               paramsData := keyData.Algorithm.Parameters.FullBytes
-               namedCurveOID := new(asn1.ObjectIdentifier)
-               rest, err := asn1.Unmarshal(paramsData, namedCurveOID)
-               if err != nil {
-                       return nil, errors.New("x509: failed to parse ECDSA parameters as named curve")
-               }
-               if len(rest) != 0 {
-                       return nil, errors.New("x509: trailing data after ECDSA parameters")
-               }
-               namedCurve := namedCurveFromOID(*namedCurveOID)
-               if namedCurve == nil {
-                       return nil, errors.New("x509: unsupported elliptic curve")
-               }
-               x, y := elliptic.Unmarshal(namedCurve, asn1Data)
-               if x == nil {
-                       return nil, errors.New("x509: failed to unmarshal elliptic curve point")
-               }
-               pub := &ecdsa.PublicKey{
-                       Curve: namedCurve,
-                       X:     x,
-                       Y:     y,
-               }
-               return pub, nil
-       case Ed25519:
-               // RFC 8410, Section 3
-               // > For all of the OIDs, the parameters MUST be absent.
-               if len(keyData.Algorithm.Parameters.FullBytes) != 0 {
-                       return nil, errors.New("x509: Ed25519 key encoded with illegal parameters")
-               }
-               if len(asn1Data) != ed25519.PublicKeySize {
-                       return nil, errors.New("x509: wrong Ed25519 public key size")
-               }
-               pub := make([]byte, ed25519.PublicKeySize)
-               copy(pub, asn1Data)
-               return ed25519.PublicKey(pub), nil
-       default:
-               return nil, nil
-       }
-}
-
-func forEachSAN(extension []byte, callback func(tag int, data []byte) error) error {
-       // RFC 5280, 4.2.1.6
-
-       // SubjectAltName ::= GeneralNames
-       //
-       // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
-       //
-       // GeneralName ::= CHOICE {
-       //      otherName                       [0]     OtherName,
-       //      rfc822Name                      [1]     IA5String,
-       //      dNSName                         [2]     IA5String,
-       //      x400Address                     [3]     ORAddress,
-       //      directoryName                   [4]     Name,
-       //      ediPartyName                    [5]     EDIPartyName,
-       //      uniformResourceIdentifier       [6]     IA5String,
-       //      iPAddress                       [7]     OCTET STRING,
-       //      registeredID                    [8]     OBJECT IDENTIFIER }
-       var seq asn1.RawValue
-       rest, err := asn1.Unmarshal(extension, &seq)
-       if err != nil {
-               return err
-       } else if len(rest) != 0 {
-               return errors.New("x509: trailing data after X.509 extension")
-       }
-       if !seq.IsCompound || seq.Tag != 16 || seq.Class != 0 {
-               return asn1.StructuralError{Msg: "bad SAN sequence"}
-       }
-
-       rest = seq.Bytes
-       for len(rest) > 0 {
-               var v asn1.RawValue
-               rest, err = asn1.Unmarshal(rest, &v)
-               if err != nil {
-                       return err
-               }
-
-               if err := callback(v.Tag, v.Bytes); err != nil {
-                       return err
-               }
-       }
-
-       return nil
-}
-
-func parseSANExtension(value []byte) (dnsNames, emailAddresses []string, ipAddresses []net.IP, uris []*url.URL, err error) {
-       err = forEachSAN(value, func(tag int, data []byte) error {
-               switch tag {
-               case nameTypeEmail:
-                       email := string(data)
-                       if err := isIA5String(email); err != nil {
-                               return errors.New("x509: SAN rfc822Name is malformed")
-                       }
-                       emailAddresses = append(emailAddresses, email)
-               case nameTypeDNS:
-                       name := string(data)
-                       if err := isIA5String(name); err != nil {
-                               return errors.New("x509: SAN dNSName is malformed")
-                       }
-                       dnsNames = append(dnsNames, string(name))
-               case nameTypeURI:
-                       uriStr := string(data)
-                       if err := isIA5String(uriStr); err != nil {
-                               return errors.New("x509: SAN uniformResourceIdentifier is malformed")
-                       }
-                       uri, err := url.Parse(uriStr)
-                       if err != nil {
-                               return fmt.Errorf("x509: cannot parse URI %q: %s", uriStr, err)
-                       }
-                       if len(uri.Host) > 0 {
-                               if _, ok := domainToReverseLabels(uri.Host); !ok {
-                                       return fmt.Errorf("x509: cannot parse URI %q: invalid domain", uriStr)
-                               }
-                       }
-                       uris = append(uris, uri)
-               case nameTypeIP:
-                       switch len(data) {
-                       case net.IPv4len, net.IPv6len:
-                               ipAddresses = append(ipAddresses, data)
-                       default:
-                               return errors.New("x509: cannot parse IP address of length " + strconv.Itoa(len(data)))
-                       }
-               }
-
-               return nil
-       })
-
-       return
-}
-
-// isValidIPMask reports whether mask consists of zero or more 1 bits, followed by zero bits.
-func isValidIPMask(mask []byte) bool {
-       seenZero := false
-
-       for _, b := range mask {
-               if seenZero {
-                       if b != 0 {
-                               return false
-                       }
-
-                       continue
-               }
-
-               switch b {
-               case 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe:
-                       seenZero = true
-               case 0xff:
-               default:
-                       return false
-               }
-       }
-
-       return true
-}
-
-func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandled bool, err error) {
-       // RFC 5280, 4.2.1.10
-
-       // NameConstraints ::= SEQUENCE {
-       //      permittedSubtrees       [0]     GeneralSubtrees OPTIONAL,
-       //      excludedSubtrees        [1]     GeneralSubtrees OPTIONAL }
-       //
-       // GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
-       //
-       // GeneralSubtree ::= SEQUENCE {
-       //      base                    GeneralName,
-       //      minimum         [0]     BaseDistance DEFAULT 0,
-       //      maximum         [1]     BaseDistance OPTIONAL }
-       //
-       // BaseDistance ::= INTEGER (0..MAX)
-
-       outer := cryptobyte.String(e.Value)
-       var toplevel, permitted, excluded cryptobyte.String
-       var havePermitted, haveExcluded bool
-       if !outer.ReadASN1(&toplevel, cryptobyte_asn1.SEQUENCE) ||
-               !outer.Empty() ||
-               !toplevel.ReadOptionalASN1(&permitted, &havePermitted, cryptobyte_asn1.Tag(0).ContextSpecific().Constructed()) ||
-               !toplevel.ReadOptionalASN1(&excluded, &haveExcluded, cryptobyte_asn1.Tag(1).ContextSpecific().Constructed()) ||
-               !toplevel.Empty() {
-               return false, errors.New("x509: invalid NameConstraints extension")
-       }
-
-       if !havePermitted && !haveExcluded || len(permitted) == 0 && len(excluded) == 0 {
-               // From RFC 5280, Section 4.2.1.10:
-               //   “either the permittedSubtrees field
-               //   or the excludedSubtrees MUST be
-               //   present”
-               return false, errors.New("x509: empty name constraints extension")
-       }
-
-       getValues := func(subtrees cryptobyte.String) (dnsNames []string, ips []*net.IPNet, emails, uriDomains []string, err error) {
-               for !subtrees.Empty() {
-                       var seq, value cryptobyte.String
-                       var tag cryptobyte_asn1.Tag
-                       if !subtrees.ReadASN1(&seq, cryptobyte_asn1.SEQUENCE) ||
-                               !seq.ReadAnyASN1(&value, &tag) {
-                               return nil, nil, nil, nil, fmt.Errorf("x509: invalid NameConstraints extension")
-                       }
-
-                       var (
-                               dnsTag   = cryptobyte_asn1.Tag(2).ContextSpecific()
-                               emailTag = cryptobyte_asn1.Tag(1).ContextSpecific()
-                               ipTag    = cryptobyte_asn1.Tag(7).ContextSpecific()
-                               uriTag   = cryptobyte_asn1.Tag(6).ContextSpecific()
-                       )
-
-                       switch tag {
-                       case dnsTag:
-                               domain := string(value)
-                               if err := isIA5String(domain); err != nil {
-                                       return nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + err.Error())
-                               }
-
-                               trimmedDomain := domain
-                               if len(trimmedDomain) > 0 && trimmedDomain[0] == '.' {
-                                       // constraints can have a leading
-                                       // period to exclude the domain
-                                       // itself, but that's not valid in a
-                                       // normal domain name.
-                                       trimmedDomain = trimmedDomain[1:]
-                               }
-                               if _, ok := domainToReverseLabels(trimmedDomain); !ok {
-                                       return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse dnsName constraint %q", domain)
-                               }
-                               dnsNames = append(dnsNames, domain)
-
-                       case ipTag:
-                               l := len(value)
-                               var ip, mask []byte
-
-                               switch l {
-                               case 8:
-                                       ip = value[:4]
-                                       mask = value[4:]
-
-                               case 32:
-                                       ip = value[:16]
-                                       mask = value[16:]
-
-                               default:
-                                       return nil, nil, nil, nil, fmt.Errorf("x509: IP constraint contained value of length %d", l)
-                               }
-
-                               if !isValidIPMask(mask) {
-                                       return nil, nil, nil, nil, fmt.Errorf("x509: IP constraint contained invalid mask %x", mask)
-                               }
-
-                               ips = append(ips, &net.IPNet{IP: net.IP(ip), Mask: net.IPMask(mask)})
-
-                       case emailTag:
-                               constraint := string(value)
-                               if err := isIA5String(constraint); err != nil {
-                                       return nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + err.Error())
-                               }
-
-                               // If the constraint contains an @ then
-                               // it specifies an exact mailbox name.
-                               if strings.Contains(constraint, "@") {
-                                       if _, ok := parseRFC2821Mailbox(constraint); !ok {
-                                               return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse rfc822Name constraint %q", constraint)
-                                       }
-                               } else {
-                                       // Otherwise it's a domain name.
-                                       domain := constraint
-                                       if len(domain) > 0 && domain[0] == '.' {
-                                               domain = domain[1:]
-                                       }
-                                       if _, ok := domainToReverseLabels(domain); !ok {
-                                               return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse rfc822Name constraint %q", constraint)
-                                       }
-                               }
-                               emails = append(emails, constraint)
-
-                       case uriTag:
-                               domain := string(value)
-                               if err := isIA5String(domain); err != nil {
-                                       return nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + err.Error())
-                               }
-
-                               if net.ParseIP(domain) != nil {
-                                       return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse URI constraint %q: cannot be IP address", domain)
-                               }
-
-                               trimmedDomain := domain
-                               if len(trimmedDomain) > 0 && trimmedDomain[0] == '.' {
-                                       // constraints can have a leading
-                                       // period to exclude the domain itself,
-                                       // but that's not valid in a normal
-                                       // domain name.
-                                       trimmedDomain = trimmedDomain[1:]
-                               }
-                               if _, ok := domainToReverseLabels(trimmedDomain); !ok {
-                                       return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse URI constraint %q", domain)
-                               }
-                               uriDomains = append(uriDomains, domain)
-
-                       default:
-                               unhandled = true
-                       }
-               }
-
-               return dnsNames, ips, emails, uriDomains, nil
-       }
-
-       if out.PermittedDNSDomains, out.PermittedIPRanges, out.PermittedEmailAddresses, out.PermittedURIDomains, err = getValues(permitted); err != nil {
-               return false, err
-       }
-       if out.ExcludedDNSDomains, out.ExcludedIPRanges, out.ExcludedEmailAddresses, out.ExcludedURIDomains, err = getValues(excluded); err != nil {
-               return false, err
-       }
-       out.PermittedDNSDomainsCritical = e.Critical
-
-       return unhandled, nil
-}
-
-func parseCertificate(in *certificate) (*Certificate, error) {
-       out := new(Certificate)
-       out.Raw = in.Raw
-       out.RawTBSCertificate = in.TBSCertificate.Raw
-       out.RawSubjectPublicKeyInfo = in.TBSCertificate.PublicKey.Raw
-       out.RawSubject = in.TBSCertificate.Subject.FullBytes
-       out.RawIssuer = in.TBSCertificate.Issuer.FullBytes
-
-       out.Signature = in.SignatureValue.RightAlign()
-       out.SignatureAlgorithm =
-               getSignatureAlgorithmFromAI(in.TBSCertificate.SignatureAlgorithm)
-
-       out.PublicKeyAlgorithm =
-               getPublicKeyAlgorithmFromOID(in.TBSCertificate.PublicKey.Algorithm.Algorithm)
-       var err error
-       out.PublicKey, err = parsePublicKey(out.PublicKeyAlgorithm, &in.TBSCertificate.PublicKey)
-       if err != nil {
-               return nil, err
-       }
-
-       out.Version = in.TBSCertificate.Version + 1
-       out.SerialNumber = in.TBSCertificate.SerialNumber
-
-       var issuer, subject pkix.RDNSequence
-       if rest, err := asn1.Unmarshal(in.TBSCertificate.Subject.FullBytes, &subject); err != nil {
-               return nil, err
-       } else if len(rest) != 0 {
-               return nil, errors.New("x509: trailing data after X.509 subject")
-       }
-       if rest, err := asn1.Unmarshal(in.TBSCertificate.Issuer.FullBytes, &issuer); err != nil {
-               return nil, err
-       } else if len(rest) != 0 {
-               return nil, errors.New("x509: trailing data after X.509 issuer")
-       }
-
-       out.Issuer.FillFromRDNSequence(&issuer)
-       out.Subject.FillFromRDNSequence(&subject)
-
-       out.NotBefore = in.TBSCertificate.Validity.NotBefore
-       out.NotAfter = in.TBSCertificate.Validity.NotAfter
-
-       for _, e := range in.TBSCertificate.Extensions {
-               out.Extensions = append(out.Extensions, e)
-               unhandled := false
-
-               if len(e.Id) == 4 && e.Id[0] == 2 && e.Id[1] == 5 && e.Id[2] == 29 {
-                       switch e.Id[3] {
-                       case 15:
-                               out.KeyUsage, err = parseKeyUsageExtension(e.Value)
-                               if err != nil {
-                                       return nil, err
-                               }
-                       case 19:
-                               out.IsCA, out.MaxPathLen, err = parseBasicConstraintsExtension(e.Value)
-                               if err != nil {
-                                       return nil, err
-                               }
-                               out.BasicConstraintsValid = true
-                               out.MaxPathLenZero = out.MaxPathLen == 0
-                       case 17:
-                               out.DNSNames, out.EmailAddresses, out.IPAddresses, out.URIs, err = parseSANExtension(e.Value)
-                               if err != nil {
-                                       return nil, err
-                               }
-
-                               if len(out.DNSNames) == 0 && len(out.EmailAddresses) == 0 && len(out.IPAddresses) == 0 && len(out.URIs) == 0 {
-                                       // If we didn't parse anything then we do the critical check, below.
-                                       unhandled = true
-                               }
-
-                       case 30:
-                               unhandled, err = parseNameConstraintsExtension(out, e)
-                               if err != nil {
-                                       return nil, err
-                               }
-
-                       case 31:
-                               // RFC 5280, 4.2.1.13
-
-                               // CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
-                               //
-                               // DistributionPoint ::= SEQUENCE {
-                               //     distributionPoint       [0]     DistributionPointName OPTIONAL,
-                               //     reasons                 [1]     ReasonFlags OPTIONAL,
-                               //     cRLIssuer               [2]     GeneralNames OPTIONAL }
-                               //
-                               // DistributionPointName ::= CHOICE {
-                               //     fullName                [0]     GeneralNames,
-                               //     nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
-
-                               var cdp []distributionPoint
-                               if rest, err := asn1.Unmarshal(e.Value, &cdp); err != nil {
-                                       return nil, err
-                               } else if len(rest) != 0 {
-                                       return nil, errors.New("x509: trailing data after X.509 CRL distribution point")
-                               }
-
-                               for _, dp := range cdp {
-                                       // Per RFC 5280, 4.2.1.13, one of distributionPoint or cRLIssuer may be empty.
-                                       if len(dp.DistributionPoint.FullName) == 0 {
-                                               continue
-                                       }
-
-                                       for _, fullName := range dp.DistributionPoint.FullName {
-                                               if fullName.Tag == 6 {
-                                                       out.CRLDistributionPoints = append(out.CRLDistributionPoints, string(fullName.Bytes))
-                                               }
-                                       }
-                               }
-
-                       case 35:
-                               // RFC 5280, 4.2.1.1
-                               var a authKeyId
-                               if rest, err := asn1.Unmarshal(e.Value, &a); err != nil {
-                                       return nil, err
-                               } else if len(rest) != 0 {
-                                       return nil, errors.New("x509: trailing data after X.509 authority key-id")
-                               }
-                               out.AuthorityKeyId = a.Id
-
-                       case 37:
-                               out.ExtKeyUsage, out.UnknownExtKeyUsage, err = parseExtKeyUsageExtension(e.Value)
-                               if err != nil {
-                                       return nil, err
-                               }
-                       case 14:
-                               out.SubjectKeyId, err = parseSubjectKeyIdExtension(e.Value)
-                               if err != nil {
-                                       return nil, err
-                               }
-                       case 32:
-                               out.PolicyIdentifiers, err = parseCertificatePoliciesExtension(e.Value)
-                               if err != nil {
-                                       return nil, err
-                               }
-                       default:
-                               // Unknown extensions are recorded if critical.
-                               unhandled = true
-                       }
-               } else if e.Id.Equal(oidExtensionAuthorityInfoAccess) {
-                       // RFC 5280 4.2.2.1: Authority Information Access
-                       var aia []authorityInfoAccess
-                       if rest, err := asn1.Unmarshal(e.Value, &aia); err != nil {
-                               return nil, err
-                       } else if len(rest) != 0 {
-                               return nil, errors.New("x509: trailing data after X.509 authority information")
-                       }
-
-                       for _, v := range aia {
-                               // GeneralName: uniformResourceIdentifier [6] IA5String
-                               if v.Location.Tag != 6 {
-                                       continue
-                               }
-                               if v.Method.Equal(oidAuthorityInfoAccessOcsp) {
-                                       out.OCSPServer = append(out.OCSPServer, string(v.Location.Bytes))
-                               } else if v.Method.Equal(oidAuthorityInfoAccessIssuers) {
-                                       out.IssuingCertificateURL = append(out.IssuingCertificateURL, string(v.Location.Bytes))
-                               }
-                       }
-               } else {
-                       // Unknown extensions are recorded if critical.
-                       unhandled = true
-               }
-
-               if e.Critical && unhandled {
-                       out.UnhandledCriticalExtensions = append(out.UnhandledCriticalExtensions, e.Id)
-               }
-       }
-
-       return out, nil
-}
-
-// parseKeyUsageExtension parses id-ce-keyUsage (2.5.29.15) from RFC 5280
-// Section 4.2.1.3
-func parseKeyUsageExtension(ext []byte) (KeyUsage, error) {
-       var usageBits asn1.BitString
-       if rest, err := asn1.Unmarshal(ext, &usageBits); err != nil {
-               return 0, err
-       } else if len(rest) != 0 {
-               return 0, errors.New("x509: trailing data after X.509 KeyUsage")
-       }
-
-       var usage int
-       for i := 0; i < 9; i++ {
-               if usageBits.At(i) != 0 {
-                       usage |= 1 << uint(i)
-               }
-       }
-       return KeyUsage(usage), nil
-}
-
-// parseBasicConstraintsExtension parses id-ce-basicConstraints (2.5.29.19)
-// from RFC 5280 Section 4.2.1.9
-func parseBasicConstraintsExtension(ext []byte) (isCA bool, maxPathLen int, err error) {
-       var constraints basicConstraints
-       if rest, err := asn1.Unmarshal(ext, &constraints); err != nil {
-               return false, 0, err
-       } else if len(rest) != 0 {
-               return false, 0, errors.New("x509: trailing data after X.509 BasicConstraints")
-       }
-
-       // TODO: map out.MaxPathLen to 0 if it has the -1 default value? (Issue 19285)
-       return constraints.IsCA, constraints.MaxPathLen, nil
-}
-
-// parseExtKeyUsageExtension parses id-ce-extKeyUsage (2.5.29.37) from
-// RFC 5280 Section 4.2.1.12
-func parseExtKeyUsageExtension(ext []byte) ([]ExtKeyUsage, []asn1.ObjectIdentifier, error) {
-       var keyUsage []asn1.ObjectIdentifier
-       if rest, err := asn1.Unmarshal(ext, &keyUsage); err != nil {
-               return nil, nil, err
-       } else if len(rest) != 0 {
-               return nil, nil, errors.New("x509: trailing data after X.509 ExtendedKeyUsage")
-       }
-
-       var extKeyUsages []ExtKeyUsage
-       var unknownUsages []asn1.ObjectIdentifier
-       for _, u := range keyUsage {
-               if extKeyUsage, ok := extKeyUsageFromOID(u); ok {
-                       extKeyUsages = append(extKeyUsages, extKeyUsage)
-               } else {
-                       unknownUsages = append(unknownUsages, u)
-               }
-       }
-       return extKeyUsages, unknownUsages, nil
-}
-
-// parseSubjectKeyIdExtension parses id-ce-subjectKeyIdentifier (2.5.29.14)
-// from RFC 5280 Section 4.2.1.2
-func parseSubjectKeyIdExtension(ext []byte) ([]byte, error) {
-       var keyid []byte
-       if rest, err := asn1.Unmarshal(ext, &keyid); err != nil {
-               return nil, err
-       } else if len(rest) != 0 {
-               return nil, errors.New("x509: trailing data after X.509 key-id")
-       }
-       return keyid, nil
-}
-
-func parseCertificatePoliciesExtension(ext []byte) ([]asn1.ObjectIdentifier, error) {
-       var policies []policyInformation
-       if rest, err := asn1.Unmarshal(ext, &policies); err != nil {
-               return nil, err
-       } else if len(rest) != 0 {
-               return nil, errors.New("x509: trailing data after X.509 certificate policies")
-       }
-       oids := make([]asn1.ObjectIdentifier, len(policies))
-       for i, policy := range policies {
-               oids[i] = policy.Policy
-       }
-       return oids, nil
-}
-
-// ParseCertificate parses a single certificate from the given ASN.1 DER data.
-func ParseCertificate(asn1Data []byte) (*Certificate, error) {
-       var cert certificate
-       rest, err := asn1.Unmarshal(asn1Data, &cert)
-       if err != nil {
-               return nil, err
-       }
-       if len(rest) > 0 {
-               return nil, asn1.SyntaxError{Msg: "trailing data"}
-       }
-
-       return parseCertificate(&cert)
-}
-
-// ParseCertificates parses one or more certificates from the given ASN.1 DER
-// data. The certificates must be concatenated with no intermediate padding.
-func ParseCertificates(asn1Data []byte) ([]*Certificate, error) {
-       var v []*certificate
-
-       for len(asn1Data) > 0 {
-               cert := new(certificate)
-               var err error
-               asn1Data, err = asn1.Unmarshal(asn1Data, cert)
-               if err != nil {
-                       return nil, err
-               }
-               v = append(v, cert)
-       }
-
-       ret := make([]*Certificate, len(v))
-       for i, ci := range v {
-               cert, err := parseCertificate(ci)
-               if err != nil {
-                       return nil, err
-               }
-               ret[i] = cert
-       }
-
-       return ret, nil
-}
-
 func reverseBitsInAByte(in byte) byte {
        b1 := in>>4 | in<<4
        b2 := b1>>2&0x33 | b1<<2&0xcc
@@ -2085,8 +1413,8 @@ func signingParamsForPublicKey(pub interface{}, requestedSigAlgo SignatureAlgori
 // just an empty SEQUENCE.
 var emptyASN1Subject = []byte{0x30, 0}
 
-// CreateCertificate creates a new X.509v3 certificate based on a template.
-// The following members of template are used:
+// CreateCertificate creates a new X.509 v3 certificate based on a template.
+// The following members of template are currently used:
 //
 //  - AuthorityKeyId
 //  - BasicConstraintsValid
@@ -2123,7 +1451,7 @@ var emptyASN1Subject = []byte{0x30, 0}
 //
 // The certificate is signed by parent. If parent is equal to template then the
 // certificate is self-signed. The parameter pub is the public key of the
-// signee and priv is the private key of the signer.
+// certificate to be generated and priv is the private key of the signer.
 //
 // The returned slice is the certificate in DER encoding.
 //
@@ -2137,7 +1465,7 @@ var emptyASN1Subject = []byte{0x30, 0}
 //
 // If SubjectKeyId from template is empty and the template is a CA, SubjectKeyId
 // will be generated from the hash of the public key.
-func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv interface{}) (cert []byte, err error) {
+func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv interface{}) ([]byte, error) {
        key, ok := priv.(crypto.Signer)
        if !ok {
                return nil, errors.New("x509: certificate private key does not implement crypto.Signer")
@@ -2163,12 +1491,12 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
 
        asn1Issuer, err := subjectBytes(parent)
        if err != nil {
-               return
+               return nil, err
        }
 
        asn1Subject, err := subjectBytes(template)
        if err != nil {
-               return
+               return nil, err
        }
 
        authorityKeyId := template.AuthorityKeyId
@@ -2186,9 +1514,19 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
                subjectKeyId = h[:]
        }
 
+       // Check that the signer's public key matches the private key, if available.
+       type privateKey interface {
+               Equal(crypto.PublicKey) bool
+       }
+       if privPub, ok := key.Public().(privateKey); !ok {
+               return nil, errors.New("x509: internal error: supported public key does not implement Equal")
+       } else if parent.PublicKey != nil && !privPub.Equal(parent.PublicKey) {
+               return nil, errors.New("x509: provided PrivateKey doesn't match parent's PublicKey")
+       }
+
        extensions, err := buildCertExtensions(template, bytes.Equal(asn1Subject, emptyASN1Subject), authorityKeyId, subjectKeyId)
        if err != nil {
-               return
+               return nil, err
        }
 
        encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes}
@@ -2205,7 +1543,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
 
        tbsCertContents, err := asn1.Marshal(c)
        if err != nil {
-               return
+               return nil, err
        }
        c.Raw = tbsCertContents
 
@@ -2227,7 +1565,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
        var signature []byte
        signature, err = key.Sign(rand, signed, signerOpts)
        if err != nil {
-               return
+               return nil, err
        }
 
        signedCert, err := asn1.Marshal(certificate{
index 51dda16815b0bb13d7bb6eb9c817ef203edd1c75..a4053abf41d4160c6d8112164fabb5ba2bef51e4 100644 (file)
@@ -2995,3 +2995,224 @@ func TestCertificateRequestRoundtripFields(t *testing.T) {
                t.Fatalf("Unexpected URIs: got %v, want %v", out.URIs, in.URIs)
        }
 }
+
+func BenchmarkParseCertificate(b *testing.B) {
+       cases := []struct {
+               name string
+               pem  string
+       }{
+               {
+                       name: "ecdsa leaf",
+                       pem: `-----BEGIN CERTIFICATE-----
+MIIINjCCBx6gAwIBAgIQHdQ6oBMoe/MJAAAAAEHzmTANBgkqhkiG9w0BAQsFADBG
+MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM
+QzETMBEGA1UEAxMKR1RTIENBIDFDMzAeFw0yMDEyMDgwOTExMzZaFw0yMTAzMDIw
+OTExMzVaMBcxFTATBgNVBAMMDCouZ29vZ2xlLmNvbTBZMBMGByqGSM49AgEGCCqG
+SM49AwEHA0IABEFYegyHh1AHRS1nar5+zYJgMACcsIQMtg0YMyK/59ml8ERIt/JF
+kXM3XIvQuCJhghUawZrrAcAs8djZF1U9M4mjggYYMIIGFDAOBgNVHQ8BAf8EBAMC
+B4AwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU
+6SWWF36XBsmXJ6iV0EHPXUFoMbwwHwYDVR0jBBgwFoAUinR/r4XN7pXNPZzQ4kYU
+83E1HScwagYIKwYBBQUHAQEEXjBcMCcGCCsGAQUFBzABhhtodHRwOi8vb2NzcC5w
+a2kuZ29vZy9ndHMxYzMwMQYIKwYBBQUHMAKGJWh0dHA6Ly9wa2kuZ29vZy9yZXBv
+L2NlcnRzL2d0czFjMy5kZXIwggTCBgNVHREEggS5MIIEtYIMKi5nb29nbGUuY29t
+gg0qLmFuZHJvaWQuY29tghYqLmFwcGVuZ2luZS5nb29nbGUuY29tggkqLmJkbi5k
+ZXaCEiouY2xvdWQuZ29vZ2xlLmNvbYIYKi5jcm93ZHNvdXJjZS5nb29nbGUuY29t
+ghgqLmRhdGFjb21wdXRlLmdvb2dsZS5jb22CBiouZy5jb4IOKi5nY3AuZ3Z0Mi5j
+b22CESouZ2NwY2RuLmd2dDEuY29tggoqLmdncGh0LmNugg4qLmdrZWNuYXBwcy5j
+boIWKi5nb29nbGUtYW5hbHl0aWNzLmNvbYILKi5nb29nbGUuY2GCCyouZ29vZ2xl
+LmNsgg4qLmdvb2dsZS5jby5pboIOKi5nb29nbGUuY28uanCCDiouZ29vZ2xlLmNv
+LnVrgg8qLmdvb2dsZS5jb20uYXKCDyouZ29vZ2xlLmNvbS5hdYIPKi5nb29nbGUu
+Y29tLmJygg8qLmdvb2dsZS5jb20uY2+CDyouZ29vZ2xlLmNvbS5teIIPKi5nb29n
+bGUuY29tLnRygg8qLmdvb2dsZS5jb20udm6CCyouZ29vZ2xlLmRlggsqLmdvb2ds
+ZS5lc4ILKi5nb29nbGUuZnKCCyouZ29vZ2xlLmh1ggsqLmdvb2dsZS5pdIILKi5n
+b29nbGUubmyCCyouZ29vZ2xlLnBsggsqLmdvb2dsZS5wdIISKi5nb29nbGVhZGFw
+aXMuY29tgg8qLmdvb2dsZWFwaXMuY26CESouZ29vZ2xlY25hcHBzLmNughQqLmdv
+b2dsZWNvbW1lcmNlLmNvbYIRKi5nb29nbGV2aWRlby5jb22CDCouZ3N0YXRpYy5j
+boINKi5nc3RhdGljLmNvbYISKi5nc3RhdGljY25hcHBzLmNuggoqLmd2dDEuY29t
+ggoqLmd2dDIuY29tghQqLm1ldHJpYy5nc3RhdGljLmNvbYIMKi51cmNoaW4uY29t
+ghAqLnVybC5nb29nbGUuY29tghMqLndlYXIuZ2tlY25hcHBzLmNughYqLnlvdXR1
+YmUtbm9jb29raWUuY29tgg0qLnlvdXR1YmUuY29tghYqLnlvdXR1YmVlZHVjYXRp
+b24uY29tghEqLnlvdXR1YmVraWRzLmNvbYIHKi55dC5iZYILKi55dGltZy5jb22C
+GmFuZHJvaWQuY2xpZW50cy5nb29nbGUuY29tggthbmRyb2lkLmNvbYIbZGV2ZWxv
+cGVyLmFuZHJvaWQuZ29vZ2xlLmNughxkZXZlbG9wZXJzLmFuZHJvaWQuZ29vZ2xl
+LmNuggRnLmNvgghnZ3BodC5jboIMZ2tlY25hcHBzLmNuggZnb28uZ2yCFGdvb2ds
+ZS1hbmFseXRpY3MuY29tggpnb29nbGUuY29tgg9nb29nbGVjbmFwcHMuY26CEmdv
+b2dsZWNvbW1lcmNlLmNvbYIYc291cmNlLmFuZHJvaWQuZ29vZ2xlLmNuggp1cmNo
+aW4uY29tggp3d3cuZ29vLmdsggh5b3V0dS5iZYILeW91dHViZS5jb22CFHlvdXR1
+YmVlZHVjYXRpb24uY29tgg95b3V0dWJla2lkcy5jb22CBXl0LmJlMCEGA1UdIAQa
+MBgwCAYGZ4EMAQIBMAwGCisGAQQB1nkCBQMwNQYDVR0fBC4wLDAqoCigJoYkaHR0
+cDovL2NybC5wa2kuZ29vZy9ndHNyMS9ndHMxYzMuY3JsMBMGCisGAQQB1nkCBAMB
+Af8EAgUAMA0GCSqGSIb3DQEBCwUAA4IBAQAlDQm5zY7JcPxcJ9ulfTGsWV/m6Pro
+gLYmAlBUPGKy313aetT4Zjz44ZseVtUOKsXVHh4avPA9O+ta1FgkASlbkgJ05ivb
+j/+MMqkrLemdMv9Svvx3CNaAq2jJ2E+8GdrA1RzMkiNthJCiRafaPnXnN6hOHGNr
+GtqYfMHsvrRHW8J2IPHW0/MUHmJ/NDu/vNchxke2OEfCPLtseo3hJt8l8HbH+yE8
+DFrt8YVRi1CLomEyuPJDF4og3O3ZsoXuxcPd9UPxULOCxycdolRw8Iv/Xgr082j3
+svXC3HUd3apM2Yy3xJAlk/mUkzVXfdJZ+Zy1huNsUoJ+gM8rmpyGhYyx
+-----END CERTIFICATE-----`,
+               },
+               {
+                       name: "rsa leaf",
+                       pem: `-----BEGIN CERTIFICATE-----
+MIIJXjCCCEagAwIBAgIRAPYaTUsjP4iRBQAAAACHSSgwDQYJKoZIhvcNAQELBQAw
+QjELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFUdvb2dsZSBUcnVzdCBTZXJ2aWNlczET
+MBEGA1UEAxMKR1RTIENBIDFPMTAeFw0yMTAxMjYwODQ2MzRaFw0yMTA0MjAwODQ2
+MzNaMGYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQH
+Ew1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUgTExDMRUwEwYDVQQDDAwq
+Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC76xx0
+UdZ36/41rZNPfQ/yQ05vsBLUO0d+3uMOhvDlpst+XvIsG6L+vLDgf3RiQRFlei0h
+KqqLOtWLDc/y0+OmaaC+8ft1zljBYdvQlAYoZrT79Cc5pAIDq7G1OZ7cC4ahDno/
+n46FHjT/UTUAMYa8cKWBaMPneMIsKvn8nMdZzHkfO2nUd6OEecn90XweMvNmx8De
+6h5AlIgG3m66hkD/UCSdxn7yJHBQVdHgkfTqzv3sz2YyBQGNi288F1bn541f6khE
+fYti1MvXRtkky7yLCQNUG6PtvuSU4cKaNvRklHigf5i1nVdGEuH61gAElZIklSia
+OVK46UyU4DGtbdWNAgMBAAGjggYpMIIGJTAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0l
+BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU8zCvllLd3jhB
+k//+Wdjo40Q+T3gwHwYDVR0jBBgwFoAUmNH4bhDrz5vsYJ8YkBug630J/SswaAYI
+KwYBBQUHAQEEXDBaMCsGCCsGAQUFBzABhh9odHRwOi8vb2NzcC5wa2kuZ29vZy9n
+dHMxbzFjb3JlMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2cvZ3NyMi9HVFMx
+TzEuY3J0MIIE1wYDVR0RBIIEzjCCBMqCDCouZ29vZ2xlLmNvbYINKi5hbmRyb2lk
+LmNvbYIWKi5hcHBlbmdpbmUuZ29vZ2xlLmNvbYIJKi5iZG4uZGV2ghIqLmNsb3Vk
+Lmdvb2dsZS5jb22CGCouY3Jvd2Rzb3VyY2UuZ29vZ2xlLmNvbYIYKi5kYXRhY29t
+cHV0ZS5nb29nbGUuY29tghMqLmZsYXNoLmFuZHJvaWQuY29tggYqLmcuY2+CDiou
+Z2NwLmd2dDIuY29tghEqLmdjcGNkbi5ndnQxLmNvbYIKKi5nZ3BodC5jboIOKi5n
+a2VjbmFwcHMuY26CFiouZ29vZ2xlLWFuYWx5dGljcy5jb22CCyouZ29vZ2xlLmNh
+ggsqLmdvb2dsZS5jbIIOKi5nb29nbGUuY28uaW6CDiouZ29vZ2xlLmNvLmpwgg4q
+Lmdvb2dsZS5jby51a4IPKi5nb29nbGUuY29tLmFygg8qLmdvb2dsZS5jb20uYXWC
+DyouZ29vZ2xlLmNvbS5icoIPKi5nb29nbGUuY29tLmNvgg8qLmdvb2dsZS5jb20u
+bXiCDyouZ29vZ2xlLmNvbS50coIPKi5nb29nbGUuY29tLnZuggsqLmdvb2dsZS5k
+ZYILKi5nb29nbGUuZXOCCyouZ29vZ2xlLmZyggsqLmdvb2dsZS5odYILKi5nb29n
+bGUuaXSCCyouZ29vZ2xlLm5sggsqLmdvb2dsZS5wbIILKi5nb29nbGUucHSCEiou
+Z29vZ2xlYWRhcGlzLmNvbYIPKi5nb29nbGVhcGlzLmNughEqLmdvb2dsZWNuYXBw
+cy5jboIUKi5nb29nbGVjb21tZXJjZS5jb22CESouZ29vZ2xldmlkZW8uY29tggwq
+LmdzdGF0aWMuY26CDSouZ3N0YXRpYy5jb22CEiouZ3N0YXRpY2NuYXBwcy5jboIK
+Ki5ndnQxLmNvbYIKKi5ndnQyLmNvbYIUKi5tZXRyaWMuZ3N0YXRpYy5jb22CDCou
+dXJjaGluLmNvbYIQKi51cmwuZ29vZ2xlLmNvbYITKi53ZWFyLmdrZWNuYXBwcy5j
+boIWKi55b3V0dWJlLW5vY29va2llLmNvbYINKi55b3V0dWJlLmNvbYIWKi55b3V0
+dWJlZWR1Y2F0aW9uLmNvbYIRKi55b3V0dWJla2lkcy5jb22CByoueXQuYmWCCyou
+eXRpbWcuY29tghphbmRyb2lkLmNsaWVudHMuZ29vZ2xlLmNvbYILYW5kcm9pZC5j
+b22CG2RldmVsb3Blci5hbmRyb2lkLmdvb2dsZS5jboIcZGV2ZWxvcGVycy5hbmRy
+b2lkLmdvb2dsZS5jboIEZy5jb4IIZ2dwaHQuY26CDGdrZWNuYXBwcy5jboIGZ29v
+LmdsghRnb29nbGUtYW5hbHl0aWNzLmNvbYIKZ29vZ2xlLmNvbYIPZ29vZ2xlY25h
+cHBzLmNughJnb29nbGVjb21tZXJjZS5jb22CGHNvdXJjZS5hbmRyb2lkLmdvb2ds
+ZS5jboIKdXJjaGluLmNvbYIKd3d3Lmdvby5nbIIIeW91dHUuYmWCC3lvdXR1YmUu
+Y29tghR5b3V0dWJlZWR1Y2F0aW9uLmNvbYIPeW91dHViZWtpZHMuY29tggV5dC5i
+ZTAhBgNVHSAEGjAYMAgGBmeBDAECAjAMBgorBgEEAdZ5AgUDMDMGA1UdHwQsMCow
+KKAmoCSGImh0dHA6Ly9jcmwucGtpLmdvb2cvR1RTMU8xY29yZS5jcmwwEwYKKwYB
+BAHWeQIEAwEB/wQCBQAwDQYJKoZIhvcNAQELBQADggEBAHh9/ozYUGRd+W5akWlM
+4WvX808TK2oUISnagbxCCFZ2trpg2oi03CJf4o4o3Je5Qzzz10s22oQY6gPHAR0B
+QHzrpqAveQw9D5vd8xjgtQ/SAujPzPKNQee5511rS7/EKW9I83ccd5XhhoEyx8A1
+/65RTS+2hKpJKTMkr0yHBPJV7kUW+n/KIef5YaSOA9VYK7hyH0niDpvm9EmoqvWS
+U5xAFAe/Xrrq3sxTuDJPQA8alk6h/ql5Klkw6dL53csiPka/MevDqdifWkzuT/6n
+YK/ePeJzPD17FA9V+N1rcuF3Wk29AZvCOSasdIkIuE82vGr3dfNrsrn9E9lWIbCr
+Qc4=
+-----END CERTIFICATE-----`,
+               },
+       }
+       for _, c := range cases {
+               b.Run(c.name, func(b *testing.B) {
+                       pemBlock, _ := pem.Decode([]byte(c.pem))
+                       b.ReportAllocs()
+                       b.ResetTimer()
+                       for i := 0; i < b.N; i++ {
+                               _, err := ParseCertificate(pemBlock.Bytes)
+                               if err != nil {
+                                       b.Fatal(err)
+                               }
+                       }
+               })
+       }
+}
+
+func TestParseCertificateRawEquals(t *testing.T) {
+       p, _ := pem.Decode([]byte(pemCertificate))
+       cert, err := ParseCertificate(p.Bytes)
+       if err != nil {
+               t.Fatalf("failed to parse certificate: %s", err)
+       }
+       if !bytes.Equal(p.Bytes, cert.Raw) {
+               t.Fatalf("unexpected Certificate.Raw\ngot: %x\nwant: %x\n", cert.Raw, p.Bytes)
+       }
+       fmt.Printf("in:  %x\nout: %x\n", p.Bytes, cert.Raw)
+}
+
+// mismatchingSigAlgIDPEM contains a certificate where the Certificate
+// signatureAlgorithm and the TBSCertificate signature contain
+// mismatching OIDs
+const mismatchingSigAlgIDPEM = `-----BEGIN CERTIFICATE-----
+MIIBBzCBrqADAgECAgEAMAoGCCqGSM49BAMCMAAwIhgPMDAwMTAxMDEwMDAwMDBa
+GA8wMDAxMDEwMTAwMDAwMFowADBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOqV
+EDuVXxwZgIU3+dOwv1SsMu0xuV48hf7xmK8n7sAMYgllB+96DnPqBeboJj4snYnx
+0AcE0PDVQ1l4Z3YXsQWjFTATMBEGA1UdEQEB/wQHMAWCA2FzZDAKBggqhkjOPQQD
+AwNIADBFAiBi1jz/T2HT5nAfrD7zsgR+68qh7Erc6Q4qlxYBOgKG4QIhAOtjIn+Q
+tA+bq+55P3ntxTOVRq0nv1mwnkjwt9cQR9Fn
+-----END CERTIFICATE-----`
+
+// mismatchingSigAlgParamPEM contains a certificate where the Certificate
+// signatureAlgorithm and the TBSCertificate signature contain
+// mismatching parameters
+const mismatchingSigAlgParamPEM = `-----BEGIN CERTIFICATE-----
+MIIBCTCBrqADAgECAgEAMAoGCCqGSM49BAMCMAAwIhgPMDAwMTAxMDEwMDAwMDBa
+GA8wMDAxMDEwMTAwMDAwMFowADBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOqV
+EDuVXxwZgIU3+dOwv1SsMu0xuV48hf7xmK8n7sAMYgllB+96DnPqBeboJj4snYnx
+0AcE0PDVQ1l4Z3YXsQWjFTATMBEGA1UdEQEB/wQHMAWCA2FzZDAMBggqhkjOPQQD
+AgUAA0gAMEUCIGLWPP9PYdPmcB+sPvOyBH7ryqHsStzpDiqXFgE6AobhAiEA62Mi
+f5C0D5ur7nk/ee3FM5VGrSe/WbCeSPC31xBH0Wc=
+-----END CERTIFICATE-----`
+
+func TestSigAlgMismatch(t *testing.T) {
+       for _, certPEM := range []string{mismatchingSigAlgIDPEM, mismatchingSigAlgParamPEM} {
+               b, _ := pem.Decode([]byte(certPEM))
+               if b == nil {
+                       t.Fatalf("couldn't decode test certificate")
+               }
+               _, err := ParseCertificate(b.Bytes)
+               if err == nil {
+                       t.Fatalf("expected ParseCertificate to fail")
+               }
+               expected := "x509: inner and outer signature algorithm identifiers don't match"
+               if err.Error() != expected {
+                       t.Errorf("unexpected error from ParseCertificate: got %q, want %q", err.Error(), expected)
+               }
+       }
+}
+
+const optionalAuthKeyIDPEM = `-----BEGIN CERTIFICATE-----
+MIIFEjCCBHugAwIBAgICAQwwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1Zh
+bGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIElu
+Yy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24g
+QXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAe
+BgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTA0MDYyOTE3MzkxNloX
+DTI0MDYyOTE3MzkxNlowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVs
+ZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAy
+IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0A
+MIIBCAKCAQEAtzLI/ulxpgSFrQwRZN/OTe/IAxiHP6Gr+zymn/DDodrU2G4rU5D7
+JKQ+hPCe6F/s5SdE9SimP3ve4CrwyK9TL57KBQGTHo9mHDmnTfpatnMEJWbrd3/n
+WcZKmSUUVOsmx/N/GdUwcI+vsEYq/63rKe3Xn6oEh6PU+YmlNF/bQ5GCNtlmPLG4
+uYL9nDo+EMg77wZlZnqbGRg9/3FRPDAuX749d3OyXQZswyNWmiuFJpIcpwKz5D8N
+rwh5grg2Peqc0zWzvGnK9cyd6P1kjReAM25eSl2ZyR6HtJ0awNVuEzUjXt+bXz3v
+1vd2wuo+u3gNHEJnawTY+Nbab4vyRKABqwIBA6OCAfMwggHvMB0GA1UdDgQWBBS/
+X7fRzt0fhvRbVazc1xDCDqmI5zCB0gYDVR0jBIHKMIHHoYHBpIG+MIG7MSQwIgYD
+VQQHExtWYWxpQ2VydCBWYWxpZGF0aW9uIE5ldHdvcmsxFzAVBgNVBAoTDlZhbGlD
+ZXJ0LCBJbmMuMTUwMwYDVQQLEyxWYWxpQ2VydCBDbGFzcyAyIFBvbGljeSBWYWxp
+ZGF0aW9uIEF1dGhvcml0eTEhMB8GA1UEAxMYaHR0cDovL3d3dy52YWxpY2VydC5j
+b20vMSAwHgYJKoZIhvcNAQkBFhFpbmZvQHZhbGljZXJ0LmNvbYIBATAPBgNVHRMB
+Af8EBTADAQH/MDkGCCsGAQUFBwEBBC0wKzApBggrBgEFBQcwAYYdaHR0cDovL29j
+c3Auc3RhcmZpZWxkdGVjaC5jb20wSgYDVR0fBEMwQTA/oD2gO4Y5aHR0cDovL2Nl
+cnRpZmljYXRlcy5zdGFyZmllbGR0ZWNoLmNvbS9yZXBvc2l0b3J5L3Jvb3QuY3Js
+MFEGA1UdIARKMEgwRgYEVR0gADA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY2VydGlm
+aWNhdGVzLnN0YXJmaWVsZHRlY2guY29tL3JlcG9zaXRvcnkwDgYDVR0PAQH/BAQD
+AgEGMA0GCSqGSIb3DQEBBQUAA4GBAKVi8afCXSWlcD284ipxs33kDTcdVWptobCr
+mADkhWBKIMuh8D1195TaQ39oXCUIuNJ9MxB73HZn8bjhU3zhxoNbKXuNSm8uf0So
+GkVrMgfHeMpkksK0hAzc3S1fTbvdiuo43NlmouxBulVtWmQ9twPMHOKRUJ7jCUSV
+FxdzPcwl
+-----END CERTIFICATE-----`
+
+func TestAuthKeyIdOptional(t *testing.T) {
+       b, _ := pem.Decode([]byte(optionalAuthKeyIDPEM))
+       if b == nil {
+               t.Fatalf("couldn't decode test certificate")
+       }
+       _, err := ParseCertificate(b.Bytes)
+       if err != nil {
+               t.Fatalf("ParseCertificate to failed to parse certificate with optional authority key identifier fields: %s", err)
+       }
+}
index b778df261aa84b9373a089a4adb5e99014bb7f5c..ef3ee807bf0c5d037d7ce8beea4a7d8be9f39acb 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 // This file is run by the x509 tests to ensure that a program with minimal
index 5bbcf20db2f07d90f91d1d3d2f82786b55b7d948..f09396175acf86099e5d902fb944d1f8131210e2 100644 (file)
@@ -115,6 +115,9 @@ type DriverContext interface {
 // DriverContext's OpenConnector method, to allow drivers
 // access to context and to avoid repeated parsing of driver
 // configuration.
+//
+// If a Connector implements io.Closer, the sql package's DB.Close
+// method will call Close and return error (if any).
 type Connector interface {
        // Connect returns a connection to the database.
        // Connect may return a cached connection (one previously
index 7605a2a6d23e0327bcccaf1d8a8cd9d616a26a23..4b68f1cba9fe1aa7f9b2806494a8eb4c6c9e066f 100644 (file)
@@ -56,6 +56,7 @@ type fakeConnector struct {
        name string
 
        waiter func(context.Context)
+       closed bool
 }
 
 func (c *fakeConnector) Connect(context.Context) (driver.Conn, error) {
@@ -68,6 +69,14 @@ func (c *fakeConnector) Driver() driver.Driver {
        return fdriver
 }
 
+func (c *fakeConnector) Close() error {
+       if c.closed {
+               return errors.New("fakedb: connector is closed")
+       }
+       c.closed = true
+       return nil
+}
+
 type fakeDriverCtx struct {
        fakeDriver
 }
@@ -906,7 +915,7 @@ func (s *fakeStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (
                                parentMem: s.c,
                                posRow:    -1,
                                rows: [][]*row{
-                                       []*row{
+                                       {
                                                {
                                                        cols: []interface{}{
                                                                txStatus,
@@ -915,12 +924,12 @@ func (s *fakeStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (
                                        },
                                },
                                cols: [][]string{
-                                       []string{
+                                       {
                                                "tx_status",
                                        },
                                },
                                colType: [][]string{
-                                       []string{
+                                       {
                                                "string",
                                        },
                                },
@@ -1177,9 +1186,11 @@ func converterForType(typ string) driver.ValueConverter {
                return driver.Bool
        case "nullbool":
                return driver.Null{Converter: driver.Bool}
+       case "byte", "int16":
+               return driver.NotNull{Converter: driver.DefaultParameterConverter}
        case "int32":
                return driver.Int32
-       case "nullint32":
+       case "nullbyte", "nullint32", "nullint16":
                return driver.Null{Converter: driver.DefaultParameterConverter}
        case "string":
                return driver.NotNull{Converter: fakeDriverString{}}
@@ -1213,6 +1224,10 @@ func colTypeToReflectType(typ string) reflect.Type {
                return reflect.TypeOf(false)
        case "nullbool":
                return reflect.TypeOf(NullBool{})
+       case "int16":
+               return reflect.TypeOf(int16(0))
+       case "nullint16":
+               return reflect.TypeOf(NullInt16{})
        case "int32":
                return reflect.TypeOf(int32(0))
        case "nullint32":
index 726aadb8990e6871fdb1253e4f422e60b39f229f..68fb392e0dbb45f5f4246fa8f95797250dee0735 100644 (file)
@@ -260,6 +260,60 @@ func (n NullInt32) Value() (driver.Value, error) {
        return int64(n.Int32), nil
 }
 
+// NullInt16 represents an int16 that may be null.
+// NullInt16 implements the Scanner interface so
+// it can be used as a scan destination, similar to NullString.
+type NullInt16 struct {
+       Int16 int16
+       Valid bool // Valid is true if Int16 is not NULL
+}
+
+// Scan implements the Scanner interface.
+func (n *NullInt16) Scan(value interface{}) error {
+       if value == nil {
+               n.Int16, n.Valid = 0, false
+               return nil
+       }
+       err := convertAssign(&n.Int16, value)
+       n.Valid = err == nil
+       return err
+}
+
+// Value implements the driver Valuer interface.
+func (n NullInt16) Value() (driver.Value, error) {
+       if !n.Valid {
+               return nil, nil
+       }
+       return int64(n.Int16), nil
+}
+
+// NullByte represents a byte that may be null.
+// NullByte implements the Scanner interface so
+// it can be used as a scan destination, similar to NullString.
+type NullByte struct {
+       Byte  byte
+       Valid bool // Valid is true if Byte is not NULL
+}
+
+// Scan implements the Scanner interface.
+func (n *NullByte) Scan(value interface{}) error {
+       if value == nil {
+               n.Byte, n.Valid = 0, false
+               return nil
+       }
+       err := convertAssign(&n.Byte, value)
+       n.Valid = err == nil
+       return err
+}
+
+// Value implements the driver Valuer interface.
+func (n NullByte) Value() (driver.Value, error) {
+       if !n.Valid {
+               return nil, nil
+       }
+       return int64(n.Byte), nil
+}
+
 // NullFloat64 represents a float64 that may be null.
 // NullFloat64 implements the Scanner interface so
 // it can be used as a scan destination, similar to NullString.
@@ -813,6 +867,9 @@ func (db *DB) PingContext(ctx context.Context) error {
 
 // Ping verifies a connection to the database is still alive,
 // establishing a connection if necessary.
+//
+// Ping uses context.Background internally; to specify the context, use
+// PingContext.
 func (db *DB) Ping() error {
        return db.PingContext(context.Background())
 }
@@ -850,6 +907,12 @@ func (db *DB) Close() error {
                }
        }
        db.stop()
+       if c, ok := db.connector.(io.Closer); ok {
+               err1 := c.Close()
+               if err1 != nil {
+                       err = err1
+               }
+       }
        return err
 }
 
@@ -1475,6 +1538,9 @@ func (db *DB) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
 // returned statement.
 // The caller must call the statement's Close method
 // when the statement is no longer needed.
+//
+// Prepare uses context.Background internally; to specify the context, use
+// PrepareContext.
 func (db *DB) Prepare(query string) (*Stmt, error) {
        return db.PrepareContext(context.Background(), query)
 }
@@ -1545,6 +1611,9 @@ func (db *DB) ExecContext(ctx context.Context, query string, args ...interface{}
 
 // Exec executes a query without returning any rows.
 // The args are for any placeholder parameters in the query.
+//
+// Exec uses context.Background internally; to specify the context, use
+// ExecContext.
 func (db *DB) Exec(query string, args ...interface{}) (Result, error) {
        return db.ExecContext(context.Background(), query, args...)
 }
@@ -1615,6 +1684,9 @@ func (db *DB) QueryContext(ctx context.Context, query string, args ...interface{
 
 // Query executes a query that returns rows, typically a SELECT.
 // The args are for any placeholder parameters in the query.
+//
+// Query uses context.Background internally; to specify the context, use
+// QueryContext.
 func (db *DB) Query(query string, args ...interface{}) (*Rows, error) {
        return db.QueryContext(context.Background(), query, args...)
 }
@@ -1713,6 +1785,9 @@ func (db *DB) QueryRowContext(ctx context.Context, query string, args ...interfa
 // If the query selects no rows, the *Row's Scan will return ErrNoRows.
 // Otherwise, the *Row's Scan scans the first selected row and discards
 // the rest.
+//
+// QueryRow uses context.Background internally; to specify the context, use
+// QueryRowContext.
 func (db *DB) QueryRow(query string, args ...interface{}) *Row {
        return db.QueryRowContext(context.Background(), query, args...)
 }
@@ -1744,6 +1819,9 @@ func (db *DB) BeginTx(ctx context.Context, opts *TxOptions) (*Tx, error) {
 
 // Begin starts a transaction. The default isolation level is dependent on
 // the driver.
+//
+// Begin uses context.Background internally; to specify the context, use
+// BeginTx.
 func (db *DB) Begin() (*Tx, error) {
        return db.BeginTx(context.Background(), nil)
 }
@@ -1771,7 +1849,7 @@ func (db *DB) beginDC(ctx context.Context, dc *driverConn, release func(error),
                return nil, err
        }
 
-       // Schedule the transaction to rollback when the context is cancelled.
+       // Schedule the transaction to rollback when the context is canceled.
        // The cancel function in Tx will be called after done is set to true.
        ctx, cancel := context.WithCancel(ctx)
        tx = &Tx{
@@ -2249,6 +2327,9 @@ func (tx *Tx) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
 // be used once the transaction has been committed or rolled back.
 //
 // To use an existing prepared statement on this transaction, see Tx.Stmt.
+//
+// Prepare uses context.Background internally; to specify the context, use
+// PrepareContext.
 func (tx *Tx) Prepare(query string) (*Stmt, error) {
        return tx.PrepareContext(context.Background(), query)
 }
@@ -2352,6 +2433,9 @@ func (tx *Tx) StmtContext(ctx context.Context, stmt *Stmt) *Stmt {
 //
 // The returned statement operates within the transaction and will be closed
 // when the transaction has been committed or rolled back.
+//
+// Stmt uses context.Background internally; to specify the context, use
+// StmtContext.
 func (tx *Tx) Stmt(stmt *Stmt) *Stmt {
        return tx.StmtContext(context.Background(), stmt)
 }
@@ -2368,6 +2452,9 @@ func (tx *Tx) ExecContext(ctx context.Context, query string, args ...interface{}
 
 // Exec executes a query that doesn't return rows.
 // For example: an INSERT and UPDATE.
+//
+// Exec uses context.Background internally; to specify the context, use
+// ExecContext.
 func (tx *Tx) Exec(query string, args ...interface{}) (Result, error) {
        return tx.ExecContext(context.Background(), query, args...)
 }
@@ -2383,6 +2470,9 @@ func (tx *Tx) QueryContext(ctx context.Context, query string, args ...interface{
 }
 
 // Query executes a query that returns rows, typically a SELECT.
+//
+// Query uses context.Background internally; to specify the context, use
+// QueryContext.
 func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) {
        return tx.QueryContext(context.Background(), query, args...)
 }
@@ -2404,6 +2494,9 @@ func (tx *Tx) QueryRowContext(ctx context.Context, query string, args ...interfa
 // If the query selects no rows, the *Row's Scan will return ErrNoRows.
 // Otherwise, the *Row's Scan scans the first selected row and discards
 // the rest.
+//
+// QueryRow uses context.Background internally; to specify the context, use
+// QueryRowContext.
 func (tx *Tx) QueryRow(query string, args ...interface{}) *Row {
        return tx.QueryRowContext(context.Background(), query, args...)
 }
@@ -2510,6 +2603,9 @@ func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (Result, er
 
 // Exec executes a prepared statement with the given arguments and
 // returns a Result summarizing the effect of the statement.
+//
+// Exec uses context.Background internally; to specify the context, use
+// ExecContext.
 func (s *Stmt) Exec(args ...interface{}) (Result, error) {
        return s.ExecContext(context.Background(), args...)
 }
@@ -2681,6 +2777,9 @@ func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, er
 
 // Query executes a prepared query statement with the given arguments
 // and returns the query results as a *Rows.
+//
+// Query uses context.Background internally; to specify the context, use
+// QueryContext.
 func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
        return s.QueryContext(context.Background(), args...)
 }
@@ -2720,6 +2819,9 @@ func (s *Stmt) QueryRowContext(ctx context.Context, args ...interface{}) *Row {
 //
 //  var name string
 //  err := nameByUseridStmt.QueryRow(id).Scan(&name)
+//
+// QueryRow uses context.Background internally; to specify the context, use
+// QueryRowContext.
 func (s *Stmt) QueryRow(args ...interface{}) *Row {
        return s.QueryRowContext(context.Background(), args...)
 }
index c968852adeefeb321b14bc2993a459a82a8ff760..f771dee4a9772a37444ef9b65d27de9b12af887a 100644 (file)
@@ -431,25 +431,24 @@ func TestTxContextWait(t *testing.T) {
        db := newTestDB(t, "people")
        defer closeDB(t, db)
 
-       ctx, cancel := context.WithTimeout(context.Background(), 15*time.Millisecond)
-       defer cancel()
+       ctx, cancel := context.WithCancel(context.Background())
 
        tx, err := db.BeginTx(ctx, nil)
        if err != nil {
-               // Guard against the context being canceled before BeginTx completes.
-               if err == context.DeadlineExceeded {
-                       t.Skip("tx context canceled prior to first use")
-               }
                t.Fatal(err)
        }
        tx.keepConnOnRollback = false
 
+       go func() {
+               time.Sleep(15 * time.Millisecond)
+               cancel()
+       }()
        // This will trigger the *fakeConn.Prepare method which will take time
        // performing the query. The ctxDriverPrepare func will check the context
        // after this and close the rows and return an error.
        _, err = tx.QueryContext(ctx, "WAIT|1s|SELECT|people|age,name|")
-       if err != context.DeadlineExceeded {
-               t.Fatalf("expected QueryContext to error with context deadline exceeded but returned %v", err)
+       if err != context.Canceled {
+               t.Fatalf("expected QueryContext to error with context canceled but returned %v", err)
        }
 
        waitForFree(t, db, 5*time.Second, 0)
@@ -657,7 +656,7 @@ func TestPoolExhaustOnCancel(t *testing.T) {
        db.SetMaxOpenConns(max)
 
        // First saturate the connection pool.
-       // Then start new requests for a connection that is cancelled after it is requested.
+       // Then start new requests for a connection that is canceled after it is requested.
 
        state = 1
        for i := 0; i < max; i++ {
@@ -1820,6 +1819,30 @@ func TestNullInt32Param(t *testing.T) {
        nullTestRun(t, spec)
 }
 
+func TestNullInt16Param(t *testing.T) {
+       spec := nullTestSpec{"nullint16", "int16", [6]nullTestRow{
+               {NullInt16{31, true}, 1, NullInt16{31, true}},
+               {NullInt16{-22, false}, 1, NullInt16{0, false}},
+               {22, 1, NullInt16{22, true}},
+               {NullInt16{33, true}, 1, NullInt16{33, true}},
+               {NullInt16{222, false}, 1, NullInt16{0, false}},
+               {0, NullInt16{31, false}, nil},
+       }}
+       nullTestRun(t, spec)
+}
+
+func TestNullByteParam(t *testing.T) {
+       spec := nullTestSpec{"nullbyte", "byte", [6]nullTestRow{
+               {NullByte{31, true}, 1, NullByte{31, true}},
+               {NullByte{0, false}, 1, NullByte{0, false}},
+               {22, 1, NullByte{22, true}},
+               {NullByte{33, true}, 1, NullByte{33, true}},
+               {NullByte{222, false}, 1, NullByte{0, false}},
+               {0, NullByte{31, false}, nil},
+       }}
+       nullTestRun(t, spec)
+}
+
 func TestNullFloat64Param(t *testing.T) {
        spec := nullTestSpec{"nullfloat64", "float64", [6]nullTestRow{
                {NullFloat64{31.2, true}, 1, NullFloat64{31.2, true}},
@@ -2785,7 +2808,7 @@ func TestTxCannotCommitAfterRollback(t *testing.T) {
        // 3. Check if 2.A has committed in Tx (pass) or outside of Tx (fail).
        sendQuery := make(chan struct{})
        // The Tx status is returned through the row results, ensure
-       // that the rows results are not cancelled.
+       // that the rows results are not canceled.
        bypassRowsAwaitDone = true
        hookTxGrabConn = func() {
                cancel()
@@ -2815,7 +2838,7 @@ func TestTxStmtDeadlock(t *testing.T) {
        db := newTestDB(t, "people")
        defer closeDB(t, db)
 
-       ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond)
+       ctx, cancel := context.WithCancel(context.Background())
        defer cancel()
        tx, err := db.BeginTx(ctx, nil)
        if err != nil {
@@ -2826,6 +2849,7 @@ func TestTxStmtDeadlock(t *testing.T) {
        if err != nil {
                t.Fatal(err)
        }
+       cancel()
        // Run number of stmt queries to reproduce deadlock from context cancel
        for i := 0; i < 1e3; i++ {
                // Encounter any close related errors (e.g. ErrTxDone, stmt is closed)
@@ -4060,9 +4084,18 @@ func TestOpenConnector(t *testing.T) {
        }
        defer db.Close()
 
-       if _, is := db.connector.(*fakeConnector); !is {
+       c, ok := db.connector.(*fakeConnector)
+       if !ok {
                t.Fatal("not using *fakeConnector")
        }
+
+       if err := db.Close(); err != nil {
+               t.Fatal(err)
+       }
+
+       if !c.closed {
+               t.Fatal("connector is not closed")
+       }
 }
 
 type ctxOnlyDriver struct {
index c60709199b003d9f5296146f0f66b10b23b45f42..c0a74b08bb85874addb64737ad524c7a5ffdd82b 100644 (file)
@@ -427,7 +427,7 @@ const (
        lneSetDiscriminator = 4
 )
 
-// Line table directory directory and file name entry formats.
+// Line table directory and file name entry formats.
 // These are new in DWARF 5.
 const (
        lnctPath           = 0x01
index 3fc73b8ead29dbe0ab50fa96635d0d939a20b92a..9f5ac570803d4c4d351633155f51ddb679eb617e 100644 (file)
@@ -317,7 +317,7 @@ const (
        // the "mac" section.
        ClassMacPtr
 
-       // ClassMacPtr represents values that are an int64 offset into
+       // ClassRangeListPtr represents values that are an int64 offset into
        // the "rangelist" section.
        ClassRangeListPtr
 
@@ -355,7 +355,7 @@ const (
        // into the "loclists" section.
        ClassLocList
 
-       // ClassRngList represents values that are aint64 offset
+       // ClassRngList represents values that are a uint64 offset
        // from the base of the "rnglists" section.
        ClassRngList
 
@@ -464,6 +464,35 @@ func (b *buf) entry(cu *Entry, atab abbrevTable, ubase Offset, vers int) *Entry
                return val
        }
 
+       resolveRnglistx := func(rnglistsBase, off uint64) uint64 {
+               is64, _ := b.format.dwarf64()
+               if is64 {
+                       off *= 8
+               } else {
+                       off *= 4
+               }
+               off += rnglistsBase
+               if uint64(int(off)) != off {
+                       b.error("DW_FORM_rnglistx offset out of range")
+               }
+
+               b1 := makeBuf(b.dwarf, b.format, "rnglists", 0, b.dwarf.rngLists)
+               b1.skip(int(off))
+               if is64 {
+                       off = b1.uint64()
+               } else {
+                       off = uint64(b1.uint32())
+               }
+               if b1.err != nil {
+                       b.err = b1.err
+                       return 0
+               }
+               if uint64(int(off)) != off {
+                       b.error("DW_FORM_rnglistx indirect offset out of range")
+               }
+               return rnglistsBase + off
+       }
+
        for i := range e.Field {
                e.Field[i].Attr = a.field[i].attr
                e.Field[i].Class = a.field[i].class
@@ -709,7 +738,21 @@ func (b *buf) entry(cu *Entry, atab abbrevTable, ubase Offset, vers int) *Entry
 
                // rnglist
                case formRnglistx:
-                       val = b.uint()
+                       off := b.uint()
+
+                       // We have to adjust by the rnglists_base of
+                       // the compilation unit. This won't work if
+                       // the program uses Reader.Seek to skip over
+                       // the unit. Not much we can do about that.
+                       var rnglistsBase int64
+                       if cu != nil {
+                               rnglistsBase, _ = cu.Val(AttrRnglistsBase).(int64)
+                       } else if a.tag == TagCompileUnit {
+                               delay = append(delay, delayed{i, off, formRnglistx})
+                               break
+                       }
+
+                       val = resolveRnglistx(uint64(rnglistsBase), off)
                }
 
                e.Field[i].Val = val
@@ -734,6 +777,12 @@ func (b *buf) entry(cu *Entry, atab abbrevTable, ubase Offset, vers int) *Entry
                        if b.err != nil {
                                return nil
                        }
+               case formRnglistx:
+                       rnglistsBase, _ := e.Val(AttrRnglistsBase).(int64)
+                       e.Field[del.idx].Val = resolveRnglistx(uint64(rnglistsBase), del.off)
+                       if b.err != nil {
+                               return nil
+                       }
                }
        }
 
@@ -993,8 +1042,15 @@ func (d *Data) Ranges(e *Entry) ([][2]uint64, error) {
                        return d.dwarf5Ranges(u, cu, base, ranges, ret)
 
                case ClassRngList:
-                       // TODO: support DW_FORM_rnglistx
-                       return ret, nil
+                       rnglist, ok := field.Val.(uint64)
+                       if !ok {
+                               return ret, nil
+                       }
+                       cu, base, err := d.baseAddressForEntry(e)
+                       if err != nil {
+                               return nil, err
+                       }
+                       return d.dwarf5Ranges(u, cu, base, int64(rnglist), ret)
 
                default:
                        return ret, nil
index b54f8b4f8daa0405ded856afa331b37e9cbdc76f..1f41d742ea5de2916561339a7c790d2af1877286 100644 (file)
@@ -84,6 +84,19 @@ func TestRangesSection(t *testing.T) {
        testRanges(t, "testdata/ranges.elf", want)
 }
 
+func TestRangesRnglistx(t *testing.T) {
+       want := []wantRange{
+               {0x401000, [][2]uint64{{0x401020, 0x40102c}, {0x401000, 0x40101d}}},
+               {0x40101c, [][2]uint64{{0x401020, 0x40102c}, {0x401000, 0x40101d}}},
+               {0x40101d, nil},
+               {0x40101f, nil},
+               {0x401020, [][2]uint64{{0x401020, 0x40102c}, {0x401000, 0x40101d}}},
+               {0x40102b, [][2]uint64{{0x401020, 0x40102c}, {0x401000, 0x40101d}}},
+               {0x40102c, nil},
+       }
+       testRanges(t, "testdata/rnglistx.elf", want)
+}
+
 func testRanges(t *testing.T, name string, want []wantRange) {
        d := elfData(t, name)
        r := d.Reader()
index b13818e8b5082ec585ee253aa40814a0c4286b30..9c6b6ff5b0326674ca38b59fdea3c6ad383fd973 100644 (file)
@@ -117,6 +117,29 @@ func TestLineELFClang(t *testing.T) {
        testLineTable(t, want, files, elfData(t, "testdata/line-clang.elf"))
 }
 
+func TestLineRnglists(t *testing.T) {
+       // Test a newer file, generated by clang.
+       file := &LineFile{Name: "/usr/local/google/home/iant/foo.c"}
+       want := []LineEntry{
+               {Address: 0x401020, File: file, Line: 12, IsStmt: true},
+               {Address: 0x401020, File: file, Line: 13, Column: 12, IsStmt: true, PrologueEnd: true},
+               {Address: 0x401022, File: file, Line: 13, Column: 7},
+               {Address: 0x401024, File: file, Line: 17, Column: 1, IsStmt: true},
+               {Address: 0x401027, File: file, Line: 16, Column: 10, IsStmt: true},
+               {Address: 0x40102c, EndSequence: true},
+               {Address: 0x401000, File: file, Line: 2, IsStmt: true},
+               {Address: 0x401000, File: file, Line: 6, Column: 17, IsStmt: true, PrologueEnd: true},
+               {Address: 0x401002, File: file, Line: 6, Column: 3},
+               {Address: 0x401019, File: file, Line: 9, Column: 3, IsStmt: true},
+               {Address: 0x40101a, File: file, Line: 0, Column: 3},
+               {Address: 0x40101c, File: file, Line: 9, Column: 3},
+               {Address: 0x40101d, EndSequence: true},
+       }
+       files := [][]*LineFile{{file}}
+
+       testLineTable(t, want, files, elfData(t, "testdata/rnglistx.elf"))
+}
+
 func TestLineSeek(t *testing.T) {
        d := elfData(t, "testdata/line-gcc.elf")
 
diff --git a/libgo/go/debug/dwarf/testdata/rnglistx.c b/libgo/go/debug/dwarf/testdata/rnglistx.c
new file mode 100644 (file)
index 0000000..8770435
--- /dev/null
@@ -0,0 +1,19 @@
+// clang -gdwarf-5 -O2 -nostdlib
+
+__attribute__((noinline, cold))
+static int sum(int i) {
+  int j, s;
+
+  s = 0;
+  for (j = 0; j < i; j++) {
+    s += j * i;
+  }
+  return s;
+}
+
+int main(int argc, char** argv) {
+  if (argc == 0) {
+    return 0;
+  }
+  return sum(argc);
+}
diff --git a/libgo/go/debug/dwarf/testdata/rnglistx.elf b/libgo/go/debug/dwarf/testdata/rnglistx.elf
new file mode 100755 (executable)
index 0000000..c2d7f55
Binary files /dev/null and b/libgo/go/debug/dwarf/testdata/rnglistx.elf differ
index 316db258f654412406a63153411bfd6253298fd3..eb5a666ed38d3bcaf1cc42a0b54c5e28ef63453a 100644 (file)
@@ -292,11 +292,35 @@ func (d *Data) Type(off Offset) (Type, error) {
        return d.readType("info", d.Reader(), off, d.typeCache, nil)
 }
 
+type typeFixer struct {
+       typedefs   []*TypedefType
+       arraytypes []*Type
+}
+
+func (tf *typeFixer) recordArrayType(t *Type) {
+       if t == nil {
+               return
+       }
+       _, ok := (*t).(*ArrayType)
+       if ok {
+               tf.arraytypes = append(tf.arraytypes, t)
+       }
+}
+
+func (tf *typeFixer) apply() {
+       for _, t := range tf.typedefs {
+               t.Common().ByteSize = t.Type.Size()
+       }
+       for _, t := range tf.arraytypes {
+               zeroArray(t)
+       }
+}
+
 // readType reads a type from r at off of name. It adds types to the
 // type cache, appends new typedef types to typedefs, and computes the
 // sizes of types. Callers should pass nil for typedefs; this is used
 // for internal recursion.
-func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Offset]Type, typedefs *[]*TypedefType) (Type, error) {
+func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Offset]Type, fixups *typeFixer) (Type, error) {
        if t, ok := typeCache[off]; ok {
                return t, nil
        }
@@ -311,18 +335,16 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off
        }
 
        // If this is the root of the recursion, prepare to resolve
-       // typedef sizes once the recursion is done. This must be done
-       // after the type graph is constructed because it may need to
-       // resolve cycles in a different order than readType
-       // encounters them.
-       if typedefs == nil {
-               var typedefList []*TypedefType
+       // typedef sizes and perform other fixups once the recursion is
+       // done. This must be done after the type graph is constructed
+       // because it may need to resolve cycles in a different order than
+       // readType encounters them.
+       if fixups == nil {
+               var fixer typeFixer
                defer func() {
-                       for _, t := range typedefList {
-                               t.Common().ByteSize = t.Type.Size()
-                       }
+                       fixer.apply()
                }()
-               typedefs = &typedefList
+               fixups = &fixer
        }
 
        // Parse type from Entry.
@@ -376,7 +398,7 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off
                var t Type
                switch toff := tval.(type) {
                case Offset:
-                       if t, err = d.readType(name, r.clone(), toff, typeCache, typedefs); err != nil {
+                       if t, err = d.readType(name, r.clone(), toff, typeCache, fixups); err != nil {
                                return nil
                        }
                case uint64:
@@ -567,7 +589,7 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off
                        if bito == lastFieldBitOffset && t.Kind != "union" {
                                // Last field was zero width. Fix array length.
                                // (DWARF writes out 0-length arrays as if they were 1-length arrays.)
-                               zeroArray(lastFieldType)
+                               fixups.recordArrayType(lastFieldType)
                        }
                        lastFieldType = &f.Type
                        lastFieldBitOffset = bito
@@ -576,7 +598,7 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off
                        b, ok := e.Val(AttrByteSize).(int64)
                        if ok && b*8 == lastFieldBitOffset {
                                // Final field must be zero width. Fix array length.
-                               zeroArray(lastFieldType)
+                               fixups.recordArrayType(lastFieldType)
                        }
                }
 
@@ -719,7 +741,7 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off
                                // Record that we need to resolve this
                                // type's size once the type graph is
                                // constructed.
-                               *typedefs = append(*typedefs, t)
+                               fixups.typedefs = append(fixups.typedefs, t)
                        case *PtrType:
                                b = int64(addressSize)
                        }
@@ -737,11 +759,8 @@ Error:
 }
 
 func zeroArray(t *Type) {
-       if t == nil {
-               return
-       }
-       at, ok := (*t).(*ArrayType)
-       if !ok || at.Type.Size() == 0 {
+       at := (*t).(*ArrayType)
+       if at.Type.Size() == 0 {
                return
        }
        // Make a copy to avoid invalidating typeCache.
index 29a744fd184895cf382dc068dd65c1e425c9580c..9b3d6e902d9993274e16dcbf0129a02a82497658 100644 (file)
@@ -48,7 +48,9 @@ func (d *Data) parseUnits() ([]unit, error) {
                        break
                }
                b.skip(int(len))
-               nunit++
+               if len > 0 {
+                       nunit++
+               }
        }
        if b.err != nil {
                return nil, b.err
@@ -61,7 +63,9 @@ func (d *Data) parseUnits() ([]unit, error) {
                u := &units[i]
                u.base = b.off
                var n Offset
-               n, u.is64 = b.unitLength()
+               for n == 0 {
+                       n, u.is64 = b.unitLength()
+               }
                dataOff := b.off
                vers := b.uint16()
                if vers < 2 || vers > 5 {
index 2b777eabac7bc351e5e1141f6e4421b1e12eff30..9f8399d4d3cef70a68bdb126b4a5c59f1be127d8 100644 (file)
@@ -123,8 +123,8 @@ const (
        ELFOSABI_NONE       OSABI = 0   /* UNIX System V ABI */
        ELFOSABI_HPUX       OSABI = 1   /* HP-UX operating system */
        ELFOSABI_NETBSD     OSABI = 2   /* NetBSD */
-       ELFOSABI_LINUX      OSABI = 3   /* GNU/Linux */
-       ELFOSABI_HURD       OSABI = 4   /* GNU/Hurd */
+       ELFOSABI_LINUX      OSABI = 3   /* Linux */
+       ELFOSABI_HURD       OSABI = 4   /* Hurd */
        ELFOSABI_86OPEN     OSABI = 5   /* 86Open common IA32 ABI */
        ELFOSABI_SOLARIS    OSABI = 6   /* Solaris */
        ELFOSABI_AIX        OSABI = 7   /* AIX */
@@ -644,6 +644,7 @@ const (
        SHT_GNU_VERSYM     SectionType = 0x6fffffff /* GNU version symbol table */
        SHT_HIOS           SectionType = 0x6fffffff /* Last of OS specific semantics */
        SHT_LOPROC         SectionType = 0x70000000 /* reserved range for processor */
+       SHT_MIPS_ABIFLAGS  SectionType = 0x7000002a /* .MIPS.abiflags */
        SHT_HIPROC         SectionType = 0x7fffffff /* specific section header types */
        SHT_LOUSER         SectionType = 0x80000000 /* reserved range for application */
        SHT_HIUSER         SectionType = 0xffffffff /* specific indexes */
@@ -675,6 +676,7 @@ var shtStrings = []intName{
        {0x6ffffffe, "SHT_GNU_VERNEED"},
        {0x6fffffff, "SHT_GNU_VERSYM"},
        {0x70000000, "SHT_LOPROC"},
+       {0x7000002a, "SHT_MIPS_ABIFLAGS"},
        {0x7fffffff, "SHT_HIPROC"},
        {0x80000000, "SHT_LOUSER"},
        {0xffffffff, "SHT_HIUSER"},
index b4091670f9d3a87f6c35541a64d2b1792e361e59..38a9313ad3edb16be14fce68c557cc9a298bc358 100644 (file)
@@ -1299,6 +1299,13 @@ func (f *File) DWARF() (*dwarf.Data, error) {
                        b = dbuf
                }
 
+               if f.Type == ET_EXEC {
+                       // Do not apply relocations to DWARF sections for ET_EXEC binaries.
+                       // Relocations should already be applied, and .rela sections may
+                       // contain incorrect data.
+                       return b, nil
+               }
+
                for _, r := range f.Sections {
                        if r.Type != SHT_RELA && r.Type != SHT_REL {
                                continue
index 49e107eed3de960df0adf7e12db0c3199b0202d7..9fa9f9575290bd1a7f8774f9b287696aa316dca7 100644 (file)
@@ -4,7 +4,7 @@
 
 // Mach-O header data structures
 // Originally at:
-// http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html (since deleted by Apply)
+// http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html (since deleted by Apple)
 // Archived copy at:
 // https://web.archive.org/web/20090819232456/http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachORuntime/index.html
 // For cloned PDF see:
index 7d763fff19d5005b1bb31ca6189df70329f22055..e50229e5a3676b8c4e30ad61de9ca3c326fc7c6d 100644 (file)
@@ -75,7 +75,7 @@ func NewFile(r io.ReaderAt) (*File, error) {
                var sign [4]byte
                r.ReadAt(sign[:], signoff)
                if !(sign[0] == 'P' && sign[1] == 'E' && sign[2] == 0 && sign[3] == 0) {
-                       return nil, fmt.Errorf("Invalid PE COFF file signature of %v.", sign)
+                       return nil, fmt.Errorf("invalid PE file signature: % x", sign)
                }
                base = signoff + 4
        } else {
@@ -86,9 +86,14 @@ func NewFile(r io.ReaderAt) (*File, error) {
                return nil, err
        }
        switch f.FileHeader.Machine {
-       case IMAGE_FILE_MACHINE_UNKNOWN, IMAGE_FILE_MACHINE_ARMNT, IMAGE_FILE_MACHINE_AMD64, IMAGE_FILE_MACHINE_I386:
+       case IMAGE_FILE_MACHINE_AMD64,
+               IMAGE_FILE_MACHINE_ARM64,
+               IMAGE_FILE_MACHINE_ARMNT,
+               IMAGE_FILE_MACHINE_I386,
+               IMAGE_FILE_MACHINE_UNKNOWN:
+               // ok
        default:
-               return nil, fmt.Errorf("Unrecognised COFF file header machine value of 0x%x.", f.FileHeader.Machine)
+               return nil, fmt.Errorf("unrecognized PE machine: %#x", f.FileHeader.Machine)
        }
 
        var err error
@@ -112,7 +117,7 @@ func NewFile(r io.ReaderAt) (*File, error) {
        // Seek past file header.
        _, err = sr.Seek(base+int64(binary.Size(f.FileHeader)), seekStart)
        if err != nil {
-               return nil, fmt.Errorf("failure to seek past the file header: %v", err)
+               return nil, err
        }
 
        // Read optional header.
@@ -309,7 +314,7 @@ func (f *File) ImportedSymbols() ([]string, error) {
                return nil, nil
        }
 
-       pe64 := f.Machine == IMAGE_FILE_MACHINE_AMD64
+       pe64 := f.Machine == IMAGE_FILE_MACHINE_AMD64 || f.Machine == IMAGE_FILE_MACHINE_ARM64
 
        // grab the number of data directory entries
        var dd_length uint32
index 739671d73f155d95d3e42c7bfee9e72d50f414ff..13eb4e62b2ed7687eacd4d0c25be3766b028be80 100644 (file)
@@ -2,12 +2,14 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build cgo
 // +build cgo
 
 package pe
 
 import (
        "os/exec"
+       "runtime"
        "testing"
 )
 
@@ -23,6 +25,9 @@ func TestDefaultLinkerDWARF(t *testing.T) {
 }
 
 func TestInternalLinkerDWARF(t *testing.T) {
+       if runtime.GOARCH == "arm64" {
+               t.Skip("internal linker disabled on windows/arm64")
+       }
        testCgoDWARF(t, linkCgoInternal)
 }
 
index 58deff14502b054d49a0cfbc2dddc9283af701c7..8964b4f847be6ee4d263adfd77e00beec98121dd 100644 (file)
@@ -353,11 +353,7 @@ func testDWARF(t *testing.T, linktype int) {
        }
        testenv.MustHaveGoRun(t)
 
-       tmpdir, err := os.MkdirTemp("", "TestDWARF")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(tmpdir)
+       tmpdir := t.TempDir()
 
        src := filepath.Join(tmpdir, "a.go")
        file, err := os.Create(src)
@@ -472,11 +468,7 @@ func TestBSSHasZeros(t *testing.T) {
                t.Skip("skipping test: gcc is missing")
        }
 
-       tmpdir, err := os.MkdirTemp("", "TestBSSHasZeros")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(tmpdir)
+       tmpdir := t.TempDir()
 
        srcpath := filepath.Join(tmpdir, "a.c")
        src := `
@@ -596,15 +588,10 @@ func TestBuildingWindowsGUI(t *testing.T) {
        if runtime.GOOS != "windows" {
                t.Skip("skipping windows only test")
        }
-       tmpdir, err := os.MkdirTemp("", "TestBuildingWindowsGUI")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(tmpdir)
+       tmpdir := t.TempDir()
 
        src := filepath.Join(tmpdir, "a.go")
-       err = os.WriteFile(src, []byte(`package main; func main() {}`), 0644)
-       if err != nil {
+       if err := os.WriteFile(src, []byte(`package main; func main() {}`), 0644); err != nil {
                t.Fatal(err)
        }
        exe := filepath.Join(tmpdir, "a.exe")
index 98da870ac6b00a8a224584fb4c734eb181184c46..851cc216fca2eba28e5898486cc4488113df7967 100644 (file)
@@ -143,7 +143,7 @@ import (
 // See the package documentation for more details about initializing an FS.
 type FS struct {
        // The compiler knows the layout of this struct.
-       // See cmd/compile/internal/gc's initEmbed.
+       // See cmd/compile/internal/staticdata's WriteEmbed.
        //
        // The files list is sorted by name but not by simple string comparison.
        // Instead, each file's name takes the form "dir/elem" or "dir/elem/".
@@ -213,7 +213,7 @@ var (
 // It implements fs.FileInfo and fs.DirEntry.
 type file struct {
        // The compiler knows the layout of this struct.
-       // See cmd/compile/internal/gc's initEmbed.
+       // See cmd/compile/internal/staticdata's WriteEmbed.
        name string
        data string
        hash [16]byte // truncated SHA256 hash
@@ -386,15 +386,15 @@ func (d *openDir) Read([]byte) (int, error) {
 
 func (d *openDir) ReadDir(count int) ([]fs.DirEntry, error) {
        n := len(d.files) - d.offset
-       if count > 0 && n > count {
-               n = count
-       }
        if n == 0 {
                if count <= 0 {
                        return nil, nil
                }
                return nil, io.EOF
        }
+       if count > 0 && n > count {
+               n = count
+       }
        list := make([]fs.DirEntry, n)
        for i := range list {
                list[i] = &d.files[d.offset+i]
index 43ae5c7e0569c87e3f9b08db68e24501a2c72ca1..2d50f5e01f1fafe1975dad2fc43c0fa83720e696 100644 (file)
@@ -102,12 +102,12 @@ func TestHidden(t *testing.T) {
        t.Logf("//go:embed testdata")
 
        testDir(t, dir, "testdata",
-               "ascii.txt", "glass.txt", "hello.txt", "i/", "ken.txt")
+               "-not-hidden/", "ascii.txt", "glass.txt", "hello.txt", "i/", "ken.txt")
 
        t.Logf("//go:embed testdata/*")
 
        testDir(t, star, "testdata",
-               ".hidden/", "_hidden/", "ascii.txt", "glass.txt", "hello.txt", "i/", "ken.txt")
+               "-not-hidden/", ".hidden/", "_hidden/", "ascii.txt", "glass.txt", "hello.txt", "i/", "ken.txt")
 
        testDir(t, star, "testdata/.hidden",
                "fortune.txt", "more/") // but not .more or _more
diff --git a/libgo/go/embed/internal/embedtest/testdata/-not-hidden/fortune.txt b/libgo/go/embed/internal/embedtest/testdata/-not-hidden/fortune.txt
new file mode 100644 (file)
index 0000000..31f2013
--- /dev/null
@@ -0,0 +1,2 @@
+WARNING: terminal is not fully functional
+ -  (press RETURN)
index f9b9cb4930e9890aaf90ab83522d7bf69982509b..cffc06dc9c8689f528203cbdb7251301322aa396 100644 (file)
@@ -914,7 +914,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
                structType := fieldType
 
                for i := 0; i < structType.NumField(); i++ {
-                       if structType.Field(i).PkgPath != "" {
+                       if !structType.Field(i).IsExported() {
                                err = StructuralError{"struct contains unexported fields"}
                                return
                        }
index 0d34d5aa1e815227bc1db6131e8643e7068ac3ab..5b4d786d495576bcf1007e99f11342eb0840bd81 100644 (file)
@@ -488,7 +488,7 @@ func makeBody(value reflect.Value, params fieldParameters) (e encoder, err error
                t := v.Type()
 
                for i := 0; i < t.NumField(); i++ {
-                       if t.Field(i).PkgPath != "" {
+                       if !t.Field(i).IsExported() {
                                return nil, StructuralError{"struct contains unexported fields"}
                        }
                }
index e3a7d8ff007a3452082ee9e4c977ea5b9d4627b8..f0217ba8a5e25c68cd870a97d94c791dc310aa8a 100644 (file)
@@ -306,7 +306,7 @@ func TestIssue11130(t *testing.T) {
                return
        }
        if !reflect.DeepEqual(v, v1) {
-               t.Errorf("got: %#v data=%q , want : %#v data=%q\n ", v1, data1, v, data)
+               t.Errorf("got: %#v data=%q, want : %#v data=%q\n ", v1, data1, v, data)
        }
 }
 
index 1fa325dec7fd944ad650788533dd3236047a05f2..8fe20b5c45d324f34ccf72752849c433a9bc2223 100644 (file)
@@ -61,8 +61,13 @@ func Uvarint(buf []byte) (uint64, int) {
        var x uint64
        var s uint
        for i, b := range buf {
+               if i == MaxVarintLen64 {
+                       // Catch byte reads past MaxVarintLen64.
+                       // See issue https://golang.org/issues/41185
+                       return 0, -(i + 1) // overflow
+               }
                if b < 0x80 {
-                       if i >= MaxVarintLen64 || i == MaxVarintLen64-1 && b > 1 {
+                       if i == MaxVarintLen64-1 && b > 1 {
                                return 0, -(i + 1) // overflow
                        }
                        return x | uint64(b)<<s, i + 1
index 6ef4c9950525a45c56eb7a11c5bb2ca443693b09..d025a67538ccdb66e42834d9540437fbb87caa14 100644 (file)
@@ -7,6 +7,7 @@ package binary
 import (
        "bytes"
        "io"
+       "math"
        "testing"
 )
 
@@ -121,10 +122,66 @@ func TestBufferTooSmall(t *testing.T) {
        }
 }
 
+// Ensure that we catch overflows of bytes going past MaxVarintLen64.
+// See issue https://golang.org/issues/41185
+func TestBufferTooBigWithOverflow(t *testing.T) {
+       tests := []struct {
+               in        []byte
+               name      string
+               wantN     int
+               wantValue uint64
+       }{
+               {
+                       name: "invalid: 1000 bytes",
+                       in: func() []byte {
+                               b := make([]byte, 1000)
+                               for i := range b {
+                                       b[i] = 0xff
+                               }
+                               b[999] = 0
+                               return b
+                       }(),
+                       wantN:     -11,
+                       wantValue: 0,
+               },
+               {
+                       name:      "valid: math.MaxUint64-40",
+                       in:        []byte{0xd7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01},
+                       wantValue: math.MaxUint64 - 40,
+                       wantN:     10,
+               },
+               {
+                       name:      "invalid: with more than MaxVarintLen64 bytes",
+                       in:        []byte{0xd7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01},
+                       wantN:     -11,
+                       wantValue: 0,
+               },
+               {
+                       name:      "invalid: 10th byte",
+                       in:        []byte{0xd7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f},
+                       wantN:     -10,
+                       wantValue: 0,
+               },
+       }
+
+       for _, tt := range tests {
+               tt := tt
+               t.Run(tt.name, func(t *testing.T) {
+                       value, n := Uvarint(tt.in)
+                       if g, w := n, tt.wantN; g != w {
+                               t.Errorf("bytes returned=%d, want=%d", g, w)
+                       }
+                       if g, w := value, tt.wantValue; g != w {
+                               t.Errorf("value=%d, want=%d", g, w)
+                       }
+               })
+       }
+}
+
 func testOverflow(t *testing.T, buf []byte, x0 uint64, n0 int, err0 error) {
        x, n := Uvarint(buf)
        if x != 0 || n != n0 {
-               t.Errorf("Uvarint(%v): got x = %d, n = %d; want 0, %d", buf, x, n, n0)
+               t.Errorf("Uvarint(% X): got x = %d, n = %d; want 0, %d", buf, x, n, n0)
        }
 
        r := bytes.NewReader(buf)
@@ -140,8 +197,8 @@ func testOverflow(t *testing.T, buf []byte, x0 uint64, n0 int, err0 error) {
 
 func TestOverflow(t *testing.T) {
        testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x2}, 0, -10, overflow)
-       testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x1, 0, 0}, 0, -13, overflow)
-       testOverflow(t, []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 1<<64-1, 0, overflow) // 11 bytes, should overflow
+       testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x1, 0, 0}, 0, -11, overflow)
+       testOverflow(t, []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 1<<64-1, -11, overflow) // 11 bytes, should overflow
 }
 
 func TestNonCanonicalZero(t *testing.T) {
index 8be21d5d2891d445f7e6afcddded8a098b2ad6ff..a03fa83d8ce3a7a7c2075369e95c0ea6e577b71d 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build gofuzz
 // +build gofuzz
 
 package csv
index c40aa506b0cbaa505e80ae0cd8b37d5947924ccd..f860f4f25f546fa181cff2ff36e5ebba0dfca2e1 100644 (file)
@@ -66,7 +66,7 @@ import (
 type ParseError struct {
        StartLine int   // Line where the record starts
        Line      int   // Line where the error occurred
-       Column    int   // Column (rune index) where the error occurred
+       Column    int   // Column (1-based byte index) where the error occurred
        Err       error // The actual error
 }
 
@@ -162,6 +162,10 @@ type Reader struct {
        // The i'th field ends at offset fieldIndexes[i] in recordBuffer.
        fieldIndexes []int
 
+       // fieldPositions is an index of field positions for the
+       // last record returned by Read.
+       fieldPositions []position
+
        // lastRecord is a record cache and only used when ReuseRecord == true.
        lastRecord []string
 }
@@ -192,6 +196,25 @@ func (r *Reader) Read() (record []string, err error) {
        return record, err
 }
 
+// FieldPos returns the line and column corresponding to
+// the start of the field with the given index in the slice most recently
+// returned by Read. Numbering of lines and columns starts at 1;
+// columns are counted in bytes, not runes.
+//
+// If this is called with an out-of-bounds index, it panics.
+func (r *Reader) FieldPos(field int) (line, column int) {
+       if field < 0 || field >= len(r.fieldPositions) {
+               panic("out of range index passed to FieldPos")
+       }
+       p := &r.fieldPositions[field]
+       return p.line, p.col
+}
+
+// pos holds the position of a field in the current line.
+type position struct {
+       line, col int
+}
+
 // ReadAll reads all the remaining records from r.
 // Each record is a slice of fields.
 // A successful call returns err == nil, not err == io.EOF. Because ReadAll is
@@ -260,7 +283,7 @@ func (r *Reader) readRecord(dst []string) ([]string, error) {
        }
 
        // Read line (automatically skipping past empty lines and any comments).
-       var line, fullLine []byte
+       var line []byte
        var errRead error
        for errRead == nil {
                line, errRead = r.readLine()
@@ -272,7 +295,6 @@ func (r *Reader) readRecord(dst []string) ([]string, error) {
                        line = nil
                        continue // Skip empty lines
                }
-               fullLine = line
                break
        }
        if errRead == io.EOF {
@@ -286,10 +308,20 @@ func (r *Reader) readRecord(dst []string) ([]string, error) {
        recLine := r.numLine // Starting line for record
        r.recordBuffer = r.recordBuffer[:0]
        r.fieldIndexes = r.fieldIndexes[:0]
+       r.fieldPositions = r.fieldPositions[:0]
+       pos := position{line: r.numLine, col: 1}
 parseField:
        for {
                if r.TrimLeadingSpace {
-                       line = bytes.TrimLeftFunc(line, unicode.IsSpace)
+                       i := bytes.IndexFunc(line, func(r rune) bool {
+                               return !unicode.IsSpace(r)
+                       })
+                       if i < 0 {
+                               i = len(line)
+                               pos.col -= lengthNL(line)
+                       }
+                       line = line[i:]
+                       pos.col += i
                }
                if len(line) == 0 || line[0] != '"' {
                        // Non-quoted string field
@@ -303,48 +335,56 @@ parseField:
                        // Check to make sure a quote does not appear in field.
                        if !r.LazyQuotes {
                                if j := bytes.IndexByte(field, '"'); j >= 0 {
-                                       col := utf8.RuneCount(fullLine[:len(fullLine)-len(line[j:])])
+                                       col := pos.col + j
                                        err = &ParseError{StartLine: recLine, Line: r.numLine, Column: col, Err: ErrBareQuote}
                                        break parseField
                                }
                        }
                        r.recordBuffer = append(r.recordBuffer, field...)
                        r.fieldIndexes = append(r.fieldIndexes, len(r.recordBuffer))
+                       r.fieldPositions = append(r.fieldPositions, pos)
                        if i >= 0 {
                                line = line[i+commaLen:]
+                               pos.col += i + commaLen
                                continue parseField
                        }
                        break parseField
                } else {
                        // Quoted string field
+                       fieldPos := pos
                        line = line[quoteLen:]
+                       pos.col += quoteLen
                        for {
                                i := bytes.IndexByte(line, '"')
                                if i >= 0 {
                                        // Hit next quote.
                                        r.recordBuffer = append(r.recordBuffer, line[:i]...)
                                        line = line[i+quoteLen:]
+                                       pos.col += i + quoteLen
                                        switch rn := nextRune(line); {
                                        case rn == '"':
                                                // `""` sequence (append quote).
                                                r.recordBuffer = append(r.recordBuffer, '"')
                                                line = line[quoteLen:]
+                                               pos.col += quoteLen
                                        case rn == r.Comma:
                                                // `",` sequence (end of field).
                                                line = line[commaLen:]
+                                               pos.col += commaLen
                                                r.fieldIndexes = append(r.fieldIndexes, len(r.recordBuffer))
+                                               r.fieldPositions = append(r.fieldPositions, fieldPos)
                                                continue parseField
                                        case lengthNL(line) == len(line):
                                                // `"\n` sequence (end of line).
                                                r.fieldIndexes = append(r.fieldIndexes, len(r.recordBuffer))
+                                               r.fieldPositions = append(r.fieldPositions, fieldPos)
                                                break parseField
                                        case r.LazyQuotes:
                                                // `"` sequence (bare quote).
                                                r.recordBuffer = append(r.recordBuffer, '"')
                                        default:
                                                // `"*` sequence (invalid non-escaped quote).
-                                               col := utf8.RuneCount(fullLine[:len(fullLine)-len(line)-quoteLen])
-                                               err = &ParseError{StartLine: recLine, Line: r.numLine, Column: col, Err: ErrQuote}
+                                               err = &ParseError{StartLine: recLine, Line: r.numLine, Column: pos.col - quoteLen, Err: ErrQuote}
                                                break parseField
                                        }
                                } else if len(line) > 0 {
@@ -353,19 +393,23 @@ parseField:
                                        if errRead != nil {
                                                break parseField
                                        }
+                                       pos.col += len(line)
                                        line, errRead = r.readLine()
+                                       if len(line) > 0 {
+                                               pos.line++
+                                               pos.col = 1
+                                       }
                                        if errRead == io.EOF {
                                                errRead = nil
                                        }
-                                       fullLine = line
                                } else {
                                        // Abrupt end of file (EOF or error).
                                        if !r.LazyQuotes && errRead == nil {
-                                               col := utf8.RuneCount(fullLine)
-                                               err = &ParseError{StartLine: recLine, Line: r.numLine, Column: col, Err: ErrQuote}
+                                               err = &ParseError{StartLine: recLine, Line: pos.line, Column: pos.col, Err: ErrQuote}
                                                break parseField
                                        }
                                        r.fieldIndexes = append(r.fieldIndexes, len(r.recordBuffer))
+                                       r.fieldPositions = append(r.fieldPositions, fieldPos)
                                        break parseField
                                }
                        }
@@ -392,7 +436,12 @@ parseField:
        // Check or update the expected fields per record.
        if r.FieldsPerRecord > 0 {
                if len(dst) != r.FieldsPerRecord && err == nil {
-                       err = &ParseError{StartLine: recLine, Line: recLine, Err: ErrFieldCount}
+                       err = &ParseError{
+                               StartLine: recLine,
+                               Line:      recLine,
+                               Column:    1,
+                               Err:       ErrFieldCount,
+                       }
                }
        } else if r.FieldsPerRecord == 0 {
                r.FieldsPerRecord = len(dst)
index 5121791cb36005736417730b981a386d38494e86..abe3fdfb394e226cc2daee4569dc9d386d26b17c 100644 (file)
@@ -5,6 +5,8 @@
 package csv
 
 import (
+       "errors"
+       "fmt"
        "io"
        "reflect"
        "strings"
@@ -12,405 +14,544 @@ import (
        "unicode/utf8"
 )
 
-func TestRead(t *testing.T) {
-       tests := []struct {
-               Name   string
-               Input  string
-               Output [][]string
-               Error  error
+type readTest struct {
+       Name      string
+       Input     string
+       Output    [][]string
+       Positions [][][2]int
+       Errors    []error
+
+       // These fields are copied into the Reader
+       Comma              rune
+       Comment            rune
+       UseFieldsPerRecord bool // false (default) means FieldsPerRecord is -1
+       FieldsPerRecord    int
+       LazyQuotes         bool
+       TrimLeadingSpace   bool
+       ReuseRecord        bool
+}
 
-               // These fields are copied into the Reader
-               Comma              rune
-               Comment            rune
-               UseFieldsPerRecord bool // false (default) means FieldsPerRecord is -1
-               FieldsPerRecord    int
-               LazyQuotes         bool
-               TrimLeadingSpace   bool
-               ReuseRecord        bool
-       }{{
-               Name:   "Simple",
-               Input:  "a,b,c\n",
-               Output: [][]string{{"a", "b", "c"}},
-       }, {
-               Name:   "CRLF",
-               Input:  "a,b\r\nc,d\r\n",
-               Output: [][]string{{"a", "b"}, {"c", "d"}},
-       }, {
-               Name:   "BareCR",
-               Input:  "a,b\rc,d\r\n",
-               Output: [][]string{{"a", "b\rc", "d"}},
-       }, {
-               Name: "RFC4180test",
-               Input: `#field1,field2,field3
-"aaa","bb
-b","ccc"
-"a,a","b""bb","ccc"
-zzz,yyy,xxx
+// In these tests, the §, ¶ and ∑ characters in readTest.Input are used to denote
+// the start of a field, a record boundary and the position of an error respectively.
+// They are removed before parsing and are used to verify the position
+// information reported by FieldPos.
+
+var readTests = []readTest{{
+       Name:   "Simple",
+       Input:  "§a,§b,§c\n",
+       Output: [][]string{{"a", "b", "c"}},
+}, {
+       Name:   "CRLF",
+       Input:  "§a,§b\r\n¶§c,§d\r\n",
+       Output: [][]string{{"a", "b"}, {"c", "d"}},
+}, {
+       Name:   "BareCR",
+       Input:  "§a,§b\rc,§d\r\n",
+       Output: [][]string{{"a", "b\rc", "d"}},
+}, {
+       Name: "RFC4180test",
+       Input: `§#field1,§field2,§field3
+¶§"aaa",§"bb
+b",§"ccc"
+¶§"a,a",§"b""bb",§"ccc"
+¶§zzz,§yyy,§xxx
 `,
-               Output: [][]string{
-                       {"#field1", "field2", "field3"},
-                       {"aaa", "bb\nb", "ccc"},
-                       {"a,a", `b"bb`, "ccc"},
-                       {"zzz", "yyy", "xxx"},
-               },
-               UseFieldsPerRecord: true,
-               FieldsPerRecord:    0,
-       }, {
-               Name:   "NoEOLTest",
-               Input:  "a,b,c",
-               Output: [][]string{{"a", "b", "c"}},
-       }, {
-               Name:   "Semicolon",
-               Input:  "a;b;c\n",
-               Output: [][]string{{"a", "b", "c"}},
-               Comma:  ';',
-       }, {
-               Name: "MultiLine",
-               Input: `"two
-line","one line","three
+       Output: [][]string{
+               {"#field1", "field2", "field3"},
+               {"aaa", "bb\nb", "ccc"},
+               {"a,a", `b"bb`, "ccc"},
+               {"zzz", "yyy", "xxx"},
+       },
+       UseFieldsPerRecord: true,
+       FieldsPerRecord:    0,
+}, {
+       Name:   "NoEOLTest",
+       Input:  "§a,§b,§c",
+       Output: [][]string{{"a", "b", "c"}},
+}, {
+       Name:   "Semicolon",
+       Input:  "§a;§b;§c\n",
+       Output: [][]string{{"a", "b", "c"}},
+       Comma:  ';',
+}, {
+       Name: "MultiLine",
+       Input: `§"two
+line",§"one line",§"three
 line
 field"`,
-               Output: [][]string{{"two\nline", "one line", "three\nline\nfield"}},
-       }, {
-               Name:  "BlankLine",
-               Input: "a,b,c\n\nd,e,f\n\n",
-               Output: [][]string{
-                       {"a", "b", "c"},
-                       {"d", "e", "f"},
-               },
-       }, {
-               Name:  "BlankLineFieldCount",
-               Input: "a,b,c\n\nd,e,f\n\n",
-               Output: [][]string{
-                       {"a", "b", "c"},
-                       {"d", "e", "f"},
-               },
-               UseFieldsPerRecord: true,
-               FieldsPerRecord:    0,
-       }, {
-               Name:             "TrimSpace",
-               Input:            " a,  b,   c\n",
-               Output:           [][]string{{"a", "b", "c"}},
-               TrimLeadingSpace: true,
-       }, {
-               Name:   "LeadingSpace",
-               Input:  " a,  b,   c\n",
-               Output: [][]string{{" a", "  b", "   c"}},
-       }, {
-               Name:    "Comment",
-               Input:   "#1,2,3\na,b,c\n#comment",
-               Output:  [][]string{{"a", "b", "c"}},
-               Comment: '#',
-       }, {
-               Name:   "NoComment",
-               Input:  "#1,2,3\na,b,c",
-               Output: [][]string{{"#1", "2", "3"}, {"a", "b", "c"}},
-       }, {
-               Name:       "LazyQuotes",
-               Input:      `a "word","1"2",a","b`,
-               Output:     [][]string{{`a "word"`, `1"2`, `a"`, `b`}},
-               LazyQuotes: true,
-       }, {
-               Name:       "BareQuotes",
-               Input:      `a "word","1"2",a"`,
-               Output:     [][]string{{`a "word"`, `1"2`, `a"`}},
-               LazyQuotes: true,
-       }, {
-               Name:       "BareDoubleQuotes",
-               Input:      `a""b,c`,
-               Output:     [][]string{{`a""b`, `c`}},
-               LazyQuotes: true,
-       }, {
-               Name:  "BadDoubleQuotes",
-               Input: `a""b,c`,
-               Error: &ParseError{StartLine: 1, Line: 1, Column: 1, Err: ErrBareQuote},
-       }, {
-               Name:             "TrimQuote",
-               Input:            ` "a"," b",c`,
-               Output:           [][]string{{"a", " b", "c"}},
-               TrimLeadingSpace: true,
-       }, {
-               Name:  "BadBareQuote",
-               Input: `a "word","b"`,
-               Error: &ParseError{StartLine: 1, Line: 1, Column: 2, Err: ErrBareQuote},
-       }, {
-               Name:  "BadTrailingQuote",
-               Input: `"a word",b"`,
-               Error: &ParseError{StartLine: 1, Line: 1, Column: 10, Err: ErrBareQuote},
-       }, {
-               Name:  "ExtraneousQuote",
-               Input: `"a "word","b"`,
-               Error: &ParseError{StartLine: 1, Line: 1, Column: 3, Err: ErrQuote},
-       }, {
-               Name:               "BadFieldCount",
-               Input:              "a,b,c\nd,e",
-               Error:              &ParseError{StartLine: 2, Line: 2, Err: ErrFieldCount},
-               UseFieldsPerRecord: true,
-               FieldsPerRecord:    0,
-       }, {
-               Name:               "BadFieldCount1",
-               Input:              `a,b,c`,
-               Error:              &ParseError{StartLine: 1, Line: 1, Err: ErrFieldCount},
-               UseFieldsPerRecord: true,
-               FieldsPerRecord:    2,
-       }, {
-               Name:   "FieldCount",
-               Input:  "a,b,c\nd,e",
-               Output: [][]string{{"a", "b", "c"}, {"d", "e"}},
-       }, {
-               Name:   "TrailingCommaEOF",
-               Input:  "a,b,c,",
-               Output: [][]string{{"a", "b", "c", ""}},
-       }, {
-               Name:   "TrailingCommaEOL",
-               Input:  "a,b,c,\n",
-               Output: [][]string{{"a", "b", "c", ""}},
-       }, {
-               Name:             "TrailingCommaSpaceEOF",
-               Input:            "a,b,c, ",
-               Output:           [][]string{{"a", "b", "c", ""}},
-               TrimLeadingSpace: true,
-       }, {
-               Name:             "TrailingCommaSpaceEOL",
-               Input:            "a,b,c, \n",
-               Output:           [][]string{{"a", "b", "c", ""}},
-               TrimLeadingSpace: true,
-       }, {
-               Name:             "TrailingCommaLine3",
-               Input:            "a,b,c\nd,e,f\ng,hi,",
-               Output:           [][]string{{"a", "b", "c"}, {"d", "e", "f"}, {"g", "hi", ""}},
-               TrimLeadingSpace: true,
-       }, {
-               Name:   "NotTrailingComma3",
-               Input:  "a,b,c, \n",
-               Output: [][]string{{"a", "b", "c", " "}},
-       }, {
-               Name: "CommaFieldTest",
-               Input: `x,y,z,w
-x,y,z,
-x,y,,
-x,,,
-,,,
-"x","y","z","w"
-"x","y","z",""
-"x","y","",""
-"x","","",""
-"","","",""
+       Output: [][]string{{"two\nline", "one line", "three\nline\nfield"}},
+}, {
+       Name:  "BlankLine",
+       Input: "§a,§b,§c\n\n¶§d,§e,§f\n\n",
+       Output: [][]string{
+               {"a", "b", "c"},
+               {"d", "e", "f"},
+       },
+}, {
+       Name:  "BlankLineFieldCount",
+       Input: "§a,§b,§c\n\n¶§d,§e,§f\n\n",
+       Output: [][]string{
+               {"a", "b", "c"},
+               {"d", "e", "f"},
+       },
+       UseFieldsPerRecord: true,
+       FieldsPerRecord:    0,
+}, {
+       Name:             "TrimSpace",
+       Input:            " §a,  §b,   §c\n",
+       Output:           [][]string{{"a", "b", "c"}},
+       TrimLeadingSpace: true,
+}, {
+       Name:   "LeadingSpace",
+       Input:  "§ a,§  b,§   c\n",
+       Output: [][]string{{" a", "  b", "   c"}},
+}, {
+       Name:    "Comment",
+       Input:   "#1,2,3\n§a,§b,§c\n#comment",
+       Output:  [][]string{{"a", "b", "c"}},
+       Comment: '#',
+}, {
+       Name:   "NoComment",
+       Input:  "§#1,§2,§3\n¶§a,§b,§c",
+       Output: [][]string{{"#1", "2", "3"}, {"a", "b", "c"}},
+}, {
+       Name:       "LazyQuotes",
+       Input:      `§a "word",§"1"2",§a",§"b`,
+       Output:     [][]string{{`a "word"`, `1"2`, `a"`, `b`}},
+       LazyQuotes: true,
+}, {
+       Name:       "BareQuotes",
+       Input:      `§a "word",§"1"2",§a"`,
+       Output:     [][]string{{`a "word"`, `1"2`, `a"`}},
+       LazyQuotes: true,
+}, {
+       Name:       "BareDoubleQuotes",
+       Input:      `§a""b,§c`,
+       Output:     [][]string{{`a""b`, `c`}},
+       LazyQuotes: true,
+}, {
+       Name:   "BadDoubleQuotes",
+       Input:  `§a∑""b,c`,
+       Errors: []error{&ParseError{Err: ErrBareQuote}},
+}, {
+       Name:             "TrimQuote",
+       Input:            ` §"a",§" b",§c`,
+       Output:           [][]string{{"a", " b", "c"}},
+       TrimLeadingSpace: true,
+}, {
+       Name:   "BadBareQuote",
+       Input:  `§a ∑"word","b"`,
+       Errors: []error{&ParseError{Err: ErrBareQuote}},
+}, {
+       Name:   "BadTrailingQuote",
+       Input:  `§"a word",b∑"`,
+       Errors: []error{&ParseError{Err: ErrBareQuote}},
+}, {
+       Name:   "ExtraneousQuote",
+       Input:  `§"a ∑"word","b"`,
+       Errors: []error{&ParseError{Err: ErrQuote}},
+}, {
+       Name:               "BadFieldCount",
+       Input:              "§a,§b,§c\n¶∑§d,§e",
+       Errors:             []error{nil, &ParseError{Err: ErrFieldCount}},
+       Output:             [][]string{{"a", "b", "c"}, {"d", "e"}},
+       UseFieldsPerRecord: true,
+       FieldsPerRecord:    0,
+}, {
+       Name:               "BadFieldCountMultiple",
+       Input:              "§a,§b,§c\n¶∑§d,§e\n¶∑§f",
+       Errors:             []error{nil, &ParseError{Err: ErrFieldCount}, &ParseError{Err: ErrFieldCount}},
+       Output:             [][]string{{"a", "b", "c"}, {"d", "e"}, {"f"}},
+       UseFieldsPerRecord: true,
+       FieldsPerRecord:    0,
+}, {
+       Name:               "BadFieldCount1",
+       Input:              `§∑a,§b,§c`,
+       Errors:             []error{&ParseError{Err: ErrFieldCount}},
+       Output:             [][]string{{"a", "b", "c"}},
+       UseFieldsPerRecord: true,
+       FieldsPerRecord:    2,
+}, {
+       Name:   "FieldCount",
+       Input:  "§a,§b,§c\n¶§d,§e",
+       Output: [][]string{{"a", "b", "c"}, {"d", "e"}},
+}, {
+       Name:   "TrailingCommaEOF",
+       Input:  "§a,§b,§c,§",
+       Output: [][]string{{"a", "b", "c", ""}},
+}, {
+       Name:   "TrailingCommaEOL",
+       Input:  "§a,§b,§c,§\n",
+       Output: [][]string{{"a", "b", "c", ""}},
+}, {
+       Name:             "TrailingCommaSpaceEOF",
+       Input:            "§a,§b,§c, §",
+       Output:           [][]string{{"a", "b", "c", ""}},
+       TrimLeadingSpace: true,
+}, {
+       Name:             "TrailingCommaSpaceEOL",
+       Input:            "§a,§b,§c, §\n",
+       Output:           [][]string{{"a", "b", "c", ""}},
+       TrimLeadingSpace: true,
+}, {
+       Name:             "TrailingCommaLine3",
+       Input:            "§a,§b,§c\n¶§d,§e,§f\n¶§g,§hi,§",
+       Output:           [][]string{{"a", "b", "c"}, {"d", "e", "f"}, {"g", "hi", ""}},
+       TrimLeadingSpace: true,
+}, {
+       Name:   "NotTrailingComma3",
+       Input:  "§a,§b,§c,§ \n",
+       Output: [][]string{{"a", "b", "c", " "}},
+}, {
+       Name: "CommaFieldTest",
+       Input: `§x,§y,§z,§w
+¶§x,§y,§z,§
+¶§x,§y,§,§
+¶§x,§,§,§
+¶§,§,§,§
+¶§"x",§"y",§"z",§"w"
+¶§"x",§"y",§"z",§""
+¶§"x",§"y",§"",§""
+¶§"x",§"",§"",§""
+¶§"",§"",§"",§""
 `,
-               Output: [][]string{
-                       {"x", "y", "z", "w"},
-                       {"x", "y", "z", ""},
-                       {"x", "y", "", ""},
-                       {"x", "", "", ""},
-                       {"", "", "", ""},
-                       {"x", "y", "z", "w"},
-                       {"x", "y", "z", ""},
-                       {"x", "y", "", ""},
-                       {"x", "", "", ""},
-                       {"", "", "", ""},
-               },
-       }, {
-               Name:  "TrailingCommaIneffective1",
-               Input: "a,b,\nc,d,e",
-               Output: [][]string{
-                       {"a", "b", ""},
-                       {"c", "d", "e"},
-               },
-               TrimLeadingSpace: true,
-       }, {
-               Name:  "ReadAllReuseRecord",
-               Input: "a,b\nc,d",
-               Output: [][]string{
-                       {"a", "b"},
-                       {"c", "d"},
-               },
-               ReuseRecord: true,
-       }, {
-               Name:  "StartLine1", // Issue 19019
-               Input: "a,\"b\nc\"d,e",
-               Error: &ParseError{StartLine: 1, Line: 2, Column: 1, Err: ErrQuote},
-       }, {
-               Name:  "StartLine2",
-               Input: "a,b\n\"d\n\n,e",
-               Error: &ParseError{StartLine: 2, Line: 5, Column: 0, Err: ErrQuote},
-       }, {
-               Name:  "CRLFInQuotedField", // Issue 21201
-               Input: "A,\"Hello\r\nHi\",B\r\n",
-               Output: [][]string{
-                       {"A", "Hello\nHi", "B"},
-               },
-       }, {
-               Name:   "BinaryBlobField", // Issue 19410
-               Input:  "x09\x41\xb4\x1c,aktau",
-               Output: [][]string{{"x09A\xb4\x1c", "aktau"}},
-       }, {
-               Name:   "TrailingCR",
-               Input:  "field1,field2\r",
-               Output: [][]string{{"field1", "field2"}},
-       }, {
-               Name:   "QuotedTrailingCR",
-               Input:  "\"field\"\r",
-               Output: [][]string{{"field"}},
-       }, {
-               Name:  "QuotedTrailingCRCR",
-               Input: "\"field\"\r\r",
-               Error: &ParseError{StartLine: 1, Line: 1, Column: 6, Err: ErrQuote},
-       }, {
-               Name:   "FieldCR",
-               Input:  "field\rfield\r",
-               Output: [][]string{{"field\rfield"}},
-       }, {
-               Name:   "FieldCRCR",
-               Input:  "field\r\rfield\r\r",
-               Output: [][]string{{"field\r\rfield\r"}},
-       }, {
-               Name:   "FieldCRCRLF",
-               Input:  "field\r\r\nfield\r\r\n",
-               Output: [][]string{{"field\r"}, {"field\r"}},
-       }, {
-               Name:   "FieldCRCRLFCR",
-               Input:  "field\r\r\n\rfield\r\r\n\r",
-               Output: [][]string{{"field\r"}, {"\rfield\r"}},
-       }, {
-               Name:   "FieldCRCRLFCRCR",
-               Input:  "field\r\r\n\r\rfield\r\r\n\r\r",
-               Output: [][]string{{"field\r"}, {"\r\rfield\r"}, {"\r"}},
-       }, {
-               Name:  "MultiFieldCRCRLFCRCR",
-               Input: "field1,field2\r\r\n\r\rfield1,field2\r\r\n\r\r,",
-               Output: [][]string{
-                       {"field1", "field2\r"},
-                       {"\r\rfield1", "field2\r"},
-                       {"\r\r", ""},
-               },
-       }, {
-               Name:             "NonASCIICommaAndComment",
-               Input:            "a£b,c£ \td,e\n€ comment\n",
-               Output:           [][]string{{"a", "b,c", "d,e"}},
-               TrimLeadingSpace: true,
-               Comma:            '£',
-               Comment:          '€',
-       }, {
-               Name:    "NonASCIICommaAndCommentWithQuotes",
-               Input:   "a€\"  b,\"€ c\nλ comment\n",
-               Output:  [][]string{{"a", "  b,", " c"}},
-               Comma:   '€',
-               Comment: 'λ',
-       }, {
-               // λ and θ start with the same byte.
-               // This tests that the parser doesn't confuse such characters.
-               Name:    "NonASCIICommaConfusion",
-               Input:   "\"abθcd\"λefθgh",
-               Output:  [][]string{{"abθcd", "efθgh"}},
-               Comma:   'λ',
-               Comment: '€',
-       }, {
-               Name:    "NonASCIICommentConfusion",
-               Input:   "λ\nλ\nθ\nλ\n",
-               Output:  [][]string{{"λ"}, {"λ"}, {"λ"}},
-               Comment: 'θ',
-       }, {
-               Name:   "QuotedFieldMultipleLF",
-               Input:  "\"\n\n\n\n\"",
-               Output: [][]string{{"\n\n\n\n"}},
-       }, {
-               Name:  "MultipleCRLF",
-               Input: "\r\n\r\n\r\n\r\n",
-       }, {
-               // The implementation may read each line in several chunks if it doesn't fit entirely
-               // in the read buffer, so we should test the code to handle that condition.
-               Name:    "HugeLines",
-               Input:   strings.Repeat("#ignore\n", 10000) + strings.Repeat("@", 5000) + "," + strings.Repeat("*", 5000),
-               Output:  [][]string{{strings.Repeat("@", 5000), strings.Repeat("*", 5000)}},
-               Comment: '#',
-       }, {
-               Name:  "QuoteWithTrailingCRLF",
-               Input: "\"foo\"bar\"\r\n",
-               Error: &ParseError{StartLine: 1, Line: 1, Column: 4, Err: ErrQuote},
-       }, {
-               Name:       "LazyQuoteWithTrailingCRLF",
-               Input:      "\"foo\"bar\"\r\n",
-               Output:     [][]string{{`foo"bar`}},
-               LazyQuotes: true,
-       }, {
-               Name:   "DoubleQuoteWithTrailingCRLF",
-               Input:  "\"foo\"\"bar\"\r\n",
-               Output: [][]string{{`foo"bar`}},
-       }, {
-               Name:   "EvenQuotes",
-               Input:  `""""""""`,
-               Output: [][]string{{`"""`}},
-       }, {
-               Name:  "OddQuotes",
-               Input: `"""""""`,
-               Error: &ParseError{StartLine: 1, Line: 1, Column: 7, Err: ErrQuote},
-       }, {
-               Name:       "LazyOddQuotes",
-               Input:      `"""""""`,
-               Output:     [][]string{{`"""`}},
-               LazyQuotes: true,
-       }, {
-               Name:  "BadComma1",
-               Comma: '\n',
-               Error: errInvalidDelim,
-       }, {
-               Name:  "BadComma2",
-               Comma: '\r',
-               Error: errInvalidDelim,
-       }, {
-               Name:  "BadComma3",
-               Comma: '"',
-               Error: errInvalidDelim,
-       }, {
-               Name:  "BadComma4",
-               Comma: utf8.RuneError,
-               Error: errInvalidDelim,
-       }, {
-               Name:    "BadComment1",
-               Comment: '\n',
-               Error:   errInvalidDelim,
-       }, {
-               Name:    "BadComment2",
-               Comment: '\r',
-               Error:   errInvalidDelim,
-       }, {
-               Name:    "BadComment3",
-               Comment: utf8.RuneError,
-               Error:   errInvalidDelim,
-       }, {
-               Name:    "BadCommaComment",
-               Comma:   'X',
-               Comment: 'X',
-               Error:   errInvalidDelim,
-       }}
+       Output: [][]string{
+               {"x", "y", "z", "w"},
+               {"x", "y", "z", ""},
+               {"x", "y", "", ""},
+               {"x", "", "", ""},
+               {"", "", "", ""},
+               {"x", "y", "z", "w"},
+               {"x", "y", "z", ""},
+               {"x", "y", "", ""},
+               {"x", "", "", ""},
+               {"", "", "", ""},
+       },
+}, {
+       Name:  "TrailingCommaIneffective1",
+       Input: "§a,§b,§\n¶§c,§d,§e",
+       Output: [][]string{
+               {"a", "b", ""},
+               {"c", "d", "e"},
+       },
+       TrimLeadingSpace: true,
+}, {
+       Name:  "ReadAllReuseRecord",
+       Input: "§a,§b\n¶§c,§d",
+       Output: [][]string{
+               {"a", "b"},
+               {"c", "d"},
+       },
+       ReuseRecord: true,
+}, {
+       Name:   "StartLine1", // Issue 19019
+       Input:  "§a,\"b\nc∑\"d,e",
+       Errors: []error{&ParseError{Err: ErrQuote}},
+}, {
+       Name:   "StartLine2",
+       Input:  "§a,§b\n¶§\"d\n\n,e∑",
+       Errors: []error{nil, &ParseError{Err: ErrQuote}},
+       Output: [][]string{{"a", "b"}},
+}, {
+       Name:  "CRLFInQuotedField", // Issue 21201
+       Input: "§A,§\"Hello\r\nHi\",§B\r\n",
+       Output: [][]string{
+               {"A", "Hello\nHi", "B"},
+       },
+}, {
+       Name:   "BinaryBlobField", // Issue 19410
+       Input:  "§x09\x41\xb4\x1c,§aktau",
+       Output: [][]string{{"x09A\xb4\x1c", "aktau"}},
+}, {
+       Name:   "TrailingCR",
+       Input:  "§field1,§field2\r",
+       Output: [][]string{{"field1", "field2"}},
+}, {
+       Name:   "QuotedTrailingCR",
+       Input:  "§\"field\"\r",
+       Output: [][]string{{"field"}},
+}, {
+       Name:   "QuotedTrailingCRCR",
+       Input:  "§\"field∑\"\r\r",
+       Errors: []error{&ParseError{Err: ErrQuote}},
+}, {
+       Name:   "FieldCR",
+       Input:  "§field\rfield\r",
+       Output: [][]string{{"field\rfield"}},
+}, {
+       Name:   "FieldCRCR",
+       Input:  "§field\r\rfield\r\r",
+       Output: [][]string{{"field\r\rfield\r"}},
+}, {
+       Name:   "FieldCRCRLF",
+       Input:  "§field\r\r\n¶§field\r\r\n",
+       Output: [][]string{{"field\r"}, {"field\r"}},
+}, {
+       Name:   "FieldCRCRLFCR",
+       Input:  "§field\r\r\n¶§\rfield\r\r\n\r",
+       Output: [][]string{{"field\r"}, {"\rfield\r"}},
+}, {
+       Name:   "FieldCRCRLFCRCR",
+       Input:  "§field\r\r\n¶§\r\rfield\r\r\n¶§\r\r",
+       Output: [][]string{{"field\r"}, {"\r\rfield\r"}, {"\r"}},
+}, {
+       Name:  "MultiFieldCRCRLFCRCR",
+       Input: "§field1,§field2\r\r\n¶§\r\rfield1,§field2\r\r\n¶§\r\r,§",
+       Output: [][]string{
+               {"field1", "field2\r"},
+               {"\r\rfield1", "field2\r"},
+               {"\r\r", ""},
+       },
+}, {
+       Name:             "NonASCIICommaAndComment",
+       Input:            "§a£§b,c£ \t§d,e\n€ comment\n",
+       Output:           [][]string{{"a", "b,c", "d,e"}},
+       TrimLeadingSpace: true,
+       Comma:            '£',
+       Comment:          '€',
+}, {
+       Name:    "NonASCIICommaAndCommentWithQuotes",
+       Input:   "§a€§\"  b,\"€§ c\nλ comment\n",
+       Output:  [][]string{{"a", "  b,", " c"}},
+       Comma:   '€',
+       Comment: 'λ',
+}, {
+       // λ and θ start with the same byte.
+       // This tests that the parser doesn't confuse such characters.
+       Name:    "NonASCIICommaConfusion",
+       Input:   "§\"abθcd\"λ§efθgh",
+       Output:  [][]string{{"abθcd", "efθgh"}},
+       Comma:   'λ',
+       Comment: '€',
+}, {
+       Name:    "NonASCIICommentConfusion",
+       Input:   "§λ\n¶§λ\nθ\n¶§λ\n",
+       Output:  [][]string{{"λ"}, {"λ"}, {"λ"}},
+       Comment: 'θ',
+}, {
+       Name:   "QuotedFieldMultipleLF",
+       Input:  "§\"\n\n\n\n\"",
+       Output: [][]string{{"\n\n\n\n"}},
+}, {
+       Name:  "MultipleCRLF",
+       Input: "\r\n\r\n\r\n\r\n",
+}, {
+       // The implementation may read each line in several chunks if it doesn't fit entirely
+       // in the read buffer, so we should test the code to handle that condition.
+       Name:    "HugeLines",
+       Input:   strings.Repeat("#ignore\n", 10000) + "§" + strings.Repeat("@", 5000) + ",§" + strings.Repeat("*", 5000),
+       Output:  [][]string{{strings.Repeat("@", 5000), strings.Repeat("*", 5000)}},
+       Comment: '#',
+}, {
+       Name:   "QuoteWithTrailingCRLF",
+       Input:  "§\"foo∑\"bar\"\r\n",
+       Errors: []error{&ParseError{Err: ErrQuote}},
+}, {
+       Name:       "LazyQuoteWithTrailingCRLF",
+       Input:      "§\"foo\"bar\"\r\n",
+       Output:     [][]string{{`foo"bar`}},
+       LazyQuotes: true,
+}, {
+       Name:   "DoubleQuoteWithTrailingCRLF",
+       Input:  "§\"foo\"\"bar\"\r\n",
+       Output: [][]string{{`foo"bar`}},
+}, {
+       Name:   "EvenQuotes",
+       Input:  `§""""""""`,
+       Output: [][]string{{`"""`}},
+}, {
+       Name:   "OddQuotes",
+       Input:  `§"""""""∑`,
+       Errors: []error{&ParseError{Err: ErrQuote}},
+}, {
+       Name:       "LazyOddQuotes",
+       Input:      `§"""""""`,
+       Output:     [][]string{{`"""`}},
+       LazyQuotes: true,
+}, {
+       Name:   "BadComma1",
+       Comma:  '\n',
+       Errors: []error{errInvalidDelim},
+}, {
+       Name:   "BadComma2",
+       Comma:  '\r',
+       Errors: []error{errInvalidDelim},
+}, {
+       Name:   "BadComma3",
+       Comma:  '"',
+       Errors: []error{errInvalidDelim},
+}, {
+       Name:   "BadComma4",
+       Comma:  utf8.RuneError,
+       Errors: []error{errInvalidDelim},
+}, {
+       Name:    "BadComment1",
+       Comment: '\n',
+       Errors:  []error{errInvalidDelim},
+}, {
+       Name:    "BadComment2",
+       Comment: '\r',
+       Errors:  []error{errInvalidDelim},
+}, {
+       Name:    "BadComment3",
+       Comment: utf8.RuneError,
+       Errors:  []error{errInvalidDelim},
+}, {
+       Name:    "BadCommaComment",
+       Comma:   'X',
+       Comment: 'X',
+       Errors:  []error{errInvalidDelim},
+}}
 
-       for _, tt := range tests {
-               t.Run(tt.Name, func(t *testing.T) {
-                       r := NewReader(strings.NewReader(tt.Input))
+func TestRead(t *testing.T) {
+       newReader := func(tt readTest) (*Reader, [][][2]int, map[int][2]int) {
+               positions, errPositions, input := makePositions(tt.Input)
+               r := NewReader(strings.NewReader(input))
 
-                       if tt.Comma != 0 {
-                               r.Comma = tt.Comma
-                       }
-                       r.Comment = tt.Comment
-                       if tt.UseFieldsPerRecord {
-                               r.FieldsPerRecord = tt.FieldsPerRecord
+               if tt.Comma != 0 {
+                       r.Comma = tt.Comma
+               }
+               r.Comment = tt.Comment
+               if tt.UseFieldsPerRecord {
+                       r.FieldsPerRecord = tt.FieldsPerRecord
+               } else {
+                       r.FieldsPerRecord = -1
+               }
+               r.LazyQuotes = tt.LazyQuotes
+               r.TrimLeadingSpace = tt.TrimLeadingSpace
+               r.ReuseRecord = tt.ReuseRecord
+               return r, positions, errPositions
+       }
+
+       for _, tt := range readTests {
+               t.Run(tt.Name, func(t *testing.T) {
+                       r, positions, errPositions := newReader(tt)
+                       out, err := r.ReadAll()
+                       if wantErr := firstError(tt.Errors, positions, errPositions); wantErr != nil {
+                               if !reflect.DeepEqual(err, wantErr) {
+                                       t.Fatalf("ReadAll() error mismatch:\ngot  %v (%#v)\nwant %v (%#v)", err, err, wantErr, wantErr)
+                               }
+                               if out != nil {
+                                       t.Fatalf("ReadAll() output:\ngot  %q\nwant nil", out)
+                               }
                        } else {
-                               r.FieldsPerRecord = -1
+                               if err != nil {
+                                       t.Fatalf("unexpected Readall() error: %v", err)
+                               }
+                               if !reflect.DeepEqual(out, tt.Output) {
+                                       t.Fatalf("ReadAll() output:\ngot  %q\nwant %q", out, tt.Output)
+                               }
                        }
-                       r.LazyQuotes = tt.LazyQuotes
-                       r.TrimLeadingSpace = tt.TrimLeadingSpace
-                       r.ReuseRecord = tt.ReuseRecord
 
-                       out, err := r.ReadAll()
-                       if !reflect.DeepEqual(err, tt.Error) {
-                               t.Errorf("ReadAll() error:\ngot  %v\nwant %v", err, tt.Error)
-                       } else if !reflect.DeepEqual(out, tt.Output) {
-                               t.Errorf("ReadAll() output:\ngot  %q\nwant %q", out, tt.Output)
+                       // Check field and error positions.
+                       r, _, _ = newReader(tt)
+                       for recNum := 0; ; recNum++ {
+                               rec, err := r.Read()
+                               var wantErr error
+                               if recNum < len(tt.Errors) && tt.Errors[recNum] != nil {
+                                       wantErr = errorWithPosition(tt.Errors[recNum], recNum, positions, errPositions)
+                               } else if recNum >= len(tt.Output) {
+                                       wantErr = io.EOF
+                               }
+                               if !reflect.DeepEqual(err, wantErr) {
+                                       t.Fatalf("Read() error at record %d:\ngot %v (%#v)\nwant %v (%#v)", recNum, err, err, wantErr, wantErr)
+                               }
+                               // ErrFieldCount is explicitly non-fatal.
+                               if err != nil && !errors.Is(err, ErrFieldCount) {
+                                       if recNum < len(tt.Output) {
+                                               t.Fatalf("need more records; got %d want %d", recNum, len(tt.Output))
+                                       }
+                                       break
+                               }
+                               if got, want := rec, tt.Output[recNum]; !reflect.DeepEqual(got, want) {
+                                       t.Errorf("Read vs ReadAll mismatch;\ngot %q\nwant %q", got, want)
+                               }
+                               pos := positions[recNum]
+                               if len(pos) != len(rec) {
+                                       t.Fatalf("mismatched position length at record %d", recNum)
+                               }
+                               for i := range rec {
+                                       line, col := r.FieldPos(i)
+                                       if got, want := [2]int{line, col}, pos[i]; got != want {
+                                               t.Errorf("position mismatch at record %d, field %d;\ngot %v\nwant %v", recNum, i, got, want)
+                                       }
+                               }
                        }
                })
        }
 }
 
+// firstError returns the first non-nil error in errs,
+// with the position adjusted according to the error's
+// index inside positions.
+func firstError(errs []error, positions [][][2]int, errPositions map[int][2]int) error {
+       for i, err := range errs {
+               if err != nil {
+                       return errorWithPosition(err, i, positions, errPositions)
+               }
+       }
+       return nil
+}
+
+func errorWithPosition(err error, recNum int, positions [][][2]int, errPositions map[int][2]int) error {
+       parseErr, ok := err.(*ParseError)
+       if !ok {
+               return err
+       }
+       if recNum >= len(positions) {
+               panic(fmt.Errorf("no positions found for error at record %d", recNum))
+       }
+       errPos, ok := errPositions[recNum]
+       if !ok {
+               panic(fmt.Errorf("no error position found for error at record %d", recNum))
+       }
+       parseErr1 := *parseErr
+       parseErr1.StartLine = positions[recNum][0][0]
+       parseErr1.Line = errPos[0]
+       parseErr1.Column = errPos[1]
+       return &parseErr1
+}
+
+// makePositions returns the expected field positions of all
+// the fields in text, the positions of any errors, and the text with the position markers
+// removed.
+//
+// The start of each field is marked with a § symbol;
+// CSV lines are separated by ¶ symbols;
+// Error positions are marked with ∑ symbols.
+func makePositions(text string) ([][][2]int, map[int][2]int, string) {
+       buf := make([]byte, 0, len(text))
+       var positions [][][2]int
+       errPositions := make(map[int][2]int)
+       line, col := 1, 1
+       recNum := 0
+
+       for len(text) > 0 {
+               r, size := utf8.DecodeRuneInString(text)
+               switch r {
+               case '\n':
+                       line++
+                       col = 1
+                       buf = append(buf, '\n')
+               case '§':
+                       if len(positions) == 0 {
+                               positions = append(positions, [][2]int{})
+                       }
+                       positions[len(positions)-1] = append(positions[len(positions)-1], [2]int{line, col})
+               case '¶':
+                       positions = append(positions, [][2]int{})
+                       recNum++
+               case '∑':
+                       errPositions[recNum] = [2]int{line, col}
+               default:
+                       buf = append(buf, text[:size]...)
+                       col += size
+               }
+               text = text[size:]
+       }
+       return positions, errPositions, string(buf)
+}
+
 // nTimes is an io.Reader which yields the string s n times.
 type nTimes struct {
        s   string
index 8f93742f49946a70e6422d8e256e20c17c8aa9b1..5965fea921f9d30bd098e3d414f48b79a07c91eb 100644 (file)
@@ -3,6 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // Delete the next line to include in the gob package.
+//go:build ignore
 // +build ignore
 
 package gob
index 1c31e66625fd50be566089ee6cd6df61b9b5c1de..994be877d935b60be097398cf5d9538509cfffc2 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 // encgen writes the helper functions for encoding. Intended to be
index b52aabe54b532df5d233a7f7151514a0f94a7a3f..b476aaac93be537f24ef16c72c208bee6538078d 100644 (file)
@@ -152,6 +152,9 @@ func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId {
                }
                // Type definition for (-id) follows.
                dec.recvType(-id)
+               if dec.err != nil {
+                       break
+               }
                // When decoding an interface, after a type there may be a
                // DelimitedValue still in the buffer. Skip its count.
                // (Alternatively, the buffer is empty and the byte count
@@ -215,7 +218,7 @@ func (dec *Decoder) DecodeValue(v reflect.Value) error {
        return dec.err
 }
 
-// If debug.go is compiled into the program , debugFunc prints a human-readable
+// If debug.go is compiled into the program, debugFunc prints a human-readable
 // representation of the gob data read from r by calling that file's Debug function.
 // Otherwise it is nil.
 var debugFunc func(io.Reader)
index 17238c98df0d3bdf04a1084c1edd129a656f8e84..8c0bbc4ff2e50bbc1f5a891f433b8ada36022f26 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 package main
index 409b8c9d9525a00d2e031e434db2e449a26e7de2..b562da177dbb34d0b4faf149ced9c1464706946c 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 // encgen writes the helper functions for encoding. Intended to be
index fe2774948a7e9a30624f036d28edaf934a2875e3..6183646f60c8d39ddbf15896911e3d036848c474 100644 (file)
@@ -1127,3 +1127,28 @@ func TestBadData(t *testing.T) {
                }
        }
 }
+
+func TestDecodeErrorMultipleTypes(t *testing.T) {
+       type Test struct {
+               A string
+               B int
+       }
+       var b bytes.Buffer
+       NewEncoder(&b).Encode(Test{"one", 1})
+
+       var result, result2 Test
+       dec := NewDecoder(&b)
+       err := dec.Decode(&result)
+       if err != nil {
+               t.Errorf("decode: unexpected error %v", err)
+       }
+
+       b.Reset()
+       NewEncoder(&b).Encode(Test{"two", 2})
+       err = dec.Decode(&result2)
+       if err == nil {
+               t.Errorf("decode: expected duplicate type error, got nil")
+       } else if !strings.Contains(err.Error(), "duplicate type") {
+               t.Errorf("decode: expected duplicate type error, got %s", err.Error())
+       }
+}
index 86d8a69db7e6d76aa40ca9d4b307ea2f43e909b7..a9917e72c761cd408021d37b712620d14ac2a84f 100644 (file)
@@ -200,16 +200,19 @@ func (n Number) Int64() (int64, error) {
        return strconv.ParseInt(string(n), 10, 64)
 }
 
+// An errorContext provides context for type errors during decoding.
+type errorContext struct {
+       Struct     reflect.Type
+       FieldStack []string
+}
+
 // decodeState represents the state while decoding a JSON value.
 type decodeState struct {
-       data         []byte
-       off          int // next read offset in data
-       opcode       int // last read result
-       scan         scanner
-       errorContext struct { // provides context for type errors
-               Struct     reflect.Type
-               FieldStack []string
-       }
+       data                  []byte
+       off                   int // next read offset in data
+       opcode                int // last read result
+       scan                  scanner
+       errorContext          *errorContext
        savedError            error
        useNumber             bool
        disallowUnknownFields bool
@@ -229,10 +232,11 @@ func (d *decodeState) init(data []byte) *decodeState {
        d.data = data
        d.off = 0
        d.savedError = nil
-       d.errorContext.Struct = nil
-
-       // Reuse the allocated space for the FieldStack slice.
-       d.errorContext.FieldStack = d.errorContext.FieldStack[:0]
+       if d.errorContext != nil {
+               d.errorContext.Struct = nil
+               // Reuse the allocated space for the FieldStack slice.
+               d.errorContext.FieldStack = d.errorContext.FieldStack[:0]
+       }
        return d
 }
 
@@ -246,12 +250,11 @@ func (d *decodeState) saveError(err error) {
 
 // addErrorContext returns a new error enhanced with information from d.errorContext
 func (d *decodeState) addErrorContext(err error) error {
-       if d.errorContext.Struct != nil || len(d.errorContext.FieldStack) > 0 {
+       if d.errorContext != nil && (d.errorContext.Struct != nil || len(d.errorContext.FieldStack) > 0) {
                switch err := err.(type) {
                case *UnmarshalTypeError:
                        err.Struct = d.errorContext.Struct.Name()
                        err.Field = strings.Join(d.errorContext.FieldStack, ".")
-                       return err
                }
        }
        return err
@@ -657,7 +660,10 @@ func (d *decodeState) object(v reflect.Value) error {
        }
 
        var mapElem reflect.Value
-       origErrorContext := d.errorContext
+       var origErrorContext errorContext
+       if d.errorContext != nil {
+               origErrorContext = *d.errorContext
+       }
 
        for {
                // Read opening " of string key or closing }.
@@ -732,6 +738,9 @@ func (d *decodeState) object(v reflect.Value) error {
                                        }
                                        subv = subv.Field(i)
                                }
+                               if d.errorContext == nil {
+                                       d.errorContext = new(errorContext)
+                               }
                                d.errorContext.FieldStack = append(d.errorContext.FieldStack, f.name)
                                d.errorContext.Struct = t
                        } else if d.disallowUnknownFields {
@@ -812,11 +821,13 @@ func (d *decodeState) object(v reflect.Value) error {
                if d.opcode == scanSkipSpace {
                        d.scanWhile(scanSkipSpace)
                }
-               // Reset errorContext to its original state.
-               // Keep the same underlying array for FieldStack, to reuse the
-               // space and avoid unnecessary allocs.
-               d.errorContext.FieldStack = d.errorContext.FieldStack[:len(origErrorContext.FieldStack)]
-               d.errorContext.Struct = origErrorContext.Struct
+               if d.errorContext != nil {
+                       // Reset errorContext to its original state.
+                       // Keep the same underlying array for FieldStack, to reuse the
+                       // space and avoid unnecessary allocs.
+                       d.errorContext.FieldStack = d.errorContext.FieldStack[:len(origErrorContext.FieldStack)]
+                       d.errorContext.Struct = origErrorContext.Struct
+               }
                if d.opcode == scanEndObject {
                        break
                }
index 483b9d8f2d0a3c5d80509a1e03d8835d869c19c4..e473e615a9ed43f5f974853e86b220259c81c091 100644 (file)
@@ -794,23 +794,24 @@ func (me mapEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
        e.WriteByte('{')
 
        // Extract and sort the keys.
-       keys := v.MapKeys()
-       sv := make([]reflectWithString, len(keys))
-       for i, v := range keys {
-               sv[i].v = v
+       sv := make([]reflectWithString, v.Len())
+       mi := v.MapRange()
+       for i := 0; mi.Next(); i++ {
+               sv[i].k = mi.Key()
+               sv[i].v = mi.Value()
                if err := sv[i].resolve(); err != nil {
                        e.error(fmt.Errorf("json: encoding error for type %q: %q", v.Type().String(), err.Error()))
                }
        }
-       sort.Slice(sv, func(i, j int) bool { return sv[i].s < sv[j].s })
+       sort.Slice(sv, func(i, j int) bool { return sv[i].ks < sv[j].ks })
 
        for i, kv := range sv {
                if i > 0 {
                        e.WriteByte(',')
                }
-               e.string(kv.s, opts.escapeHTML)
+               e.string(kv.ks, opts.escapeHTML)
                e.WriteByte(':')
-               me.elemEnc(e, v.MapIndex(kv.v), opts)
+               me.elemEnc(e, kv.v, opts)
        }
        e.WriteByte('}')
        e.ptrLevel--
@@ -997,29 +998,30 @@ func typeByIndex(t reflect.Type, index []int) reflect.Type {
 }
 
 type reflectWithString struct {
-       v reflect.Value
-       s string
+       k  reflect.Value
+       v  reflect.Value
+       ks string
 }
 
 func (w *reflectWithString) resolve() error {
-       if w.v.Kind() == reflect.String {
-               w.s = w.v.String()
+       if w.k.Kind() == reflect.String {
+               w.ks = w.k.String()
                return nil
        }
-       if tm, ok := w.v.Interface().(encoding.TextMarshaler); ok {
-               if w.v.Kind() == reflect.Ptr && w.v.IsNil() {
+       if tm, ok := w.k.Interface().(encoding.TextMarshaler); ok {
+               if w.k.Kind() == reflect.Ptr && w.k.IsNil() {
                        return nil
                }
                buf, err := tm.MarshalText()
-               w.s = string(buf)
+               w.ks = string(buf)
                return err
        }
-       switch w.v.Kind() {
+       switch w.k.Kind() {
        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-               w.s = strconv.FormatInt(w.v.Int(), 10)
+               w.ks = strconv.FormatInt(w.k.Int(), 10)
                return nil
        case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-               w.s = strconv.FormatUint(w.v.Uint(), 10)
+               w.ks = strconv.FormatUint(w.k.Uint(), 10)
                return nil
        }
        panic("unexpected map key type")
@@ -1239,19 +1241,18 @@ func typeFields(t reflect.Type) structFields {
                        // Scan f.typ for fields to include.
                        for i := 0; i < f.typ.NumField(); i++ {
                                sf := f.typ.Field(i)
-                               isUnexported := sf.PkgPath != ""
                                if sf.Anonymous {
                                        t := sf.Type
                                        if t.Kind() == reflect.Ptr {
                                                t = t.Elem()
                                        }
-                                       if isUnexported && t.Kind() != reflect.Struct {
+                                       if !sf.IsExported() && t.Kind() != reflect.Struct {
                                                // Ignore embedded fields of unexported non-struct types.
                                                continue
                                        }
                                        // Do not ignore embedded fields of unexported struct types
                                        // since they may have exported fields.
-                               } else if isUnexported {
+                               } else if !sf.IsExported() {
                                        // Ignore unexported non-embedded fields.
                                        continue
                                }
index 42bb09d5cded0babe31a089369f325ff6b3aaf7e..0dad9510952702948d743932aeeaf583d62a0007 100644 (file)
@@ -245,6 +245,22 @@ func TestUnsupportedValues(t *testing.T) {
        }
 }
 
+// Issue 43207
+func TestMarshalTextFloatMap(t *testing.T) {
+       m := map[textfloat]string{
+               textfloat(math.NaN()): "1",
+               textfloat(math.NaN()): "1",
+       }
+       got, err := Marshal(m)
+       if err != nil {
+               t.Errorf("Marshal() error: %v", err)
+       }
+       want := `{"TF:NaN":"1","TF:NaN":"1"}`
+       if string(got) != want {
+               t.Errorf("Marshal() = %s, want %s", got, want)
+       }
+}
+
 // Ref has Marshaler and Unmarshaler methods with pointer receiver.
 type Ref int
 
@@ -854,6 +870,10 @@ func tenc(format string, a ...interface{}) ([]byte, error) {
        return buf.Bytes(), nil
 }
 
+type textfloat float64
+
+func (f textfloat) MarshalText() ([]byte, error) { return tenc(`TF:%0.2f`, f) }
+
 // Issue 13783
 func TestEncodeBytekind(t *testing.T) {
        testdata := []struct {
@@ -872,6 +892,7 @@ func TestEncodeBytekind(t *testing.T) {
                {[]jsonint{5, 4}, `[{"JI":5},{"JI":4}]`},
                {[]textint{9, 3}, `["TI:9","TI:3"]`},
                {[]int{9, 3}, `[9,3]`},
+               {[]textfloat{12, 3}, `["TF:12.00","TF:3.00"]`},
        }
        for _, d := range testdata {
                js, err := Marshal(d.data)
index be03f0d7ffc55510da9dcb41937709c959b6d9f9..d3fa2d111384152b18e9b804bea4bf429c1548ed 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build gofuzz
 // +build gofuzz
 
 package json
index f30fe58590bd774d6bf5c423506d0c107aae4819..162724ef1a58b02d452a7783a11f523c65c3d6bf 100644 (file)
@@ -60,7 +60,7 @@ func getTypeInfo(typ reflect.Type) (*typeInfo, error) {
                n := typ.NumField()
                for i := 0; i < n; i++ {
                        f := typ.Field(i)
-                       if (f.PkgPath != "" && !f.Anonymous) || f.Tag.Get("xml") == "-" {
+                       if (!f.IsExported() && !f.Anonymous) || f.Tag.Get("xml") == "-" {
                                continue // Private field
                        }
 
index 6f9594d7ba7a3ae2cc1609e910b95d4020497b57..c14954df155a64a0ff3ef1126f22376538f4f78a 100644 (file)
@@ -261,7 +261,7 @@ func NewTokenDecoder(t TokenReader) *Decoder {
 // call to Token. To acquire a copy of the bytes, call CopyToken
 // or the token's Copy method.
 //
-// Token expands self-closing elements such as <br/>
+// Token expands self-closing elements such as <br>
 // into separate start and end elements returned by successive calls.
 //
 // Token guarantees that the StartElement and EndElement
@@ -768,6 +768,12 @@ func (d *Decoder) rawToken() (Token, error) {
                                        }
                                        b0, b1 = b1, b
                                }
+
+                               // Replace the comment with a space in the returned Directive
+                               // body, so that markup parts that were separated by the comment
+                               // (like a "<" and a "!") don't get joined when re-encoding the
+                               // Directive, taking new semantic meaning.
+                               d.buf.WriteByte(' ')
                        }
                }
                return Directive(d.buf.Bytes()), nil
@@ -1156,8 +1162,9 @@ func (d *Decoder) nsname() (name Name, ok bool) {
        if !ok {
                return
        }
-       i := strings.Index(s, ":")
-       if i < 0 {
+       if strings.Count(s, ":") > 1 {
+               name.Local = s
+       } else if i := strings.Index(s, ":"); i < 1 || i > len(s)-2 {
                name.Local = s
        } else {
                name.Space = s[0:i]
index 5672ebb375f0d4a25019e0ea402922f6c60cd9a8..19152dbdb689511a4f3ec28eab5ee21172438472 100644 (file)
@@ -802,11 +802,11 @@ var directivesWithCommentsInput = `
 
 var directivesWithCommentsTokens = []Token{
        CharData("\n"),
-       Directive(`DOCTYPE [<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">]`),
+       Directive(`DOCTYPE [ <!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">]`),
        CharData("\n"),
-       Directive(`DOCTYPE [<!ENTITY go "Golang">]`),
+       Directive(`DOCTYPE [<!ENTITY go "Golang"> ]`),
        CharData("\n"),
-       Directive(`DOCTYPE <!-> <!>    [<!ENTITY go "Golang">]`),
+       Directive(`DOCTYPE <!-> <!>       [<!ENTITY go "Golang"> ]`),
        CharData("\n"),
 }
 
@@ -940,7 +940,7 @@ func (m mapper) Token() (Token, error) {
 }
 
 func TestNewTokenDecoderIdempotent(t *testing.T) {
-       d := NewDecoder(strings.NewReader(`<br/>`))
+       d := NewDecoder(strings.NewReader(`<br>`))
        d2 := NewTokenDecoder(d)
        if d != d2 {
                t.Error("NewTokenDecoder did not detect underlying Decoder")
@@ -1003,3 +1003,60 @@ func TestTokenUnmarshaler(t *testing.T) {
        d := NewTokenDecoder(tokReader{})
        d.Decode(&Failure{})
 }
+
+func testRoundTrip(t *testing.T, input string) {
+       d := NewDecoder(strings.NewReader(input))
+       var tokens []Token
+       var buf bytes.Buffer
+       e := NewEncoder(&buf)
+       for {
+               tok, err := d.Token()
+               if err == io.EOF {
+                       break
+               }
+               if err != nil {
+                       t.Fatalf("invalid input: %v", err)
+               }
+               if err := e.EncodeToken(tok); err != nil {
+                       t.Fatalf("failed to re-encode input: %v", err)
+               }
+               tokens = append(tokens, CopyToken(tok))
+       }
+       if err := e.Flush(); err != nil {
+               t.Fatal(err)
+       }
+
+       d = NewDecoder(&buf)
+       for {
+               tok, err := d.Token()
+               if err == io.EOF {
+                       break
+               }
+               if err != nil {
+                       t.Fatalf("failed to decode output: %v", err)
+               }
+               if len(tokens) == 0 {
+                       t.Fatalf("unexpected token: %#v", tok)
+               }
+               a, b := tokens[0], tok
+               if !reflect.DeepEqual(a, b) {
+                       t.Fatalf("token mismatch: %#v vs %#v", a, b)
+               }
+               tokens = tokens[1:]
+       }
+       if len(tokens) > 0 {
+               t.Fatalf("lost tokens: %#v", tokens)
+       }
+}
+
+func TestRoundTrip(t *testing.T) {
+       tests := map[string]string{
+               "leading colon":          `<::Test ::foo="bar"><:::Hello></:::Hello><Hello></Hello></::Test>`,
+               "trailing colon":         `<foo abc:="x"></foo>`,
+               "double colon":           `<x:y:foo></x:y:foo>`,
+               "comments in directives": `<!ENTITY x<!<!-- c1 [ " -->--x --> > <e></e> <!DOCTYPE xxx [ x<!-- c2 " -->--x ]>`,
+       }
+       for name, input := range tests {
+               t.Run(name, func(t *testing.T) { testRoundTrip(t, input) })
+       }
+}
index 7928fe673ee7a8c6ba2f9f472799f6e98563c59c..4eb4f9ae378bdbb182d4403edfd725cebbd6dfa6 100644 (file)
@@ -83,10 +83,10 @@ func As(err error, target interface{}) bool {
        if typ.Kind() != reflectlite.Ptr || val.IsNil() {
                panic("errors: target must be a non-nil pointer")
        }
-       if e := typ.Elem(); e.Kind() != reflectlite.Interface && !e.Implements(errorType) {
+       targetType := typ.Elem()
+       if targetType.Kind() != reflectlite.Interface && !targetType.Implements(errorType) {
                panic("errors: *target must be interface or implement error")
        }
-       targetType := typ.Elem()
        for err != nil {
                if reflectlite.TypeOf(err).AssignableTo(targetType) {
                        val.Elem().Set(reflectlite.ValueOf(err))
index a8485f034f30c13cee232c0d5ffcfa15bb36c8e2..885a4c8369663f99b9b492bb65d4e768b66d51f6 100644 (file)
@@ -508,31 +508,33 @@ func UnquoteUsage(flag *Flag) (name string, usage string) {
 // documentation for the global function PrintDefaults for more information.
 func (f *FlagSet) PrintDefaults() {
        f.VisitAll(func(flag *Flag) {
-               s := fmt.Sprintf("  -%s", flag.Name) // Two spaces before -; see next two comments.
+               var b strings.Builder
+               fmt.Fprintf(&b, "  -%s", flag.Name) // Two spaces before -; see next two comments.
                name, usage := UnquoteUsage(flag)
                if len(name) > 0 {
-                       s += " " + name
+                       b.WriteString(" ")
+                       b.WriteString(name)
                }
                // Boolean flags of one ASCII letter are so common we
                // treat them specially, putting their usage on the same line.
-               if len(s) <= 4 { // space, space, '-', 'x'.
-                       s += "\t"
+               if b.Len() <= 4 { // space, space, '-', 'x'.
+                       b.WriteString("\t")
                } else {
                        // Four spaces before the tab triggers good alignment
                        // for both 4- and 8-space tab stops.
-                       s += "\n    \t"
+                       b.WriteString("\n    \t")
                }
-               s += strings.ReplaceAll(usage, "\n", "\n    \t")
+               b.WriteString(strings.ReplaceAll(usage, "\n", "\n    \t"))
 
                if !isZeroValue(flag, flag.DefValue) {
                        if _, ok := flag.Value.(*stringValue); ok {
                                // put quotes on the value
-                               s += fmt.Sprintf(" (default %q)", flag.DefValue)
+                               fmt.Fprintf(&b, " (default %q)", flag.DefValue)
                        } else {
-                               s += fmt.Sprintf(" (default %v)", flag.DefValue)
+                               fmt.Fprintf(&b, " (default %v)", flag.DefValue)
                        }
                }
-               fmt.Fprint(f.Output(), s, "\n")
+               fmt.Fprint(f.Output(), b.String(), "\n")
        })
 }
 
@@ -857,17 +859,23 @@ func Func(name, usage string, fn func(string) error) {
 // of strings by giving the slice the methods of Value; in particular, Set would
 // decompose the comma-separated string into the slice.
 func (f *FlagSet) Var(value Value, name string, usage string) {
+       // Flag must not begin "-" or contain "=".
+       if strings.HasPrefix(name, "-") {
+               panic(f.sprintf("flag %q begins with -", name))
+       } else if strings.Contains(name, "=") {
+               panic(f.sprintf("flag %q contains =", name))
+       }
+
        // Remember the default value as a string; it won't change.
        flag := &Flag{name, usage, value, value.String()}
        _, alreadythere := f.formal[name]
        if alreadythere {
                var msg string
                if f.name == "" {
-                       msg = fmt.Sprintf("flag redefined: %s", name)
+                       msg = f.sprintf("flag redefined: %s", name)
                } else {
-                       msg = fmt.Sprintf("%s flag redefined: %s", f.name, name)
+                       msg = f.sprintf("%s flag redefined: %s", f.name, name)
                }
-               fmt.Fprintln(f.Output(), msg)
                panic(msg) // Happens only if flags are declared with identical names
        }
        if f.formal == nil {
@@ -886,13 +894,19 @@ func Var(value Value, name string, usage string) {
        CommandLine.Var(value, name, usage)
 }
 
+// sprintf formats the message, prints it to output, and returns it.
+func (f *FlagSet) sprintf(format string, a ...interface{}) string {
+       msg := fmt.Sprintf(format, a...)
+       fmt.Fprintln(f.Output(), msg)
+       return msg
+}
+
 // failf prints to standard error a formatted error and usage message and
 // returns the error.
 func (f *FlagSet) failf(format string, a ...interface{}) error {
-       err := fmt.Errorf(format, a...)
-       fmt.Fprintln(f.Output(), err)
+       msg := f.sprintf(format, a...)
        f.usage()
-       return err
+       return errors.New(msg)
 }
 
 // usage calls the Usage method for the flag set if one is specified,
index 06cab79405a7bab928b557c51335951ff83bdfa3..5835fcf22cd7a9ff2c1eddfc3980d92cd7d5c13b 100644 (file)
@@ -655,3 +655,86 @@ func TestExitCode(t *testing.T) {
                }
        }
 }
+
+func mustPanic(t *testing.T, testName string, expected string, f func()) {
+       t.Helper()
+       defer func() {
+               switch msg := recover().(type) {
+               case nil:
+                       t.Errorf("%s\n: expected panic(%q), but did not panic", testName, expected)
+               case string:
+                       if msg != expected {
+                               t.Errorf("%s\n: expected panic(%q), but got panic(%q)", testName, expected, msg)
+                       }
+               default:
+                       t.Errorf("%s\n: expected panic(%q), but got panic(%T%v)", testName, expected, msg, msg)
+               }
+       }()
+       f()
+}
+
+func TestInvalidFlags(t *testing.T) {
+       tests := []struct {
+               flag     string
+               errorMsg string
+       }{
+               {
+                       flag:     "-foo",
+                       errorMsg: "flag \"-foo\" begins with -",
+               },
+               {
+                       flag:     "foo=bar",
+                       errorMsg: "flag \"foo=bar\" contains =",
+               },
+       }
+
+       for _, test := range tests {
+               testName := fmt.Sprintf("FlagSet.Var(&v, %q, \"\")", test.flag)
+
+               fs := NewFlagSet("", ContinueOnError)
+               buf := bytes.NewBuffer(nil)
+               fs.SetOutput(buf)
+
+               mustPanic(t, testName, test.errorMsg, func() {
+                       var v flagVar
+                       fs.Var(&v, test.flag, "")
+               })
+               if msg := test.errorMsg + "\n"; msg != buf.String() {
+                       t.Errorf("%s\n: unexpected output: expected %q, bug got %q", testName, msg, buf)
+               }
+       }
+}
+
+func TestRedefinedFlags(t *testing.T) {
+       tests := []struct {
+               flagSetName string
+               errorMsg    string
+       }{
+               {
+                       flagSetName: "",
+                       errorMsg:    "flag redefined: foo",
+               },
+               {
+                       flagSetName: "fs",
+                       errorMsg:    "fs flag redefined: foo",
+               },
+       }
+
+       for _, test := range tests {
+               testName := fmt.Sprintf("flag redefined in FlagSet(%q)", test.flagSetName)
+
+               fs := NewFlagSet(test.flagSetName, ContinueOnError)
+               buf := bytes.NewBuffer(nil)
+               fs.SetOutput(buf)
+
+               var v flagVar
+               fs.Var(&v, "foo", "")
+
+               mustPanic(t, testName, test.errorMsg, func() {
+                       fs.Var(&v, "foo", "")
+               })
+               if msg := test.errorMsg + "\n"; msg != buf.String() {
+                       t.Errorf("%s\n: unexpected output: expected %q, bug got %q", testName, msg, buf)
+               }
+       }
+}
index d05ee519c3db471c384bae5bfe05de56914b0dcc..c584cc9465e57364b27143529040d6f4dcce9434 100644 (file)
        When printing a struct, fmt cannot and therefore does not invoke
        formatting methods such as Error or String on unexported fields.
 
-       Explicit argument indexes:
+       Explicit argument indexes
 
        In Printf, Sprintf, and Fprintf, the default behavior is for each
        formatting verb to format successive arguments passed in the call.
                fmt.Sprintf("%d %d %#[1]x %#x", 16, 17)
        will yield "16 17 0x10 0x11".
 
-       Format errors:
+       Format errors
 
        If an invalid argument is given for a verb, such as providing
        a string to %d, the generated string will contain a
index 4d12f82f7dea84a14d0edd574150115f2c80c64e..bd00e5a5e0131f071d9b3b0a5f6c8d2b6ad1060b 100644 (file)
@@ -320,7 +320,7 @@ func (f *fmt) fmtInteger(u uint64, base int, isSigned bool, verb rune, digits st
        f.zero = oldZero
 }
 
-// truncate truncates the string s to the specified precision, if present.
+// truncateString truncates the string s to the specified precision, if present.
 func (f *fmt) truncateString(s string) string {
        if f.precPresent {
                n := f.prec
index 798677b68c13459fc4feea646cd799e55a71cab9..379dcf504e5316fe43a502bc12e92411650dd9d6 100644 (file)
@@ -1,10 +1,10 @@
 module std
 
-go 1.16
+go 1.17
 
 require (
-       golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
-       golang.org/x/net v0.0.0-20210428183300-3f4a416c7d3b
-       golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect
-       golang.org/x/text v0.3.4 // indirect
+       golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e
+       golang.org/x/net v0.0.0-20210510120150-4163338589ed
+       golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 // indirect
+       golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f // indirect
 )
index 300966a32638009c3b8d44f84e297d116c6e37e5..337c87fd797351c344bf3e4b2ea01c20b3235c2e 100644 (file)
@@ -193,11 +193,14 @@ func isDirective(c string) bool {
 // in a signature.
 // Field.Names is nil for unnamed parameters (parameter lists which only contain types)
 // and embedded struct fields. In the latter case, the field name is the type name.
+// Field.Names contains a single name "type" for elements of interface type lists.
+// Types belonging to the same type list share the same "type" identifier which also
+// records the position of that keyword.
 //
 type Field struct {
        Doc     *CommentGroup // associated documentation; or nil
-       Names   []*Ident      // field/method/parameter names; or nil
-       Type    Expr          // field/method/parameter type
+       Names   []*Ident      // field/method/(type) parameter names, or type "type"; or nil
+       Type    Expr          // field/method/parameter type, type list type; or nil
        Tag     *BasicLit     // field tag; or nil
        Comment *CommentGroup // line comments; or nil
 }
@@ -206,14 +209,23 @@ func (f *Field) Pos() token.Pos {
        if len(f.Names) > 0 {
                return f.Names[0].Pos()
        }
-       return f.Type.Pos()
+       if f.Type != nil {
+               return f.Type.Pos()
+       }
+       return token.NoPos
 }
 
 func (f *Field) End() token.Pos {
        if f.Tag != nil {
                return f.Tag.End()
        }
-       return f.Type.End()
+       if f.Type != nil {
+               return f.Type.End()
+       }
+       if len(f.Names) > 0 {
+               return f.Names[len(f.Names)-1].End()
+       }
+       return token.NoPos
 }
 
 // A FieldList represents a list of Fields, enclosed by parentheses or braces.
@@ -290,12 +302,6 @@ type (
        }
 
        // A BasicLit node represents a literal of basic type.
-       //
-       // Note that for the CHAR and STRING kinds, the literal is stored
-       // with its quotes. For example, for a double-quoted STRING, the
-       // first and the last rune in the Value field will be ". The
-       // Unquote and UnquoteChar functions in the strconv package can be
-       // used to unquote STRING and CHAR values, respectively.
        BasicLit struct {
                ValuePos token.Pos   // literal position
                Kind     token.Token // token.INT, token.FLOAT, token.IMAG, token.CHAR, or token.STRING
@@ -434,18 +440,11 @@ type (
 
        // Pointer types are represented via StarExpr nodes.
 
-       // A FuncType node represents a function type.
-       FuncType struct {
-               Func    token.Pos  // position of "func" keyword (token.NoPos if there is no "func")
-               Params  *FieldList // (incoming) parameters; non-nil
-               Results *FieldList // (outgoing) results; or nil
-       }
-
        // An InterfaceType node represents an interface type.
        InterfaceType struct {
                Interface  token.Pos  // position of "interface" keyword
-               Methods    *FieldList // list of methods
-               Incomplete bool       // true if (source) methods are missing in the Methods list
+               Methods    *FieldList // list of embedded interfaces, methods, or types
+               Incomplete bool       // true if (source) methods or types are missing in the Methods list
        }
 
        // A MapType node represents a map type.
@@ -893,15 +892,6 @@ type (
                Values  []Expr        // initial values; or nil
                Comment *CommentGroup // line comments; or nil
        }
-
-       // A TypeSpec node represents a type declaration (TypeSpec production).
-       TypeSpec struct {
-               Doc     *CommentGroup // associated documentation; or nil
-               Name    *Ident        // type name
-               Assign  token.Pos     // position of '=', if any
-               Type    Expr          // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypes
-               Comment *CommentGroup // line comments; or nil
-       }
 )
 
 // Pos and End implementations for spec nodes.
@@ -965,7 +955,7 @@ type (
        GenDecl struct {
                Doc    *CommentGroup // associated documentation; or nil
                TokPos token.Pos     // position of Tok
-               Tok    token.Token   // IMPORT, CONST, TYPE, VAR
+               Tok    token.Token   // IMPORT, CONST, TYPE, or VAR
                Lparen token.Pos     // position of '(', if any
                Specs  []Spec
                Rparen token.Pos // position of ')', if any
@@ -976,8 +966,10 @@ type (
                Doc  *CommentGroup // associated documentation; or nil
                Recv *FieldList    // receiver (methods); or nil (functions)
                Name *Ident        // function/method name
-               Type *FuncType     // function signature: parameters, results, and position of "func" keyword
+               Type *FuncType     // function signature: type and value parameters, results, and position of "func" keyword
                Body *BlockStmt    // function body; or nil for external (non-Go) function
+               // TODO(rFindley) consider storing TParams here, rather than FuncType, as
+               //                they are only valid for declared functions
        }
 )
 
diff --git a/libgo/go/go/ast/ast_notypeparams.go b/libgo/go/go/ast/ast_notypeparams.go
new file mode 100644 (file)
index 0000000..fa132fb
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !typeparams
+// +build !typeparams
+
+package ast
+
+import "go/token"
+
+type (
+       // A FuncType node represents a function type.
+       FuncType struct {
+               Func    token.Pos  // position of "func" keyword (token.NoPos if there is no "func")
+               Params  *FieldList // (incoming) parameters; non-nil
+               Results *FieldList // (outgoing) results; or nil
+       }
+
+       // A TypeSpec node represents a type declaration (TypeSpec production).
+       TypeSpec struct {
+               Doc     *CommentGroup // associated documentation; or nil
+               Name    *Ident        // type name
+               Assign  token.Pos     // position of '=', if any
+               Type    Expr          // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypes
+               Comment *CommentGroup // line comments; or nil
+       }
+)
diff --git a/libgo/go/go/ast/ast_typeparams.go b/libgo/go/go/ast/ast_typeparams.go
new file mode 100644 (file)
index 0000000..24fdc5f
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build typeparams
+// +build typeparams
+
+package ast
+
+import "go/token"
+
+type (
+       // A FuncType node represents a function type.
+       FuncType struct {
+               Func    token.Pos  // position of "func" keyword (token.NoPos if there is no "func")
+               TParams *FieldList // type parameters; or nil
+               Params  *FieldList // (incoming) parameters; non-nil
+               Results *FieldList // (outgoing) results; or nil
+       }
+
+       // A TypeSpec node represents a type declaration (TypeSpec production).
+       TypeSpec struct {
+               Doc     *CommentGroup // associated documentation; or nil
+               Name    *Ident        // type name
+               TParams *FieldList    // type parameters; or nil
+               Assign  token.Pos     // position of '=', if any
+               Type    Expr          // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypes
+               Comment *CommentGroup // line comments; or nil
+       }
+
+       // A ListExpr node represents a list of expressions separated by commas.
+       // ListExpr nodes are used as index in IndexExpr nodes representing type
+       // or function instantiations with more than one type argument.
+       ListExpr struct {
+               ElemList []Expr
+       }
+)
+
+func (*ListExpr) exprNode() {}
+func (x *ListExpr) Pos() token.Pos {
+       if len(x.ElemList) > 0 {
+               return x.ElemList[0].Pos()
+       }
+       return token.NoPos
+}
+func (x *ListExpr) End() token.Pos {
+       if len(x.ElemList) > 0 {
+               return x.ElemList[len(x.ElemList)-1].End()
+       }
+       return token.NoPos
+}
index 2a653a60ac9b3ec13f0566f5e938a1bf37b85a9f..5161ea70b7640d088e918a5299c61bea7d313717 100644 (file)
@@ -315,9 +315,17 @@ loop:
 }
 
 func (cmap CommentMap) String() string {
+       // print map entries in sorted order
+       var nodes []Node
+       for node := range cmap {
+               nodes = append(nodes, node)
+       }
+       sort.Sort(byInterval(nodes))
+
        var buf bytes.Buffer
        fmt.Fprintln(&buf, "CommentMap {")
-       for node, comment := range cmap {
+       for _, node := range nodes {
+               comment := cmap[node]
                // print name of identifiers; print node type for other nodes
                var s string
                if ident, ok := node.(*Ident); ok {
index 8ca21959b11a012cae79c9f018100cb3bf1fe7fc..9224264e291e2fc8904fc208d94d0915f2e626f4 100644 (file)
@@ -4,8 +4,6 @@
 
 package ast
 
-import "fmt"
-
 // A Visitor's Visit method is invoked for each node encountered by Walk.
 // If the result visitor w is not nil, Walk visits each of the children
 // of node with the visitor w, followed by a call of w.Visit(nil).
@@ -71,7 +69,9 @@ func Walk(v Visitor, node Node) {
                        Walk(v, n.Doc)
                }
                walkIdentList(v, n.Names)
-               Walk(v, n.Type)
+               if n.Type != nil {
+                       Walk(v, n.Type)
+               }
                if n.Tag != nil {
                        Walk(v, n.Tag)
                }
@@ -161,6 +161,7 @@ func Walk(v Visitor, node Node) {
                Walk(v, n.Fields)
 
        case *FuncType:
+               walkFuncTypeParams(v, n)
                if n.Params != nil {
                        Walk(v, n.Params)
                }
@@ -315,6 +316,7 @@ func Walk(v Visitor, node Node) {
                        Walk(v, n.Doc)
                }
                Walk(v, n.Name)
+               walkTypeSpecParams(v, n)
                Walk(v, n.Type)
                if n.Comment != nil {
                        Walk(v, n.Comment)
@@ -361,7 +363,7 @@ func Walk(v Visitor, node Node) {
                }
 
        default:
-               panic(fmt.Sprintf("ast.Walk: unexpected node type %T", n))
+               walkOtherNodes(v, n)
        }
 
        v.Visit(nil)
diff --git a/libgo/go/go/ast/walk_notypeparams.go b/libgo/go/go/ast/walk_notypeparams.go
new file mode 100644 (file)
index 0000000..d43e13d
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !typeparams
+// +build !typeparams
+
+package ast
+
+import "fmt"
+
+func walkFuncTypeParams(v Visitor, n *FuncType) {}
+func walkTypeSpecParams(v Visitor, n *TypeSpec) {}
+
+func walkOtherNodes(v Visitor, n Node) {
+       panic(fmt.Sprintf("ast.Walk: unexpected node type %T", n))
+}
diff --git a/libgo/go/go/ast/walk_typeparams.go b/libgo/go/go/ast/walk_typeparams.go
new file mode 100644 (file)
index 0000000..b662133
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build typeparams
+// +build typeparams
+
+package ast
+
+import (
+       "fmt"
+)
+
+func walkFuncTypeParams(v Visitor, n *FuncType) {
+       if n.TParams != nil {
+               Walk(v, n.TParams)
+       }
+}
+
+func walkTypeSpecParams(v Visitor, n *TypeSpec) {
+       if n.TParams != nil {
+               Walk(v, n.TParams)
+       }
+}
+
+func walkOtherNodes(v Visitor, n Node) {
+       if e, ok := n.(*ListExpr); ok {
+               if e != nil {
+                       for _, elem := range e.ElemList {
+                               Walk(v, elem)
+                       }
+               }
+       } else {
+               panic(fmt.Sprintf("ast.Walk: unexpected node type %T", n))
+       }
+}
index 3007cef435130f66ec150da1c7dd941acaac29ed..f19f3d4a589e20f6fc8de3ae634241eeaf2e08eb 100644 (file)
@@ -9,8 +9,10 @@ import (
        "errors"
        "fmt"
        "go/ast"
+       "go/build/constraint"
        "go/doc"
        "go/token"
+       "internal/buildcfg"
        exec "internal/execabs"
        "internal/goroot"
        "internal/goversion"
@@ -47,16 +49,18 @@ type Context struct {
        UseAllFiles bool   // use files regardless of +build lines, file names
        Compiler    string // compiler to assume when computing target paths
 
-       // The build and release tags specify build constraints
+       // The build, tool, and release tags specify build constraints
        // that should be considered satisfied when processing +build lines.
        // Clients creating a new context may customize BuildTags, which
-       // defaults to empty, but it is usually an error to customize ReleaseTags,
-       // which defaults to the list of Go releases the current release is compatible with.
+       // defaults to empty, but it is usually an error to customize ToolTags or ReleaseTags.
+       // ToolTags defaults to build tags appropriate to the current Go toolchain configuration.
+       // ReleaseTags defaults to the list of Go releases the current release is compatible with.
        // BuildTags is not set for the Default build Context.
-       // In addition to the BuildTags and ReleaseTags, build constraints
+       // In addition to the BuildTags, ToolTags, and ReleaseTags, build constraints
        // consider the values of GOARCH and GOOS as satisfied tags.
        // The last element in ReleaseTags is assumed to be the current release.
        BuildTags   []string
+       ToolTags    []string
        ReleaseTags []string
 
        // The install suffix specifies a suffix to use in the name of the installation
@@ -187,6 +191,7 @@ func (ctxt *Context) readDir(path string) ([]fs.FileInfo, error) {
        if f := ctxt.ReadDir; f != nil {
                return f(path)
        }
+       // TODO: use os.ReadDir
        return ioutil.ReadDir(path)
 }
 
@@ -290,17 +295,27 @@ func defaultGOPATH() string {
        return ""
 }
 
-var defaultReleaseTags []string
+var defaultToolTags, defaultReleaseTags []string
 
 func defaultContext() Context {
        var c Context
 
-       c.GOARCH = envOr("GOARCH", runtime.GOARCH)
-       c.GOOS = envOr("GOOS", runtime.GOOS)
+       c.GOARCH = buildcfg.GOARCH
+       c.GOOS = buildcfg.GOOS
        c.GOROOT = pathpkg.Clean(runtime.GOROOT())
        c.GOPATH = envOr("GOPATH", defaultGOPATH())
        c.Compiler = runtime.Compiler
 
+       // For each experiment that has been enabled in the toolchain, define a
+       // build tag with the same name but prefixed by "goexperiment." which can be
+       // used for compiling alternative files for the experiment. This allows
+       // changes for the experiment, like extra struct fields in the runtime,
+       // without affecting the base non-experiment code at all.
+       for _, exp := range buildcfg.EnabledExperiments() {
+               c.ToolTags = append(c.ToolTags, "goexperiment."+exp)
+       }
+       defaultToolTags = append([]string{}, c.ToolTags...) // our own private copy
+
        // Each major Go release in the Go 1.x series adds a new
        // "go1.x" release tag. That is, the go1.x tag is present in
        // all releases >= Go 1.x. Code that requires Go 1.x or later
@@ -797,6 +812,17 @@ Found:
        }
 
        var badGoError error
+       badFiles := make(map[string]bool)
+       badFile := func(name string, err error) {
+               if badGoError == nil {
+                       badGoError = err
+               }
+               if !badFiles[name] {
+                       p.InvalidGoFiles = append(p.InvalidGoFiles, name)
+                       badFiles[name] = true
+               }
+       }
+
        var Sfiles []string // files with ".S"(capital S)/.sx(capital s equivalent for case insensitive filesystems)
        var firstFile, firstCommentFile string
        embedPos := make(map[string][]token.Position)
@@ -821,16 +847,9 @@ Found:
                name := d.Name()
                ext := nameExt(name)
 
-               badFile := func(err error) {
-                       if badGoError == nil {
-                               badGoError = err
-                       }
-                       p.InvalidGoFiles = append(p.InvalidGoFiles, name)
-               }
-
                info, err := ctxt.matchFile(p.Dir, name, allTags, &p.BinaryOnly, fset)
                if err != nil {
-                       badFile(err)
+                       badFile(name, err)
                        continue
                }
                if info == nil {
@@ -861,15 +880,18 @@ Found:
                }
 
                if info.parseErr != nil {
-                       badFile(info.parseErr)
-                       continue
+                       badFile(name, info.parseErr)
+                       // Fall through: we might still have a partial AST in info.parsed,
+                       // and we want to list files with parse errors anyway.
                }
-               pf := info.parsed
 
-               pkg := pf.Name.Name
-               if pkg == "documentation" {
-                       p.IgnoredGoFiles = append(p.IgnoredGoFiles, name)
-                       continue
+               var pkg string
+               if info.parsed != nil {
+                       pkg = info.parsed.Name.Name
+                       if pkg == "documentation" {
+                               p.IgnoredGoFiles = append(p.IgnoredGoFiles, name)
+                               continue
+                       }
                }
 
                isTest := strings.HasSuffix(name, "_test.go")
@@ -883,16 +905,18 @@ Found:
                        p.Name = pkg
                        firstFile = name
                } else if pkg != p.Name {
-                       badFile(&MultiplePackageError{
+                       // TODO(#45999): The choice of p.Name is arbitrary based on file iteration
+                       // order. Instead of resolving p.Name arbitrarily, we should clear out the
+                       // existing name and mark the existing files as also invalid.
+                       badFile(name, &MultiplePackageError{
                                Dir:      p.Dir,
                                Packages: []string{p.Name, pkg},
                                Files:    []string{firstFile, name},
                        })
-                       p.InvalidGoFiles = append(p.InvalidGoFiles, name)
                }
                // Grab the first package comment as docs, provided it is not from a test file.
-               if pf.Doc != nil && p.Doc == "" && !isTest && !isXTest {
-                       p.Doc = doc.Synopsis(pf.Doc.Text())
+               if info.parsed != nil && info.parsed.Doc != nil && p.Doc == "" && !isTest && !isXTest {
+                       p.Doc = doc.Synopsis(info.parsed.Doc.Text())
                }
 
                if mode&ImportComment != 0 {
@@ -900,12 +924,12 @@ Found:
                        if line != 0 {
                                com, err := strconv.Unquote(qcom)
                                if err != nil {
-                                       badFile(fmt.Errorf("%s:%d: cannot parse import comment", filename, line))
+                                       badFile(name, fmt.Errorf("%s:%d: cannot parse import comment", filename, line))
                                } else if p.ImportComment == "" {
                                        p.ImportComment = com
                                        firstCommentFile = name
                                } else if p.ImportComment != com {
-                                       badFile(fmt.Errorf("found import comments %q (%s) and %q (%s) in %s", p.ImportComment, firstCommentFile, com, name, p.Dir))
+                                       badFile(name, fmt.Errorf("found import comments %q (%s) and %q (%s) in %s", p.ImportComment, firstCommentFile, com, name, p.Dir))
                                }
                        }
                }
@@ -915,13 +939,13 @@ Found:
                for _, imp := range info.imports {
                        if imp.path == "C" {
                                if isTest {
-                                       badFile(fmt.Errorf("use of cgo in test %s not supported", filename))
+                                       badFile(name, fmt.Errorf("use of cgo in test %s not supported", filename))
                                        continue
                                }
                                isCgo = true
                                if imp.doc != nil {
                                        if err := ctxt.saveCgo(filename, p, imp.doc); err != nil {
-                                               badFile(err)
+                                               badFile(name, err)
                                        }
                                }
                        }
@@ -1056,7 +1080,7 @@ func (ctxt *Context) importGo(p *Package, path, srcDir string, mode ImportMode)
        // we must not being doing special things like AllowBinary or IgnoreVendor,
        // and all the file system callbacks must be nil (we're meant to use the local file system).
        if mode&AllowBinary != 0 || mode&IgnoreVendor != 0 ||
-               ctxt.JoinPath != nil || ctxt.SplitPathList != nil || ctxt.IsAbsPath != nil || ctxt.IsDir != nil || ctxt.HasSubdir != nil || ctxt.ReadDir != nil || ctxt.OpenFile != nil || !equal(ctxt.ReleaseTags, defaultReleaseTags) {
+               ctxt.JoinPath != nil || ctxt.SplitPathList != nil || ctxt.IsAbsPath != nil || ctxt.IsDir != nil || ctxt.HasSubdir != nil || ctxt.ReadDir != nil || ctxt.OpenFile != nil || !equal(ctxt.ToolTags, defaultToolTags) || !equal(ctxt.ReleaseTags, defaultReleaseTags) {
                return errNoModules
        }
 
@@ -1425,7 +1449,7 @@ func (ctxt *Context) matchFile(dir, name string, allTags map[string]bool, binary
        // Look for +build comments to accept or reject the file.
        ok, sawBinaryOnly, err := ctxt.shouldBuild(info.header, allTags)
        if err != nil {
-               return nil, err
+               return nil, fmt.Errorf("%s: %v", name, err)
        }
        if !ok && !ctxt.UseAllFiles {
                return nil, nil
@@ -1461,11 +1485,12 @@ var (
        bSlashSlash = []byte(slashSlash)
        bStarSlash  = []byte(starSlash)
        bSlashStar  = []byte(slashStar)
+       bPlusBuild  = []byte("+build")
 
        goBuildComment = []byte("//go:build")
 
        errGoBuildWithoutBuild = errors.New("//go:build comment without // +build comment")
-       errMultipleGoBuild     = errors.New("multiple //go:build comments") // unused in Go 1.(N-1)
+       errMultipleGoBuild     = errors.New("multiple //go:build comments")
 )
 
 func isGoBuildComment(line []byte) bool {
@@ -1500,8 +1525,7 @@ var binaryOnlyComment = []byte("//go:binary-only-package")
 // shouldBuild reports whether the file should be built
 // and whether a //go:binary-only-package comment was found.
 func (ctxt *Context) shouldBuild(content []byte, allTags map[string]bool) (shouldBuild, binaryOnly bool, err error) {
-
-       // Pass 1. Identify leading run of // comments and blank lines,
+       // Identify leading run of // comments and blank lines,
        // which must be followed by a blank line.
        // Also identify any //go:build comments.
        content, goBuild, sawBinaryOnly, err := parseFileHeader(content)
@@ -1509,44 +1533,42 @@ func (ctxt *Context) shouldBuild(content []byte, allTags map[string]bool) (shoul
                return false, false, err
        }
 
-       // Pass 2.  Process each +build line in the run.
-       p := content
-       shouldBuild = true
-       sawBuild := false
-       for len(p) > 0 {
-               line := p
-               if i := bytes.IndexByte(line, '\n'); i >= 0 {
-                       line, p = line[:i], p[i+1:]
-               } else {
-                       p = p[len(p):]
-               }
-               line = bytes.TrimSpace(line)
-               if !bytes.HasPrefix(line, bSlashSlash) {
-                       continue
+       // If //go:build line is present, it controls.
+       // Otherwise fall back to +build processing.
+       switch {
+       case goBuild != nil:
+               x, err := constraint.Parse(string(goBuild))
+               if err != nil {
+                       return false, false, fmt.Errorf("parsing //go:build line: %v", err)
                }
-               line = bytes.TrimSpace(line[len(bSlashSlash):])
-               if len(line) > 0 && line[0] == '+' {
-                       // Looks like a comment +line.
-                       f := strings.Fields(string(line))
-                       if f[0] == "+build" {
-                               sawBuild = true
-                               ok := false
-                               for _, tok := range f[1:] {
-                                       if ctxt.match(tok, allTags) {
-                                               ok = true
-                                       }
-                               }
-                               if !ok {
+               shouldBuild = ctxt.eval(x, allTags)
+
+       default:
+               shouldBuild = true
+               p := content
+               for len(p) > 0 {
+                       line := p
+                       if i := bytes.IndexByte(line, '\n'); i >= 0 {
+                               line, p = line[:i], p[i+1:]
+                       } else {
+                               p = p[len(p):]
+                       }
+                       line = bytes.TrimSpace(line)
+                       if !bytes.HasPrefix(line, bSlashSlash) || !bytes.Contains(line, bPlusBuild) {
+                               continue
+                       }
+                       text := string(line)
+                       if !constraint.IsPlusBuild(text) {
+                               continue
+                       }
+                       if x, err := constraint.Parse(text); err == nil {
+                               if !ctxt.eval(x, allTags) {
                                        shouldBuild = false
                                }
                        }
                }
        }
 
-       if goBuild != nil && !sawBuild {
-               return false, false, errGoBuildWithoutBuild
-       }
-
        return shouldBuild, sawBinaryOnly, nil
 }
 
@@ -1582,7 +1604,7 @@ Lines:
                }
 
                if !inSlashStar && isGoBuildComment(line) {
-                       if false && goBuild != nil { // enabled in Go 1.N
+                       if goBuild != nil {
                                return nil, nil, false, errMultipleGoBuild
                        }
                        goBuild = line
@@ -1651,7 +1673,7 @@ func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup)
                if len(cond) > 0 {
                        ok := false
                        for _, c := range cond {
-                               if ctxt.match(c, nil) {
+                               if ctxt.matchAuto(c, nil) {
                                        ok = true
                                        break
                                }
@@ -1833,50 +1855,44 @@ func splitQuoted(s string) (r []string, err error) {
        return args, err
 }
 
-// match reports whether the name is one of:
+// matchAuto interprets text as either a +build or //go:build expression (whichever works),
+// reporting whether the expression matches the build context.
+//
+// matchAuto is only used for testing of tag evaluation
+// and in #cgo lines, which accept either syntax.
+func (ctxt *Context) matchAuto(text string, allTags map[string]bool) bool {
+       if strings.ContainsAny(text, "&|()") {
+               text = "//go:build " + text
+       } else {
+               text = "// +build " + text
+       }
+       x, err := constraint.Parse(text)
+       if err != nil {
+               return false
+       }
+       return ctxt.eval(x, allTags)
+}
+
+func (ctxt *Context) eval(x constraint.Expr, allTags map[string]bool) bool {
+       return x.Eval(func(tag string) bool { return ctxt.matchTag(tag, allTags) })
+}
+
+// matchTag reports whether the name is one of:
 //
+//     cgo (if cgo is enabled)
 //     $GOOS
 //     $GOARCH
-//     cgo (if cgo is enabled)
-//     !cgo (if cgo is disabled)
 //     ctxt.Compiler
-//     !ctxt.Compiler
+//     linux (if GOOS = android)
+//     solaris (if GOOS = illumos)
 //     tag (if tag is listed in ctxt.BuildTags or ctxt.ReleaseTags)
-//     !tag (if tag is not listed in ctxt.BuildTags or ctxt.ReleaseTags)
-//     a comma-separated list of any of these
 //
-func (ctxt *Context) match(name string, allTags map[string]bool) bool {
-       if name == "" {
-               if allTags != nil {
-                       allTags[name] = true
-               }
-               return false
-       }
-       if i := strings.Index(name, ","); i >= 0 {
-               // comma-separated list
-               ok1 := ctxt.match(name[:i], allTags)
-               ok2 := ctxt.match(name[i+1:], allTags)
-               return ok1 && ok2
-       }
-       if strings.HasPrefix(name, "!!") { // bad syntax, reject always
-               return false
-       }
-       if strings.HasPrefix(name, "!") { // negation
-               return len(name) > 1 && !ctxt.match(name[1:], allTags)
-       }
-
+// It records all consulted tags in allTags.
+func (ctxt *Context) matchTag(name string, allTags map[string]bool) bool {
        if allTags != nil {
                allTags[name] = true
        }
 
-       // Tags must be letters, digits, underscores or dots.
-       // Unlike in Go identifiers, all digits are fine (e.g., "386").
-       for _, c := range name {
-               if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' {
-                       return false
-               }
-       }
-
        // special tags
        if ctxt.CgoEnabled && name == "cgo" {
                return true
@@ -1900,6 +1916,11 @@ func (ctxt *Context) match(name string, allTags map[string]bool) bool {
                        return true
                }
        }
+       for _, tag := range ctxt.ToolTags {
+               if tag == name {
+                       return true
+               }
+       }
        for _, tag := range ctxt.ReleaseTags {
                if tag == name {
                        return true
@@ -1948,10 +1969,10 @@ func (ctxt *Context) goodOSArchFile(name string, allTags map[string]bool) bool {
        }
        n := len(l)
        if n >= 2 && knownOS[l[n-2]] && knownArch[l[n-1]] {
-               return ctxt.match(l[n-1], allTags) && ctxt.match(l[n-2], allTags)
+               return ctxt.matchTag(l[n-1], allTags) && ctxt.matchTag(l[n-2], allTags)
        }
        if n >= 1 && (knownOS[l[n-1]] || knownArch[l[n-1]]) {
-               return ctxt.match(l[n-1], allTags)
+               return ctxt.matchTag(l[n-1], allTags)
        }
        return true
 }
index 1c0dc4692c9314945556dc6299b711c928dbd22d..a8f361aa660baf25a9f16f34daa528cbc474aa2c 100644 (file)
@@ -30,7 +30,7 @@ func TestMatch(t *testing.T) {
        match := func(tag string, want map[string]bool) {
                t.Helper()
                m := make(map[string]bool)
-               if !ctxt.match(tag, m) {
+               if !ctxt.matchAuto(tag, m) {
                        t.Errorf("%s context should match %s, does not", what, tag)
                }
                if !reflect.DeepEqual(m, want) {
@@ -40,7 +40,7 @@ func TestMatch(t *testing.T) {
        nomatch := func(tag string, want map[string]bool) {
                t.Helper()
                m := make(map[string]bool)
-               if ctxt.match(tag, m) {
+               if ctxt.matchAuto(tag, m) {
                        t.Errorf("%s context should NOT match %s, does", what, tag)
                }
                if !reflect.DeepEqual(m, want) {
@@ -104,7 +104,8 @@ func TestEmptyFolderImport(t *testing.T) {
 }
 
 func TestMultiplePackageImport(t *testing.T) {
-       _, err := Import(".", "testdata/multi", 0)
+       pkg, err := Import(".", "testdata/multi", 0)
+
        mpe, ok := err.(*MultiplePackageError)
        if !ok {
                t.Fatal(`Import("testdata/multi") did not return MultiplePackageError.`)
@@ -115,7 +116,20 @@ func TestMultiplePackageImport(t *testing.T) {
                Files:    []string{"file.go", "file_appengine.go"},
        }
        if !reflect.DeepEqual(mpe, want) {
-               t.Errorf("got %#v; want %#v", mpe, want)
+               t.Errorf("err = %#v; want %#v", mpe, want)
+       }
+
+       // TODO(#45999): Since the name is ambiguous, pkg.Name should be left empty.
+       if wantName := "main"; pkg.Name != wantName {
+               t.Errorf("pkg.Name = %q; want %q", pkg.Name, wantName)
+       }
+
+       if wantGoFiles := []string{"file.go", "file_appengine.go"}; !reflect.DeepEqual(pkg.GoFiles, wantGoFiles) {
+               t.Errorf("pkg.GoFiles = %q; want %q", pkg.GoFiles, wantGoFiles)
+       }
+
+       if wantInvalidFiles := []string{"file_appengine.go"}; !reflect.DeepEqual(pkg.InvalidGoFiles, wantInvalidFiles) {
+               t.Errorf("pkg.InvalidGoFiles = %q; want %q", pkg.InvalidGoFiles, wantInvalidFiles)
        }
 }
 
@@ -154,6 +168,13 @@ var shouldBuildTests = []struct {
                tags:        map[string]bool{"yes": true},
                shouldBuild: true,
        },
+       {
+               name: "Yes2",
+               content: "//go:build yes\n" +
+                       "package main\n",
+               tags:        map[string]bool{"yes": true},
+               shouldBuild: true,
+       },
        {
                name: "Or",
                content: "// +build no yes\n\n" +
@@ -161,6 +182,13 @@ var shouldBuildTests = []struct {
                tags:        map[string]bool{"yes": true, "no": true},
                shouldBuild: true,
        },
+       {
+               name: "Or2",
+               content: "//go:build no || yes\n" +
+                       "package main\n",
+               tags:        map[string]bool{"yes": true, "no": true},
+               shouldBuild: true,
+       },
        {
                name: "And",
                content: "// +build no,yes\n\n" +
@@ -168,6 +196,13 @@ var shouldBuildTests = []struct {
                tags:        map[string]bool{"yes": true, "no": true},
                shouldBuild: false,
        },
+       {
+               name: "And2",
+               content: "//go:build no && yes\n" +
+                       "package main\n",
+               tags:        map[string]bool{"yes": true, "no": true},
+               shouldBuild: false,
+       },
        {
                name: "Cgo",
                content: "// +build cgo\n\n" +
@@ -178,12 +213,23 @@ var shouldBuildTests = []struct {
                tags:        map[string]bool{"cgo": true},
                shouldBuild: false,
        },
+       {
+               name: "Cgo2",
+               content: "//go:build cgo\n" +
+                       "// Copyright The Go Authors.\n\n" +
+                       "// This package implements parsing of tags like\n" +
+                       "// +build tag1\n" +
+                       "package build",
+               tags:        map[string]bool{"cgo": true},
+               shouldBuild: false,
+       },
        {
                name: "AfterPackage",
                content: "// Copyright The Go Authors.\n\n" +
                        "package build\n\n" +
                        "// shouldBuild checks tags given by lines of the form\n" +
                        "// +build tag\n" +
+                       "//go:build tag\n" +
                        "func shouldBuild(content []byte)\n",
                tags:        map[string]bool{},
                shouldBuild: true,
@@ -195,6 +241,13 @@ var shouldBuildTests = []struct {
                tags:        map[string]bool{},
                shouldBuild: true,
        },
+       {
+               name: "TooClose2",
+               content: "//go:build yes\n" +
+                       "package main\n",
+               tags:        map[string]bool{"yes": true},
+               shouldBuild: true,
+       },
        {
                name: "TooCloseNo",
                content: "// +build no\n" +
@@ -202,6 +255,13 @@ var shouldBuildTests = []struct {
                tags:        map[string]bool{},
                shouldBuild: true,
        },
+       {
+               name: "TooCloseNo2",
+               content: "//go:build no\n" +
+                       "package main\n",
+               tags:        map[string]bool{"no": true},
+               shouldBuild: false,
+       },
        {
                name: "BinaryOnly",
                content: "//go:binary-only-package\n" +
@@ -212,41 +272,30 @@ var shouldBuildTests = []struct {
                shouldBuild: true,
        },
        {
-               name: "ValidGoBuild",
-               content: "// +build yes\n\n" +
+               name: "BinaryOnly2",
+               content: "//go:binary-only-package\n" +
                        "//go:build no\n" +
                        "package main\n",
-               tags:        map[string]bool{"yes": true},
-               shouldBuild: true,
-       },
-       {
-               name: "MissingBuild",
-               content: "//go:build no\n" +
-                       "package main\n",
-               tags:        map[string]bool{},
+               tags:        map[string]bool{"no": true},
+               binaryOnly:  true,
                shouldBuild: false,
-               err:         errGoBuildWithoutBuild,
        },
        {
-               name: "MissingBuild2",
-               content: "/* */\n" +
-                       "// +build yes\n\n" +
+               name: "ValidGoBuild",
+               content: "// +build yes\n\n" +
                        "//go:build no\n" +
                        "package main\n",
-               tags:        map[string]bool{},
+               tags:        map[string]bool{"no": true},
                shouldBuild: false,
-               err:         errGoBuildWithoutBuild,
        },
        {
                name: "MissingBuild2",
-               content: "/*\n" +
+               content: "/* */\n" +
                        "// +build yes\n\n" +
-                       "*/\n" +
                        "//go:build no\n" +
                        "package main\n",
-               tags:        map[string]bool{},
+               tags:        map[string]bool{"no": true},
                shouldBuild: false,
-               err:         errGoBuildWithoutBuild,
        },
        {
                name: "Comment1",
@@ -264,9 +313,8 @@ var shouldBuildTests = []struct {
                        "*/\n\n" +
                        "//go:build no\n" +
                        "package main\n",
-               tags:        map[string]bool{},
+               tags:        map[string]bool{"no": true},
                shouldBuild: false,
-               err:         errGoBuildWithoutBuild,
        },
        {
                name: "Comment3",
@@ -275,9 +323,8 @@ var shouldBuildTests = []struct {
                        "*/\n\n" +
                        "//go:build no\n" +
                        "package main\n",
-               tags:        map[string]bool{},
+               tags:        map[string]bool{"no": true},
                shouldBuild: false,
-               err:         errGoBuildWithoutBuild,
        },
        {
                name: "Comment4",
@@ -291,9 +338,8 @@ var shouldBuildTests = []struct {
                content: "/**/\n" +
                        "//go:build no\n" +
                        "package main\n",
-               tags:        map[string]bool{},
+               tags:        map[string]bool{"no": true},
                shouldBuild: false,
-               err:         errGoBuildWithoutBuild,
        },
 }
 
@@ -456,11 +502,7 @@ func TestImportDirNotExist(t *testing.T) {
        testenv.MustHaveGoBuild(t) // really must just have source
        ctxt := Default
 
-       emptyDir, err := os.MkdirTemp("", t.Name())
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(emptyDir)
+       emptyDir := t.TempDir()
 
        ctxt.GOPATH = emptyDir
        ctxt.Dir = emptyDir
@@ -513,8 +555,7 @@ func TestImportDirNotExist(t *testing.T) {
 func TestImportVendor(t *testing.T) {
        testenv.MustHaveGoBuild(t) // really must just have source
 
-       defer os.Setenv("GO111MODULE", os.Getenv("GO111MODULE"))
-       os.Setenv("GO111MODULE", "off")
+       t.Setenv("GO111MODULE", "off")
 
        ctxt := Default
        wd, err := os.Getwd()
@@ -535,8 +576,7 @@ func TestImportVendor(t *testing.T) {
 func TestImportVendorFailure(t *testing.T) {
        testenv.MustHaveGoBuild(t) // really must just have source
 
-       defer os.Setenv("GO111MODULE", os.Getenv("GO111MODULE"))
-       os.Setenv("GO111MODULE", "off")
+       t.Setenv("GO111MODULE", "off")
 
        ctxt := Default
        wd, err := os.Getwd()
@@ -558,8 +598,7 @@ func TestImportVendorFailure(t *testing.T) {
 func TestImportVendorParentFailure(t *testing.T) {
        testenv.MustHaveGoBuild(t) // really must just have source
 
-       defer os.Setenv("GO111MODULE", os.Getenv("GO111MODULE"))
-       os.Setenv("GO111MODULE", "off")
+       t.Setenv("GO111MODULE", "off")
 
        ctxt := Default
        wd, err := os.Getwd()
@@ -589,16 +628,11 @@ func TestImportPackageOutsideModule(t *testing.T) {
 
        // Disable module fetching for this test so that 'go list' fails quickly
        // without trying to find the latest version of a module.
-       defer os.Setenv("GOPROXY", os.Getenv("GOPROXY"))
-       os.Setenv("GOPROXY", "off")
+       t.Setenv("GOPROXY", "off")
 
        // Create a GOPATH in a temporary directory. We don't use testdata
        // because it's in GOROOT, which interferes with the module heuristic.
-       gopath, err := os.MkdirTemp("", "gobuild-notmodule")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(gopath)
+       gopath := t.TempDir()
        if err := os.MkdirAll(filepath.Join(gopath, "src/example.com/p"), 0777); err != nil {
                t.Fatal(err)
        }
@@ -606,10 +640,8 @@ func TestImportPackageOutsideModule(t *testing.T) {
                t.Fatal(err)
        }
 
-       defer os.Setenv("GO111MODULE", os.Getenv("GO111MODULE"))
-       os.Setenv("GO111MODULE", "on")
-       defer os.Setenv("GOPATH", os.Getenv("GOPATH"))
-       os.Setenv("GOPATH", gopath)
+       t.Setenv("GO111MODULE", "on")
+       t.Setenv("GOPATH", gopath)
        ctxt := Default
        ctxt.GOPATH = gopath
        ctxt.Dir = filepath.Join(gopath, "src/example.com/p")
@@ -658,26 +690,19 @@ func TestIssue23594(t *testing.T) {
 // Verifies golang.org/issue/34752.
 func TestMissingImportErrorRepetition(t *testing.T) {
        testenv.MustHaveGoBuild(t) // need 'go list' internally
-       tmp, err := os.MkdirTemp("", "")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(tmp)
+       tmp := t.TempDir()
        if err := os.WriteFile(filepath.Join(tmp, "go.mod"), []byte("module m"), 0666); err != nil {
                t.Fatal(err)
        }
-       defer os.Setenv("GO111MODULE", os.Getenv("GO111MODULE"))
-       os.Setenv("GO111MODULE", "on")
-       defer os.Setenv("GOPROXY", os.Getenv("GOPROXY"))
-       os.Setenv("GOPROXY", "off")
-       defer os.Setenv("GONOPROXY", os.Getenv("GONOPROXY"))
-       os.Setenv("GONOPROXY", "none")
+       t.Setenv("GO111MODULE", "on")
+       t.Setenv("GOPROXY", "off")
+       t.Setenv("GONOPROXY", "none")
 
        ctxt := Default
        ctxt.Dir = tmp
 
        pkgPath := "example.com/hello"
-       _, err = ctxt.Import(pkgPath, tmp, FindOnly)
+       _, err := ctxt.Import(pkgPath, tmp, FindOnly)
        if err == nil {
                t.Fatal("unexpected success")
        }
index 3b278702f808b3346e2734ae7aa91480d542825e..957eb9b5279b4f173dec48661322944fe1c23891 100644 (file)
@@ -355,8 +355,8 @@ func IsPlusBuild(line string) bool {
        return ok
 }
 
-// splitGoBuild splits apart the leading //go:build prefix in line from the build expression itself.
-// It returns "", false if the input is not a //go:build line or if the input contains multiple lines.
+// splitPlusBuild splits apart the leading // +build prefix in line from the build expression itself.
+// It returns "", false if the input is not a // +build line or if the input contains multiple lines.
 func splitPlusBuild(line string) (expr string, ok bool) {
        // A single trailing newline is OK; otherwise multiple lines are not.
        if len(line) > 0 && line[len(line)-1] == '\n' {
@@ -426,6 +426,9 @@ func parsePlusBuildExpr(text string) Expr {
                        x = or(x, y)
                }
        }
+       if x == nil {
+               x = tag("ignore")
+       }
        return x
 }
 
index 4979f8b5f28978e8e891b818e5df709b3eccf17a..15d189012efb7d91bf4c7b8bf9e9d93910a2e282 100644 (file)
@@ -216,6 +216,7 @@ var parsePlusBuildExprTests = []struct {
        {"!!x", tag("ignore")},
        {"!x", not(tag("x"))},
        {"!", tag("ignore")},
+       {"", tag("ignore")},
 }
 
 func TestParsePlusBuildExpr(t *testing.T) {
@@ -232,19 +233,22 @@ func TestParsePlusBuildExpr(t *testing.T) {
 var constraintTests = []struct {
        in  string
        x   Expr
-       err error
+       err string
 }{
-       {"//+build x y", or(tag("x"), tag("y")), nil},
-       {"// +build x y \n", or(tag("x"), tag("y")), nil},
-       {"// +build x y \n ", nil, errNotConstraint},
-       {"// +build x y \nmore", nil, errNotConstraint},
-       {" //+build x y", nil, errNotConstraint},
+       {"//+build !", tag("ignore"), ""},
+       {"//+build", tag("ignore"), ""},
+       {"//+build x y", or(tag("x"), tag("y")), ""},
+       {"// +build x y \n", or(tag("x"), tag("y")), ""},
+       {"// +build x y \n ", nil, "not a build constraint"},
+       {"// +build x y \nmore", nil, "not a build constraint"},
+       {" //+build x y", nil, "not a build constraint"},
 
-       {"//go:build x && y", and(tag("x"), tag("y")), nil},
-       {"//go:build x && y\n", and(tag("x"), tag("y")), nil},
-       {"//go:build x && y\n ", nil, errNotConstraint},
-       {"//go:build x && y\nmore", nil, errNotConstraint},
-       {" //go:build x && y", nil, errNotConstraint},
+       {"//go:build x && y", and(tag("x"), tag("y")), ""},
+       {"//go:build x && y\n", and(tag("x"), tag("y")), ""},
+       {"//go:build x && y\n ", nil, "not a build constraint"},
+       {"//go:build x && y\nmore", nil, "not a build constraint"},
+       {" //go:build x && y", nil, "not a build constraint"},
+       {"//go:build\n", nil, "unexpected end of expression"},
 }
 
 func TestParse(t *testing.T) {
@@ -252,14 +256,14 @@ func TestParse(t *testing.T) {
                t.Run(fmt.Sprint(i), func(t *testing.T) {
                        x, err := Parse(tt.in)
                        if err != nil {
-                               if tt.err == nil {
+                               if tt.err == "" {
                                        t.Errorf("Constraint(%q): unexpected error: %v", tt.in, err)
-                               } else if tt.err != err {
+                               } else if !strings.Contains(err.Error(), tt.err) {
                                        t.Errorf("Constraint(%q): error %v, want %v", tt.in, err, tt.err)
                                }
                                return
                        }
-                       if tt.err != nil {
+                       if tt.err != "" {
                                t.Errorf("Constraint(%q) = %v, want error %v", tt.in, x, tt.err)
                                return
                        }
index f0bbe4e876544905cf9698822900b11168f91011..e9b4e71067e7dba71b7b73a86bd458024df63b97 100644 (file)
@@ -71,14 +71,19 @@ var depsRules = `
        # No dependencies allowed for any of these packages.
        NONE
        < container/list, container/ring,
-         internal/cfg, internal/cpu,
+         internal/cfg, internal/cpu, internal/goexperiment,
          internal/goversion, internal/nettrace,
          unicode/utf8, unicode/utf16, unicode,
          unsafe;
 
+       # These packages depend only on unsafe.
+       unsafe
+       < internal/abi;
+
        # RUNTIME is the core runtime group of packages, all of them very light-weight.
-       internal/cpu, unsafe
+       internal/abi, internal/cpu, internal/goexperiment, unsafe
        < internal/bytealg
+       < internal/itoa
        < internal/unsafeheader
        < runtime/internal/sys
        < runtime/internal/atomic
@@ -273,9 +278,13 @@ var depsRules = `
        < go/token
        < go/scanner
        < go/ast
+       < go/internal/typeparams
        < go/parser;
 
-       go/parser, text/tabwriter
+       FMT
+       < go/build/constraint;
+
+       go/build/constraint, go/parser, text/tabwriter
        < go/printer
        < go/format;
 
@@ -285,13 +294,13 @@ var depsRules = `
        math/big, go/token
        < go/constant;
 
-       container/heap, go/constant, go/parser
+       container/heap, go/constant, go/parser, regexp
        < go/types;
 
-       FMT
-       < go/build/constraint;
+       FMT, internal/goexperiment
+       < internal/buildcfg;
 
-       go/doc, go/parser, internal/goroot, internal/goversion
+       go/build/constraint, go/doc, go/parser, internal/buildcfg, internal/goroot, internal/goversion
        < go/build;
 
        DEBUG, go/build, go/types, text/scanner
@@ -383,6 +392,9 @@ var depsRules = `
        < crypto
        < crypto/subtle
        < crypto/internal/subtle
+       < crypto/elliptic/internal/fiat
+       < crypto/ed25519/internal/edwards25519/field
+       < crypto/ed25519/internal/edwards25519
        < crypto/cipher
        < crypto/aes, crypto/des, crypto/hmac, crypto/md5, crypto/rc4,
          crypto/sha1, crypto/sha256, crypto/sha512
@@ -394,7 +406,6 @@ var depsRules = `
        CRYPTO, FMT, math/big
        < crypto/rand
        < crypto/internal/randutil
-       < crypto/ed25519/internal/edwards25519
        < crypto/ed25519
        < encoding/asn1
        < golang.org/x/crypto/cryptobyte/asn1
@@ -429,7 +440,8 @@ var depsRules = `
        # HTTP, King of Dependencies.
 
        FMT
-       < golang.org/x/net/http2/hpack, net/http/internal;
+       < golang.org/x/net/http2/hpack
+       < net/http/internal, net/http/internal/ascii, net/http/internal/testcert;
 
        FMT, NET, container/list, encoding/binary, log
        < golang.org/x/text/transform
@@ -447,6 +459,8 @@ var depsRules = `
        golang.org/x/net/http/httpproxy,
        golang.org/x/net/http2/hpack,
        net/http/internal,
+       net/http/internal/ascii,
+       net/http/internal/testcert,
        net/http/httptrace,
        mime/multipart,
        log
@@ -457,7 +471,7 @@ var depsRules = `
        encoding/json, net/http
        < expvar;
 
-       net/http
+       net/http, net/http/internal/ascii
        < net/http/cookiejar, net/http/httputil;
 
        net/http, flag
@@ -494,7 +508,7 @@ var depsRules = `
        FMT, flag, math/rand
        < testing/quick;
 
-       FMT, flag, runtime/debug, runtime/trace, internal/sysinfo
+       FMT, flag, runtime/debug, runtime/trace, internal/sysinfo, math/rand
        < testing;
 
        internal/testlog, runtime/pprof, regexp
index 2c6f0a83bea9713837f17be50fda7d8a354a6002..778b4f40f7c5775c2dc1418b6822bc1c59d78251 100644 (file)
@@ -59,7 +59,7 @@
 //
 // A build constraint, also known as a build tag, is a line comment that begins
 //
-//     // +build
+//     //go:build
 //
 // that lists the conditions under which a file should be included in the
 // package. Build constraints may also be part of a file's name
index 3025cd5681591f0c2f0aaee701786be344dcdcc5..e16e186e0df9662ee420c51d2ad41eaced1f6a31 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build gc
 // +build gc
 
 package build
index c6aac9aa1bc2d6fb5eec8749a220f4b69ced5036..c8ec7041fb3653cd71ce0799925851303fd50868 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build gccgo
 // +build gccgo
 
 package build
index aa7c6ee59eb6d3350e262b3bb6f928646d40d10c..b98c7938a855993454b5e374ff99d9b9ebd04b95 100644 (file)
@@ -6,6 +6,7 @@ package build
 
 import (
        "bufio"
+       "bytes"
        "errors"
        "fmt"
        "go/ast"
@@ -28,9 +29,19 @@ type importReader struct {
        pos  token.Position
 }
 
+var bom = []byte{0xef, 0xbb, 0xbf}
+
 func newImportReader(name string, r io.Reader) *importReader {
+       b := bufio.NewReader(r)
+       // Remove leading UTF-8 BOM.
+       // Per https://golang.org/ref/spec#Source_code_representation:
+       // a compiler may ignore a UTF-8-encoded byte order mark (U+FEFF)
+       // if it is the first Unicode code point in the source text.
+       if leadingBytes, err := b.Peek(3); err == nil && bytes.Equal(leadingBytes, bom) {
+               b.Discard(3)
+       }
        return &importReader{
-               b: bufio.NewReader(r),
+               b: b,
                pos: token.Position{
                        Filename: name,
                        Line:     1,
index 32e6bae008841bb4db5b7fb456729f3e6267828e..1e5e1c2de2e6d110b539058fe64711c97547ee89 100644 (file)
@@ -66,6 +66,10 @@ var readGoInfoTests = []readTest{
                `,
                "",
        },
+       {
+               "\ufeff𝔻" + `package p; import "x";ℙvar x = 1`,
+               "",
+       },
 }
 
 var readCommentsTests = []readTest{
@@ -81,6 +85,10 @@ var readCommentsTests = []readTest{
                `ℙpackage p; import . "x"`,
                "",
        },
+       {
+               "\ufeff𝔻" + `ℙpackage p; import . "x"`,
+               "",
+       },
        {
                `// foo
 
@@ -90,6 +98,19 @@ var readCommentsTests = []readTest{
 
                /*/ zot */
 
+               // asdf
+               ℙHello, world`,
+               "",
+       },
+       {
+               "\ufeff𝔻" + `// foo
+
+               /* bar */
+
+               /* quux */ // baz
+
+               /*/ zot */
+
                // asdf
                ℙHello, world`,
                "",
@@ -107,6 +128,11 @@ func testRead(t *testing.T, tests []readTest, read func(io.Reader) ([]byte, erro
                        in = tt.in[:j] + tt.in[j+len("ℙ"):]
                        testOut = tt.in[:j]
                }
+               d := strings.Index(tt.in, "𝔻")
+               if d >= 0 {
+                       in = in[:d] + in[d+len("𝔻"):]
+                       testOut = testOut[d+len("𝔻"):]
+               }
                r := strings.NewReader(in)
                buf, err := read(r)
                if err != nil {
@@ -264,6 +290,12 @@ var readEmbedTests = []struct {
                 test:3:14:y
                 test:3:16:z`,
        },
+       {
+               "\ufeffpackage p\nimport \"embed\"\n//go:embed x y z\nvar files embed.FS",
+               `test:3:12:x
+                test:3:14:y
+                test:3:16:z`,
+       },
        {
                "package p\nimport \"embed\"\nvar s = \"/*\"\n//go:embed x\nvar files embed.FS",
                `test:4:12:x`,
@@ -292,6 +324,10 @@ var readEmbedTests = []struct {
                "package p\n//go:embed x y z\nvar files embed.FS", // no import, no scan
                "",
        },
+       {
+               "\ufeffpackage p\n//go:embed x y z\nvar files embed.FS", // no import, no scan
+               "",
+       },
 }
 
 func TestReadEmbed(t *testing.T) {
index 4f5e96c044d3c740340f4727148beece9747c10a..cb7d87673672102dff2cef7a16245e876ba4d7fd 100644 (file)
@@ -8,4 +8,4 @@ package build
 // Do not remove from this list, as these are used for go/build filename matching.
 
 const goosList = "aix android darwin dragonfly freebsd hurd illumos ios js linux nacl netbsd openbsd plan9 solaris windows zos "
-const goarchList = "386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le ppc riscv riscv64 s390 s390x sparc sparc64 wasm alpha m68k nios2 sh shbe "
+const goarchList = "386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 ppc64le loong64 mips mipsle mips64 mips64le mips64p32 mips64p32le ppc riscv riscv64 s390 s390x sparc sparc64 wasm alpha m68k nios2 sh shbe "
index 46414423f2d122f0883e347bb3c84d1d1cf99801..78cb3f896f535cd7fddd64a2f2b34e03f1ec81dd 100644 (file)
@@ -17,6 +17,7 @@ import (
        "go/token"
        "math"
        "math/big"
+       "math/bits"
        "strconv"
        "strings"
        "sync"
@@ -71,6 +72,17 @@ const prec = 512
 //           too large (incl. infinity), that could be recorded in unknownVal.
 //           See also #20583 and #42695 for use cases.
 
+// Representation of values:
+//
+// Values of Int and Float Kind have two different representations each: int64Val
+// and intVal, and ratVal and floatVal. When possible, the "smaller", respectively
+// more precise (for Floats) representation is chosen. However, once a Float value
+// is represented as a floatVal, any subsequent results remain floatVals (unless
+// explicitly converted); i.e., no attempt is made to convert a floatVal back into
+// a ratVal. The reasoning is that all representations but floatVal are mathematically
+// exact, but once that precision is lost (by moving to floatVal), moving back to
+// a different representation implies a precision that's not actually there.
+
 type (
        unknownVal struct{}
        boolVal    bool
@@ -262,14 +274,8 @@ func i64tor(x int64Val) ratVal   { return ratVal{newRat().SetInt64(int64(x))} }
 func i64tof(x int64Val) floatVal { return floatVal{newFloat().SetInt64(int64(x))} }
 func itor(x intVal) ratVal       { return ratVal{newRat().SetInt(x.val)} }
 func itof(x intVal) floatVal     { return floatVal{newFloat().SetInt(x.val)} }
-
-func rtof(x ratVal) floatVal {
-       a := newFloat().SetInt(x.val.Num())
-       b := newFloat().SetInt(x.val.Denom())
-       return floatVal{a.Quo(a, b)}
-}
-
-func vtoc(x Value) complexVal { return complexVal{x, int64Val(0)} }
+func rtof(x ratVal) floatVal     { return floatVal{newFloat().SetRat(x.val)} }
+func vtoc(x Value) complexVal    { return complexVal{x, int64Val(0)} }
 
 func makeInt(x *big.Int) Value {
        if x.IsInt64() {
@@ -278,21 +284,15 @@ func makeInt(x *big.Int) Value {
        return intVal{x}
 }
 
-// Permit fractions with component sizes up to maxExp
-// before switching to using floating-point numbers.
-const maxExp = 4 << 10
-
 func makeRat(x *big.Rat) Value {
        a := x.Num()
        b := x.Denom()
-       if a.BitLen() < maxExp && b.BitLen() < maxExp {
+       if smallInt(a) && smallInt(b) {
                // ok to remain fraction
                return ratVal{x}
        }
        // components too large => switch to float
-       fa := newFloat().SetInt(a)
-       fb := newFloat().SetInt(b)
-       return floatVal{fa.Quo(fa, fb)}
+       return floatVal{newFloat().SetRat(x)}
 }
 
 var floatVal0 = floatVal{newFloat()}
@@ -305,6 +305,9 @@ func makeFloat(x *big.Float) Value {
        if x.IsInf() {
                return unknownVal{}
        }
+       // No attempt is made to "go back" to ratVal, even if possible,
+       // to avoid providing the illusion of a mathematically exact
+       // representation.
        return floatVal{x}
 }
 
@@ -317,7 +320,7 @@ func makeComplex(re, im Value) Value {
 
 func makeFloatFromLiteral(lit string) Value {
        if f, ok := newFloat().SetString(lit); ok {
-               if smallRat(f) {
+               if smallFloat(f) {
                        // ok to use rationals
                        if f.Sign() == 0 {
                                // Issue 20228: If the float underflowed to zero, parse just "0".
@@ -336,14 +339,34 @@ func makeFloatFromLiteral(lit string) Value {
        return nil
 }
 
-// smallRat reports whether x would lead to "reasonably"-sized fraction
+// Permit fractions with component sizes up to maxExp
+// before switching to using floating-point numbers.
+const maxExp = 4 << 10
+
+// smallInt reports whether x would lead to "reasonably"-sized fraction
+// if converted to a *big.Rat.
+func smallInt(x *big.Int) bool {
+       return x.BitLen() < maxExp
+}
+
+// smallFloat64 reports whether x would lead to "reasonably"-sized fraction
 // if converted to a *big.Rat.
-func smallRat(x *big.Float) bool {
-       if !x.IsInf() {
-               e := x.MantExp(nil)
-               return -maxExp < e && e < maxExp
+func smallFloat64(x float64) bool {
+       if math.IsInf(x, 0) {
+               return false
+       }
+       _, e := math.Frexp(x)
+       return -maxExp < e && e < maxExp
+}
+
+// smallFloat reports whether x would lead to "reasonably"-sized fraction
+// if converted to a *big.Rat.
+func smallFloat(x *big.Float) bool {
+       if x.IsInf() {
+               return false
        }
-       return false
+       e := x.MantExp(nil)
+       return -maxExp < e && e < maxExp
 }
 
 // ----------------------------------------------------------------------------
@@ -376,7 +399,10 @@ func MakeFloat64(x float64) Value {
        if math.IsInf(x, 0) || math.IsNaN(x) {
                return unknownVal{}
        }
-       return ratVal{newRat().SetFloat64(x + 0)} // convert -0 to 0
+       if smallFloat64(x) {
+               return ratVal{newRat().SetFloat64(x + 0)} // convert -0 to 0
+       }
+       return floatVal{newFloat().SetFloat64(x + 0)}
 }
 
 // MakeFromLiteral returns the corresponding integer, floating-point,
@@ -607,7 +633,11 @@ func Make(x interface{}) Value {
 func BitLen(x Value) int {
        switch x := x.(type) {
        case int64Val:
-               return i64toi(x).val.BitLen()
+               u := uint64(x)
+               if x < 0 {
+                       u = uint64(-x)
+               }
+               return 64 - bits.LeadingZeros64(u)
        case intVal:
                return x.val.BitLen()
        case unknownVal:
@@ -728,7 +758,7 @@ func Num(x Value) Value {
        case ratVal:
                return makeInt(x.val.Num())
        case floatVal:
-               if smallRat(x.val) {
+               if smallFloat(x.val) {
                        r, _ := x.val.Rat(nil)
                        return makeInt(r.Num())
                }
@@ -750,7 +780,7 @@ func Denom(x Value) Value {
        case ratVal:
                return makeInt(x.val.Denom())
        case floatVal:
-               if smallRat(x.val) {
+               if smallFloat(x.val) {
                        r, _ := x.val.Rat(nil)
                        return makeInt(r.Denom())
                }
@@ -823,7 +853,7 @@ func ToInt(x Value) Value {
                // avoid creation of huge integers
                // (Existing tests require permitting exponents of at least 1024;
                // allow any value that would also be permissible as a fraction.)
-               if smallRat(x.val) {
+               if smallFloat(x.val) {
                        i := newInt()
                        if _, acc := x.val.Int(i); acc == big.Exact {
                                return makeInt(i)
@@ -866,14 +896,16 @@ func ToInt(x Value) Value {
 func ToFloat(x Value) Value {
        switch x := x.(type) {
        case int64Val:
-               return i64tof(x)
+               return i64tor(x) // x is always a small int
        case intVal:
+               if smallInt(x.val) {
+                       return itor(x)
+               }
                return itof(x)
        case ratVal, floatVal:
                return x
        case complexVal:
-               if im := ToInt(x.im); im.Kind() == Int && Sign(im) == 0 {
-                       // imaginary component is 0
+               if Sign(x.im) == 0 {
                        return ToFloat(x.re)
                }
        }
@@ -884,13 +916,7 @@ func ToFloat(x Value) Value {
 // Otherwise it returns an Unknown.
 func ToComplex(x Value) Value {
        switch x := x.(type) {
-       case int64Val:
-               return vtoc(i64tof(x))
-       case intVal:
-               return vtoc(itof(x))
-       case ratVal:
-               return vtoc(x)
-       case floatVal:
+       case int64Val, intVal, ratVal, floatVal:
                return vtoc(x)
        case complexVal:
                return x
@@ -1009,59 +1035,45 @@ func ord(x Value) int {
 // or invalid (say, nil) both results are that value.
 //
 func match(x, y Value) (_, _ Value) {
-       if ord(x) > ord(y) {
-               y, x = match(y, x)
-               return x, y
+       switch ox, oy := ord(x), ord(y); {
+       case ox < oy:
+               x, y = match0(x, y)
+       case ox > oy:
+               y, x = match0(y, x)
        }
-       // ord(x) <= ord(y)
-
-       switch x := x.(type) {
-       case boolVal, *stringVal, complexVal:
-               return x, y
+       return x, y
+}
 
-       case int64Val:
-               switch y := y.(type) {
-               case int64Val:
-                       return x, y
-               case intVal:
-                       return i64toi(x), y
-               case ratVal:
-                       return i64tor(x), y
-               case floatVal:
-                       return i64tof(x), y
-               case complexVal:
-                       return vtoc(x), y
-               }
+// match0 must only be called by match.
+// Invariant: ord(x) < ord(y)
+func match0(x, y Value) (_, _ Value) {
+       // Prefer to return the original x and y arguments when possible,
+       // to avoid unnecessary heap allocations.
 
+       switch y.(type) {
        case intVal:
-               switch y := y.(type) {
-               case intVal:
-                       return x, y
-               case ratVal:
-                       return itor(x), y
-               case floatVal:
-                       return itof(x), y
-               case complexVal:
-                       return vtoc(x), y
+               switch x1 := x.(type) {
+               case int64Val:
+                       return i64toi(x1), y
                }
-
        case ratVal:
-               switch y := y.(type) {
-               case ratVal:
-                       return x, y
-               case floatVal:
-                       return rtof(x), y
-               case complexVal:
-                       return vtoc(x), y
+               switch x1 := x.(type) {
+               case int64Val:
+                       return i64tor(x1), y
+               case intVal:
+                       return itor(x1), y
                }
-
        case floatVal:
-               switch y := y.(type) {
-               case floatVal:
-                       return x, y
-               case complexVal:
-                       return vtoc(x), y
+               switch x1 := x.(type) {
+               case int64Val:
+                       return i64tof(x1), y
+               case intVal:
+                       return itof(x1), y
+               case ratVal:
+                       return rtof(x1), y
                }
+       case complexVal:
+               return vtoc(x), y
        }
 
        // force unknown and invalid values into "x position" in callers of match
index 286677407d98d832a1fbf1effb5db019ae39410b..91ad0b0c2b9d998a2a28feb2827d8b118cb56124 100644 (file)
@@ -706,3 +706,24 @@ func BenchmarkStringAdd(b *testing.B) {
                })
        }
 }
+
+var bitLenTests = []struct {
+       val  int64
+       want int
+}{
+       {0, 0},
+       {1, 1},
+       {-16, 5},
+       {1 << 61, 62},
+       {1 << 62, 63},
+       {-1 << 62, 63},
+       {-1 << 63, 64},
+}
+
+func TestBitLen(t *testing.T) {
+       for _, test := range bitLenTests {
+               if got := BitLen(MakeInt64(test.val)); got != test.want {
+                       t.Errorf("%v: got %v, want %v", test.val, got, test.want)
+               }
+       }
+}
index 125fd530b133d73c9f805c0041077ba5842a732a..274000cecb7a4b194193cbe2f87e7a1d5753f867 100644 (file)
@@ -237,7 +237,10 @@ func playExample(file *ast.File, f *ast.FuncDecl) *ast.File {
                                }
                        }
 
-                       ast.Inspect(d.Body, inspectFunc)
+                       // Functions might not have a body. See #42706.
+                       if d.Body != nil {
+                               ast.Inspect(d.Body, inspectFunc)
+                       }
                case *ast.GenDecl:
                        for _, spec := range d.Specs {
                                switch s := spec.(type) {
index 7c96f0300a8fb5b0622debf805728f21a7ca3c2f..cf1b702549e5242e57d60e4998873c558d5fed72 100644 (file)
@@ -352,6 +352,25 @@ func main() {
 }
 `
 
+const exampleWholeFileExternalFunction = `package foo_test
+
+func foo(int)
+
+func Example() {
+       foo(42)
+       // Output:
+}
+`
+
+const exampleWholeFileExternalFunctionOutput = `package main
+
+func foo(int)
+
+func main() {
+       foo(42)
+}
+`
+
 var exampleWholeFileTestCases = []struct {
        Title, Source, Play, Output string
 }{
@@ -367,6 +386,12 @@ var exampleWholeFileTestCases = []struct {
                exampleWholeFileFunctionOutput,
                "Hello, world!\n",
        },
+       {
+               "ExternalFunction",
+               exampleWholeFileExternalFunction,
+               exampleWholeFileExternalFunctionOutput,
+               "",
+       },
 }
 
 func TestExamplesWholeFile(t *testing.T) {
index fe26a0ea8426950cd4fea7100d181099ace14dfc..28cb84f91da8f0436684072703ad84c5ce231210 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 /*
index 27f4c74cdf9181f73c74ab7f75a9d2ee5d0d23af..6cc0278b79b696aad583f35539518d384124f7bc 100644 (file)
@@ -151,6 +151,10 @@ var tests = []string{
        // erroneous programs
        "ERROR1 + 2 +",
        "ERRORx :=  0",
+
+       // build comments
+       "// copyright\n\n//go:build x\n\npackage p\n",
+       "// copyright\n\n//go:build x\n// +build x\n\npackage p\n",
 }
 
 func String(s string) (string, error) {
index 745ef900f6b7819f54f24166e49856b631ab5695..5484ca506bf87d013221f5598959584eb2e1aad0 100644 (file)
@@ -188,7 +188,7 @@ func TestInstallationImporter(t *testing.T) {
                {pkgpath: "io", name: "ReadWriter", want: "type ReadWriter interface{Reader; Writer}"},
                {pkgpath: "math", name: "Pi", want: "const Pi untyped float"},
                {pkgpath: "math", name: "Sin", want: "func Sin(x float64) float64"},
-               {pkgpath: "sort", name: "Ints", want: "func Ints(a []int)"},
+               {pkgpath: "sort", name: "Search", want: "func Search(n int, f func(int) bool) int"},
                {pkgpath: "unsafe", name: "Pointer", want: "type Pointer"},
        } {
                runImporterTest(t, imp, nil, &test)
index 35240c8fe68745f1df00117e34471d5d11843adc..8a7ee1aa4ffa9ba2b4b265d5bf669dbb6549fd4f 100644 (file)
@@ -94,7 +94,7 @@ var importerTests = [...]importerTest{
        {pkgpath: "nointerface", name: "I", want: "type I int"},
        {pkgpath: "issue29198", name: "FooServer", gccgoVersion: 7, want: "type FooServer struct{FooServer *FooServer; user string; ctx context.Context}"},
        {pkgpath: "issue30628", name: "Apple", want: "type Apple struct{hey sync.RWMutex; x int; RQ [517]struct{Count uintptr; NumBytes uintptr; Last uintptr}}"},
-       {pkgpath: "issue31540", name: "S", gccgoVersion: 7, want: "type S struct{b int; map[Y]Z}"},
+       {pkgpath: "issue31540", name: "S", gccgoVersion: 7, want: "type S struct{b int; map[Y]Z}"}, // should want "type S struct{b int; A2}" (issue  #44410)
        {pkgpath: "issue34182", name: "T1", want: "type T1 struct{f *T2}"},
        {pkgpath: "notinheap", name: "S", want: "type S struct{}"},
 }
@@ -149,21 +149,11 @@ func TestObjImporter(t *testing.T) {
        }
        t.Logf("gccgo version %d.%d", major, minor)
 
-       tmpdir, err := os.MkdirTemp("", "TestObjImporter")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(tmpdir)
-
+       tmpdir := t.TempDir()
        initmap := make(map[*types.Package]InitData)
        imp := GetImporter([]string{tmpdir}, initmap)
 
-       artmpdir, err := os.MkdirTemp("", "TestObjImporter")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(artmpdir)
-
+       artmpdir := t.TempDir()
        arinitmap := make(map[*types.Package]InitData)
        arimp := GetImporter([]string{artmpdir}, arinitmap)
 
index b74daca246374542f6fa60362eb7f820930cedf9..73cf6334fd65e681aafe7d97b986de0b5dd8ed29 100644 (file)
@@ -145,17 +145,14 @@ func Import(fset *token.FileSet, packages map[string]*types.Package, path, srcDi
                err = fmt.Errorf("import %q: old textual export format no longer supported (recompile library)", path)
 
        case "$$B\n":
-               var data []byte
-               data, err = io.ReadAll(buf)
-               if err != nil {
-                       break
-               }
+               var exportFormat byte
+               exportFormat, err = buf.ReadByte()
 
                // The indexed export format starts with an 'i'; the older
                // binary export format starts with a 'c', 'd', or 'v'
                // (from "version"). Select appropriate importer.
-               if len(data) > 0 && data[0] == 'i' {
-                       _, pkg, err = iImportData(fset, packages, data[1:], id)
+               if err == nil && exportFormat == 'i' {
+                       pkg, err = iImportData(fset, packages, buf, id)
                } else {
                        err = fmt.Errorf("import %q: old binary export format no longer supported (recompile library)", path)
                }
index c59dd16533173506db93882e8c14c7f10b9950e4..76d47d08f1f88a9a11a4761604aba4d753d5fe5f 100644 (file)
@@ -8,6 +8,7 @@
 package gcimporter
 
 import (
+       "bufio"
        "bytes"
        "encoding/binary"
        "fmt"
@@ -15,11 +16,12 @@ import (
        "go/token"
        "go/types"
        "io"
+       "math/big"
        "sort"
 )
 
 type intReader struct {
-       *bytes.Reader
+       *bufio.Reader
        path string
 }
 
@@ -60,7 +62,7 @@ const (
 // and returns the number of bytes consumed and a reference to the package.
 // If the export data version is not recognized or the format is otherwise
 // compromised, an error is returned.
-func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
+func iImportData(fset *token.FileSet, imports map[string]*types.Package, dataReader *bufio.Reader, path string) (pkg *types.Package, err error) {
        const currentVersion = 1
        version := int64(-1)
        defer func() {
@@ -73,7 +75,7 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []
                }
        }()
 
-       r := &intReader{bytes.NewReader(data), path}
+       r := &intReader{dataReader, path}
 
        version = int64(r.uint64())
        switch version {
@@ -85,10 +87,12 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []
        sLen := int64(r.uint64())
        dLen := int64(r.uint64())
 
-       whence, _ := r.Seek(0, io.SeekCurrent)
-       stringData := data[whence : whence+sLen]
-       declData := data[whence+sLen : whence+sLen+dLen]
-       r.Seek(sLen+dLen, io.SeekCurrent)
+       data := make([]byte, sLen+dLen)
+       if _, err := io.ReadFull(r, data); err != nil {
+               errorf("cannot read %d bytes of stringData and declData: %s", len(data), err)
+       }
+       stringData := data[:sLen]
+       declData := data[sLen:]
 
        p := iimporter{
                ipath:   path,
@@ -164,9 +168,7 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []
 
        // package was imported completely and without errors
        localpkg.MarkComplete()
-
-       consumed, _ := r.Seek(0, io.SeekCurrent)
-       return int(consumed), localpkg, nil
+       return localpkg, nil
 }
 
 type iimporter struct {
@@ -320,7 +322,9 @@ func (r *importReader) value() (typ types.Type, val constant.Value) {
                val = constant.MakeString(r.string())
 
        case types.IsInteger:
-               val = r.mpint(b)
+               var x big.Int
+               r.mpint(&x, b)
+               val = constant.Make(&x)
 
        case types.IsFloat:
                val = r.mpfloat(b)
@@ -365,8 +369,8 @@ func intSize(b *types.Basic) (signed bool, maxBytes uint) {
        return
 }
 
-func (r *importReader) mpint(b *types.Basic) constant.Value {
-       signed, maxBytes := intSize(b)
+func (r *importReader) mpint(x *big.Int, typ *types.Basic) {
+       signed, maxBytes := intSize(typ)
 
        maxSmall := 256 - maxBytes
        if signed {
@@ -385,7 +389,8 @@ func (r *importReader) mpint(b *types.Basic) constant.Value {
                                v = ^v
                        }
                }
-               return constant.MakeInt64(v)
+               x.SetInt64(v)
+               return
        }
 
        v := -n
@@ -395,39 +400,23 @@ func (r *importReader) mpint(b *types.Basic) constant.Value {
        if v < 1 || uint(v) > maxBytes {
                errorf("weird decoding: %v, %v => %v", n, signed, v)
        }
-
-       buf := make([]byte, v)
-       io.ReadFull(&r.declReader, buf)
-
-       // convert to little endian
-       // TODO(gri) go/constant should have a more direct conversion function
-       //           (e.g., once it supports a big.Float based implementation)
-       for i, j := 0, len(buf)-1; i < j; i, j = i+1, j-1 {
-               buf[i], buf[j] = buf[j], buf[i]
-       }
-
-       x := constant.MakeFromBytes(buf)
+       b := make([]byte, v)
+       io.ReadFull(&r.declReader, b)
+       x.SetBytes(b)
        if signed && n&1 != 0 {
-               x = constant.UnaryOp(token.SUB, x, 0)
+               x.Neg(x)
        }
-       return x
 }
 
-func (r *importReader) mpfloat(b *types.Basic) constant.Value {
-       x := r.mpint(b)
-       if constant.Sign(x) == 0 {
-               return x
+func (r *importReader) mpfloat(typ *types.Basic) constant.Value {
+       var mant big.Int
+       r.mpint(&mant, typ)
+       var f big.Float
+       f.SetInt(&mant)
+       if f.Sign() != 0 {
+               f.SetMantExp(&f, int(r.int64()))
        }
-
-       exp := r.int64()
-       switch {
-       case exp > 0:
-               x = constant.Shift(x, token.SHL, uint(exp))
-       case exp < 0:
-               d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp))
-               x = constant.BinaryOp(x, token.QUO, d)
-       }
-       return x
+       return constant.Make(&f)
 }
 
 func (r *importReader) ident() string {
index 863b672bd5955f60fa12e6897f034da3c5481c0c..c0172ba0eeb6c4a66bcabac12da60966b7ad7ec2 100644 (file)
@@ -30,7 +30,7 @@ type Importer struct {
        packages map[string]*types.Package
 }
 
-// NewImporter returns a new Importer for the given context, file set, and map
+// New returns a new Importer for the given context, file set, and map
 // of packages. The context is used to resolve import paths to package paths,
 // and identifying the files belonging to the package. If the context provides
 // non-nil file system functions, they are used instead of the regular package
diff --git a/libgo/go/go/internal/typeparams/common.go b/libgo/go/go/internal/typeparams/common.go
new file mode 100644 (file)
index 0000000..47b8f7c
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package typeparams provides functions to work with type parameter data
+// stored in the AST, while these AST changes are guarded by a build
+// constraint.
+package typeparams
+
+// DisallowParsing is the numeric value of a parsing mode that disallows type
+// parameters. This only matters if the typeparams experiment is active, and
+// may be used for running tests that disallow generics.
+const DisallowParsing = 1 << 30
diff --git a/libgo/go/go/internal/typeparams/notypeparams.go b/libgo/go/go/internal/typeparams/notypeparams.go
new file mode 100644 (file)
index 0000000..2ceafaa
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !typeparams
+// +build !typeparams
+
+package typeparams
+
+import (
+       "go/ast"
+)
+
+const Enabled = false
+
+func PackExpr(list []ast.Expr) ast.Expr {
+       switch len(list) {
+       case 1:
+               return list[0]
+       default:
+               // The parser should not attempt to pack multiple expressions into an
+               // IndexExpr if type params are disabled.
+               panic("multiple index expressions are unsupported without type params")
+       }
+}
+
+func UnpackExpr(expr ast.Expr) []ast.Expr {
+       return []ast.Expr{expr}
+}
+
+func IsListExpr(n ast.Node) bool {
+       return false
+}
+
+func Get(ast.Node) *ast.FieldList {
+       return nil
+}
+
+func Set(node ast.Node, params *ast.FieldList) {
+}
diff --git a/libgo/go/go/internal/typeparams/typeparams.go b/libgo/go/go/internal/typeparams/typeparams.go
new file mode 100644 (file)
index 0000000..871e95d
--- /dev/null
@@ -0,0 +1,69 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build typeparams
+// +build typeparams
+
+package typeparams
+
+import (
+       "fmt"
+       "go/ast"
+)
+
+const Enabled = true
+
+func PackExpr(list []ast.Expr) ast.Expr {
+       switch len(list) {
+       case 0:
+               // Return an empty ListExpr here, rather than nil, as IndexExpr.Index must
+               // never be nil.
+               // TODO(rFindley) would a BadExpr be more appropriate here?
+               return &ast.ListExpr{}
+       case 1:
+               return list[0]
+       default:
+               return &ast.ListExpr{ElemList: list}
+       }
+}
+
+// TODO(gri) Should find a more efficient solution that doesn't
+//           require introduction of a new slice for simple
+//           expressions.
+func UnpackExpr(x ast.Expr) []ast.Expr {
+       if x, _ := x.(*ast.ListExpr); x != nil {
+               return x.ElemList
+       }
+       if x != nil {
+               return []ast.Expr{x}
+       }
+       return nil
+}
+
+func IsListExpr(n ast.Node) bool {
+       _, ok := n.(*ast.ListExpr)
+       return ok
+}
+
+func Get(n ast.Node) *ast.FieldList {
+       switch n := n.(type) {
+       case *ast.TypeSpec:
+               return n.TParams
+       case *ast.FuncType:
+               return n.TParams
+       default:
+               panic(fmt.Sprintf("node type %T has no type parameters", n))
+       }
+}
+
+func Set(n ast.Node, params *ast.FieldList) {
+       switch n := n.(type) {
+       case *ast.TypeSpec:
+               n.TParams = params
+       case *ast.FuncType:
+               n.TParams = params
+       default:
+               panic(fmt.Sprintf("node type %T has no type parameters", n))
+       }
+}
index 358a844f65a6657107ebb6d2d49a8afa202a80b7..f4f0a5240ac801e71ce64c7e868025afb97780b4 100644 (file)
@@ -23,6 +23,7 @@
 package parser
 
 import (
+       "go/internal/typeparams"
        "go/scanner"
        "go/token"
        "os"
@@ -89,7 +90,7 @@ func expectedErrors(fset *token.FileSet, filename string, src []byte) map[token.
                                if s[1] == "HERE" {
                                        pos = here
                                }
-                               errors[pos] = string(s[2])
+                               errors[pos] = s[2]
                        }
                case token.SEMICOLON:
                        // don't use the position of auto-inserted (invisible) semicolons
@@ -114,6 +115,7 @@ func expectedErrors(fset *token.FileSet, filename string, src []byte) map[token.
 // of found errors and reports discrepancies.
 //
 func compareErrors(t *testing.T, fset *token.FileSet, expected map[token.Pos]string, found scanner.ErrorList) {
+       t.Helper()
        for _, error := range found {
                // error.Pos is a token.Position, but we want
                // a token.Pos so we can do a map lookup
@@ -149,7 +151,8 @@ func compareErrors(t *testing.T, fset *token.FileSet, expected map[token.Pos]str
        }
 }
 
-func checkErrors(t *testing.T, filename string, input interface{}) {
+func checkErrors(t *testing.T, filename string, input interface{}, mode Mode, expectErrors bool) {
+       t.Helper()
        src, err := readSource(filename, input)
        if err != nil {
                t.Error(err)
@@ -157,7 +160,7 @@ func checkErrors(t *testing.T, filename string, input interface{}) {
        }
 
        fset := token.NewFileSet()
-       _, err = ParseFile(fset, filename, src, DeclarationErrors|AllErrors)
+       _, err = ParseFile(fset, filename, src, mode)
        found, ok := err.(scanner.ErrorList)
        if err != nil && !ok {
                t.Error(err)
@@ -165,9 +168,12 @@ func checkErrors(t *testing.T, filename string, input interface{}) {
        }
        found.RemoveMultiples()
 
-       // we are expecting the following errors
-       // (collect these after parsing a file so that it is found in the file set)
-       expected := expectedErrors(fset, filename, src)
+       expected := map[token.Pos]string{}
+       if expectErrors {
+               // we are expecting the following errors
+               // (collect these after parsing a file so that it is found in the file set)
+               expected = expectedErrors(fset, filename, src)
+       }
 
        // verify errors returned by the parser
        compareErrors(t, fset, expected, found)
@@ -180,8 +186,16 @@ func TestErrors(t *testing.T) {
        }
        for _, d := range list {
                name := d.Name()
-               if !d.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".src") {
-                       checkErrors(t, filepath.Join(testdata, name), nil)
+               if !d.IsDir() && !strings.HasPrefix(name, ".") && (strings.HasSuffix(name, ".src") || strings.HasSuffix(name, ".go2")) {
+                       mode := DeclarationErrors | AllErrors
+                       if strings.HasSuffix(name, ".go2") {
+                               if !typeparams.Enabled {
+                                       continue
+                               }
+                       } else {
+                               mode |= typeparams.DisallowParsing
+                       }
+                       checkErrors(t, filepath.Join(testdata, name), nil, mode, true)
                }
        }
 }
index 56ff5fefb4f095408d2ba01dde0d33ea6a5d190d..85486d2f4b465ddd7638bdb10f691e215788c1a8 100644 (file)
@@ -49,13 +49,14 @@ func readSource(filename string, src interface{}) ([]byte, error) {
 type Mode uint
 
 const (
-       PackageClauseOnly Mode             = 1 << iota // stop parsing after package clause
-       ImportsOnly                                    // stop parsing after import declarations
-       ParseComments                                  // parse comments and add them to AST
-       Trace                                          // print a trace of parsed productions
-       DeclarationErrors                              // report declaration errors
-       SpuriousErrors                                 // same as AllErrors, for backward-compatibility
-       AllErrors         = SpuriousErrors             // report all errors (not just the first 10 on different lines)
+       PackageClauseOnly    Mode             = 1 << iota // stop parsing after package clause
+       ImportsOnly                                       // stop parsing after import declarations
+       ParseComments                                     // parse comments and add them to AST
+       Trace                                             // print a trace of parsed productions
+       DeclarationErrors                                 // report declaration errors
+       SpuriousErrors                                    // same as AllErrors, for backward-compatibility
+       SkipObjectResolution                              // don't resolve identifiers to objects - see ParseFile
+       AllErrors            = SpuriousErrors             // report all errors (not just the first 10 on different lines)
 )
 
 // ParseFile parses the source code of a single Go source file and returns
@@ -68,8 +69,12 @@ const (
 // If src == nil, ParseFile parses the file specified by filename.
 //
 // The mode parameter controls the amount of source text parsed and other
-// optional parser functionality. Position information is recorded in the
-// file set fset, which must not be nil.
+// optional parser functionality. If the SkipObjectResolution mode bit is set,
+// the object resolution phase of parsing will be skipped, causing File.Scope,
+// File.Unresolved, and all Ident.Obj fields to be nil.
+//
+// Position information is recorded in the file set fset, which must not be
+// nil.
 //
 // If the source couldn't be read, the returned AST is nil and the error
 // indicates the specific failure. If the source was read but syntax
@@ -208,15 +213,7 @@ func ParseExprFrom(fset *token.FileSet, filename string, src interface{}, mode M
 
        // parse expr
        p.init(fset, filename, text, mode)
-       // Set up pkg-level scopes to avoid nil-pointer errors.
-       // This is not needed for a correct expression x as the
-       // parser will be ok with a nil topScope, but be cautious
-       // in case of an erroneous x.
-       p.openScope()
-       p.pkgScope = p.topScope
        expr = p.parseRhsOrType()
-       p.closeScope()
-       assert(p.topScope == nil, "unbalanced scopes")
 
        // If a semicolon was inserted, consume it;
        // report an error if there's more tokens.
index 31a73985bf3b567381114da88162ef9ce7b50920..f10c8650afd0bf15461f712a8694e03bd02f7ab3 100644 (file)
@@ -19,6 +19,7 @@ package parser
 import (
        "fmt"
        "go/ast"
+       "go/internal/typeparams"
        "go/scanner"
        "go/token"
        "strconv"
@@ -34,7 +35,7 @@ type parser struct {
 
        // Tracing/debugging
        mode   Mode // parsing mode
-       trace  bool // == (mode & Trace != 0)
+       trace  bool // == (mode&Trace != 0)
        indent int  // indentation used for tracing output
 
        // Comments
@@ -58,16 +59,7 @@ type parser struct {
        exprLev int  // < 0: in control clause, >= 0: in expression
        inRhs   bool // if set, the parser is parsing a rhs expression
 
-       // Ordinary identifier scopes
-       pkgScope   *ast.Scope        // pkgScope.Outer == nil
-       topScope   *ast.Scope        // top-most scope; may be pkgScope
-       unresolved []*ast.Ident      // unresolved identifiers
-       imports    []*ast.ImportSpec // list of imports
-
-       // Label scopes
-       // (maintained by open/close LabelScope)
-       labelScope  *ast.Scope     // label scope for current function
-       targetStack [][]*ast.Ident // stack of unresolved labels
+       imports []*ast.ImportSpec // list of imports
 }
 
 func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode Mode) {
@@ -81,129 +73,11 @@ func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode Mod
 
        p.mode = mode
        p.trace = mode&Trace != 0 // for convenience (p.trace is used frequently)
-
        p.next()
 }
 
-// ----------------------------------------------------------------------------
-// Scoping support
-
-func (p *parser) openScope() {
-       p.topScope = ast.NewScope(p.topScope)
-}
-
-func (p *parser) closeScope() {
-       p.topScope = p.topScope.Outer
-}
-
-func (p *parser) openLabelScope() {
-       p.labelScope = ast.NewScope(p.labelScope)
-       p.targetStack = append(p.targetStack, nil)
-}
-
-func (p *parser) closeLabelScope() {
-       // resolve labels
-       n := len(p.targetStack) - 1
-       scope := p.labelScope
-       for _, ident := range p.targetStack[n] {
-               ident.Obj = scope.Lookup(ident.Name)
-               if ident.Obj == nil && p.mode&DeclarationErrors != 0 {
-                       p.error(ident.Pos(), fmt.Sprintf("label %s undefined", ident.Name))
-               }
-       }
-       // pop label scope
-       p.targetStack = p.targetStack[0:n]
-       p.labelScope = p.labelScope.Outer
-}
-
-func (p *parser) declare(decl, data interface{}, scope *ast.Scope, kind ast.ObjKind, idents ...*ast.Ident) {
-       for _, ident := range idents {
-               assert(ident.Obj == nil, "identifier already declared or resolved")
-               obj := ast.NewObj(kind, ident.Name)
-               // remember the corresponding declaration for redeclaration
-               // errors and global variable resolution/typechecking phase
-               obj.Decl = decl
-               obj.Data = data
-               ident.Obj = obj
-               if ident.Name != "_" {
-                       if alt := scope.Insert(obj); alt != nil && p.mode&DeclarationErrors != 0 {
-                               prevDecl := ""
-                               if pos := alt.Pos(); pos.IsValid() {
-                                       prevDecl = fmt.Sprintf("\n\tprevious declaration at %s", p.file.Position(pos))
-                               }
-                               p.error(ident.Pos(), fmt.Sprintf("%s redeclared in this block%s", ident.Name, prevDecl))
-                       }
-               }
-       }
-}
-
-func (p *parser) shortVarDecl(decl *ast.AssignStmt, list []ast.Expr) {
-       // Go spec: A short variable declaration may redeclare variables
-       // provided they were originally declared in the same block with
-       // the same type, and at least one of the non-blank variables is new.
-       n := 0 // number of new variables
-       for _, x := range list {
-               if ident, isIdent := x.(*ast.Ident); isIdent {
-                       assert(ident.Obj == nil, "identifier already declared or resolved")
-                       obj := ast.NewObj(ast.Var, ident.Name)
-                       // remember corresponding assignment for other tools
-                       obj.Decl = decl
-                       ident.Obj = obj
-                       if ident.Name != "_" {
-                               if alt := p.topScope.Insert(obj); alt != nil {
-                                       ident.Obj = alt // redeclaration
-                               } else {
-                                       n++ // new declaration
-                               }
-                       }
-               } else {
-                       p.errorExpected(x.Pos(), "identifier on left side of :=")
-               }
-       }
-       if n == 0 && p.mode&DeclarationErrors != 0 {
-               p.error(list[0].Pos(), "no new variables on left side of :=")
-       }
-}
-
-// The unresolved object is a sentinel to mark identifiers that have been added
-// to the list of unresolved identifiers. The sentinel is only used for verifying
-// internal consistency.
-var unresolved = new(ast.Object)
-
-// If x is an identifier, tryResolve attempts to resolve x by looking up
-// the object it denotes. If no object is found and collectUnresolved is
-// set, x is marked as unresolved and collected in the list of unresolved
-// identifiers.
-//
-func (p *parser) tryResolve(x ast.Expr, collectUnresolved bool) {
-       // nothing to do if x is not an identifier or the blank identifier
-       ident, _ := x.(*ast.Ident)
-       if ident == nil {
-               return
-       }
-       assert(ident.Obj == nil, "identifier already declared or resolved")
-       if ident.Name == "_" {
-               return
-       }
-       // try to resolve the identifier
-       for s := p.topScope; s != nil; s = s.Outer {
-               if obj := s.Lookup(ident.Name); obj != nil {
-                       ident.Obj = obj
-                       return
-               }
-       }
-       // all local scopes are known, so any unresolved identifier
-       // must be found either in the file scope, package scope
-       // (perhaps in another file), or universe scope --- collect
-       // them so that they can be resolved later
-       if collectUnresolved {
-               ident.Obj = unresolved
-               p.unresolved = append(p.unresolved, ident)
-       }
-}
-
-func (p *parser) resolve(x ast.Expr) {
-       p.tryResolve(x, true)
+func (p *parser) parseTypeParams() bool {
+       return typeparams.Enabled && p.mode&typeparams.DisallowParsing == 0
 }
 
 // ----------------------------------------------------------------------------
@@ -241,7 +115,7 @@ func (p *parser) next0() {
        // Because of one-token look-ahead, print the previous token
        // when tracing as it provides a more readable output. The
        // very first token (!p.pos.IsValid()) is not initialized
-       // (it is token.ILLEGAL), so don't print it .
+       // (it is token.ILLEGAL), so don't print it.
        if p.trace && p.pos.IsValid() {
                s := p.tok.String()
                switch {
@@ -352,6 +226,10 @@ func (p *parser) next() {
 type bailout struct{}
 
 func (p *parser) error(pos token.Pos, msg string) {
+       if p.trace {
+               defer un(trace(p, "error: "+msg))
+       }
+
        epos := p.file.Position(pos)
 
        // If AllErrors is not set, discard errors reported on the same line
@@ -573,52 +451,24 @@ func (p *parser) parseIdentList() (list []*ast.Ident) {
 // Common productions
 
 // If lhs is set, result list elements which are identifiers are not resolved.
-func (p *parser) parseExprList(lhs bool) (list []ast.Expr) {
+func (p *parser) parseExprList() (list []ast.Expr) {
        if p.trace {
                defer un(trace(p, "ExpressionList"))
        }
 
-       list = append(list, p.checkExpr(p.parseExpr(lhs)))
+       list = append(list, p.checkExpr(p.parseExpr()))
        for p.tok == token.COMMA {
                p.next()
-               list = append(list, p.checkExpr(p.parseExpr(lhs)))
+               list = append(list, p.checkExpr(p.parseExpr()))
        }
 
        return
 }
 
-func (p *parser) parseLhsList() []ast.Expr {
+func (p *parser) parseList(inRhs bool) []ast.Expr {
        old := p.inRhs
-       p.inRhs = false
-       list := p.parseExprList(true)
-       switch p.tok {
-       case token.DEFINE:
-               // lhs of a short variable declaration
-               // but doesn't enter scope until later:
-               // caller must call p.shortVarDecl(p.makeIdentList(list))
-               // at appropriate time.
-       case token.COLON:
-               // lhs of a label declaration or a communication clause of a select
-               // statement (parseLhsList is not called when parsing the case clause
-               // of a switch statement):
-               // - labels are declared by the caller of parseLhsList
-               // - for communication clauses, if there is a stand-alone identifier
-               //   followed by a colon, we have a syntax error; there is no need
-               //   to resolve the identifier in that case
-       default:
-               // identifiers must be declared elsewhere
-               for _, x := range list {
-                       p.resolve(x)
-               }
-       }
-       p.inRhs = old
-       return list
-}
-
-func (p *parser) parseRhsList() []ast.Expr {
-       old := p.inRhs
-       p.inRhs = true
-       list := p.parseExprList(false)
+       p.inRhs = inRhs
+       list := p.parseExprList()
        p.inRhs = old
        return list
 }
@@ -631,7 +481,7 @@ func (p *parser) parseType() ast.Expr {
                defer un(trace(p, "Type"))
        }
 
-       typ := p.tryType()
+       typ := p.tryIdentOrType()
 
        if typ == nil {
                pos := p.pos
@@ -643,19 +493,32 @@ func (p *parser) parseType() ast.Expr {
        return typ
 }
 
+func (p *parser) parseQualifiedIdent(ident *ast.Ident) ast.Expr {
+       if p.trace {
+               defer un(trace(p, "QualifiedIdent"))
+       }
+
+       typ := p.parseTypeName(ident)
+       if p.tok == token.LBRACK && p.parseTypeParams() {
+               typ = p.parseTypeInstance(typ)
+       }
+
+       return typ
+}
+
 // If the result is an identifier, it is not resolved.
-func (p *parser) parseTypeName() ast.Expr {
+func (p *parser) parseTypeName(ident *ast.Ident) ast.Expr {
        if p.trace {
                defer un(trace(p, "TypeName"))
        }
 
-       ident := p.parseIdent()
-       // don't resolve ident yet - it may be a parameter or field name
+       if ident == nil {
+               ident = p.parseIdent()
+       }
 
        if p.tok == token.PERIOD {
                // ident is a package name
                p.next()
-               p.resolve(ident)
                sel := p.parseIdent()
                return &ast.SelectorExpr{X: ident, Sel: sel}
        }
@@ -663,12 +526,11 @@ func (p *parser) parseTypeName() ast.Expr {
        return ident
 }
 
-func (p *parser) parseArrayType() ast.Expr {
+func (p *parser) parseArrayLen() ast.Expr {
        if p.trace {
-               defer un(trace(p, "ArrayType"))
+               defer un(trace(p, "ArrayLen"))
        }
 
-       lbrack := p.expect(token.LBRACK)
        p.exprLev++
        var len ast.Expr
        // always permit ellipsis for more fault-tolerant parsing
@@ -679,66 +541,111 @@ func (p *parser) parseArrayType() ast.Expr {
                len = p.parseRhs()
        }
        p.exprLev--
-       p.expect(token.RBRACK)
-       elt := p.parseType()
 
-       return &ast.ArrayType{Lbrack: lbrack, Len: len, Elt: elt}
+       return len
 }
 
-func (p *parser) makeIdentList(list []ast.Expr) []*ast.Ident {
-       idents := make([]*ast.Ident, len(list))
-       for i, x := range list {
-               ident, isIdent := x.(*ast.Ident)
-               if !isIdent {
-                       if _, isBad := x.(*ast.BadExpr); !isBad {
-                               // only report error if it's a new one
-                               p.errorExpected(x.Pos(), "identifier")
+func (p *parser) parseArrayFieldOrTypeInstance(x *ast.Ident) (*ast.Ident, ast.Expr) {
+       if p.trace {
+               defer un(trace(p, "ArrayFieldOrTypeInstance"))
+       }
+
+       // TODO(gri) Should we allow a trailing comma in a type argument
+       //           list such as T[P,]? (We do in parseTypeInstance).
+       lbrack := p.expect(token.LBRACK)
+       var args []ast.Expr
+       var firstComma token.Pos
+       // TODO(rfindley): consider changing parseRhsOrType so that this function variable
+       // is not needed.
+       argparser := p.parseRhsOrType
+       if !p.parseTypeParams() {
+               argparser = p.parseRhs
+       }
+       if p.tok != token.RBRACK {
+               p.exprLev++
+               args = append(args, argparser())
+               for p.tok == token.COMMA {
+                       if !firstComma.IsValid() {
+                               firstComma = p.pos
                        }
-                       ident = &ast.Ident{NamePos: x.Pos(), Name: "_"}
+                       p.next()
+                       args = append(args, argparser())
                }
-               idents[i] = ident
+               p.exprLev--
        }
-       return idents
+       rbrack := p.expect(token.RBRACK)
+
+       if len(args) == 0 {
+               // x []E
+               elt := p.parseType()
+               return x, &ast.ArrayType{Lbrack: lbrack, Elt: elt}
+       }
+
+       // x [P]E or x[P]
+       if len(args) == 1 {
+               elt := p.tryIdentOrType()
+               if elt != nil {
+                       // x [P]E
+                       return x, &ast.ArrayType{Lbrack: lbrack, Len: args[0], Elt: elt}
+               }
+               if !p.parseTypeParams() {
+                       p.error(rbrack, "missing element type in array type expression")
+                       return nil, &ast.BadExpr{From: args[0].Pos(), To: args[0].End()}
+               }
+       }
+
+       if !p.parseTypeParams() {
+               p.error(firstComma, "expected ']', found ','")
+               return x, &ast.BadExpr{From: args[0].Pos(), To: args[len(args)-1].End()}
+       }
+
+       // x[P], x[P1, P2], ...
+       return nil, &ast.IndexExpr{X: x, Lbrack: lbrack, Index: typeparams.PackExpr(args), Rbrack: rbrack}
 }
 
-func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field {
+func (p *parser) parseFieldDecl() *ast.Field {
        if p.trace {
                defer un(trace(p, "FieldDecl"))
        }
 
        doc := p.leadComment
 
-       // 1st FieldDecl
-       // A type name used as an anonymous field looks like a field identifier.
-       var list []ast.Expr
-       for {
-               list = append(list, p.parseVarType(false))
-               if p.tok != token.COMMA {
-                       break
+       var names []*ast.Ident
+       var typ ast.Expr
+       if p.tok == token.IDENT {
+               name := p.parseIdent()
+               if p.tok == token.PERIOD || p.tok == token.STRING || p.tok == token.SEMICOLON || p.tok == token.RBRACE {
+                       // embedded type
+                       typ = name
+                       if p.tok == token.PERIOD {
+                               typ = p.parseQualifiedIdent(name)
+                       }
+               } else {
+                       // name1, name2, ... T
+                       names = []*ast.Ident{name}
+                       for p.tok == token.COMMA {
+                               p.next()
+                               names = append(names, p.parseIdent())
+                       }
+                       // Careful dance: We don't know if we have an embedded instantiated
+                       // type T[P1, P2, ...] or a field T of array type []E or [P]E.
+                       if len(names) == 1 && p.tok == token.LBRACK {
+                               name, typ = p.parseArrayFieldOrTypeInstance(name)
+                               if name == nil {
+                                       names = nil
+                               }
+                       } else {
+                               // T P
+                               typ = p.parseType()
+                       }
                }
-               p.next()
-       }
-
-       typ := p.tryVarType(false)
-
-       // analyze case
-       var idents []*ast.Ident
-       if typ != nil {
-               // IdentifierList Type
-               idents = p.makeIdentList(list)
        } else {
-               // ["*"] TypeName (AnonymousField)
-               typ = list[0] // we always have at least one element
-               if n := len(list); n > 1 {
-                       p.errorExpected(p.pos, "type")
-                       typ = &ast.BadExpr{From: p.pos, To: p.pos}
-               } else if !isTypeName(deref(typ)) {
-                       p.errorExpected(typ.Pos(), "anonymous field")
-                       typ = &ast.BadExpr{From: typ.Pos(), To: p.safePos(typ.End())}
-               }
+               // embedded, possibly generic type
+               // (using the enclosing parentheses to distinguish it from a named field declaration)
+               // TODO(rFindley) confirm that this doesn't allow parenthesized embedded type
+               typ = p.parseType()
        }
 
-       // Tag
        var tag *ast.BasicLit
        if p.tok == token.STRING {
                tag = &ast.BasicLit{ValuePos: p.pos, Kind: p.tok, Value: p.lit}
@@ -747,10 +654,7 @@ func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field {
 
        p.expectSemi() // call before accessing p.linecomment
 
-       field := &ast.Field{Doc: doc, Names: idents, Type: typ, Tag: tag, Comment: p.lineComment}
-       p.declare(field, nil, scope, ast.Var, idents...)
-       p.resolve(typ)
-
+       field := &ast.Field{Doc: doc, Names: names, Type: typ, Tag: tag, Comment: p.lineComment}
        return field
 }
 
@@ -761,13 +665,12 @@ func (p *parser) parseStructType() *ast.StructType {
 
        pos := p.expect(token.STRUCT)
        lbrace := p.expect(token.LBRACE)
-       scope := ast.NewScope(nil) // struct scope
        var list []*ast.Field
        for p.tok == token.IDENT || p.tok == token.MUL || p.tok == token.LPAREN {
                // a field declaration cannot start with a '(' but we accept
                // it here for more robust parsing and better error messages
                // (parseFieldDecl will check and complain if necessary)
-               list = append(list, p.parseFieldDecl(scope))
+               list = append(list, p.parseFieldDecl())
        }
        rbrace := p.expect(token.RBRACE)
 
@@ -792,119 +695,232 @@ func (p *parser) parsePointerType() *ast.StarExpr {
        return &ast.StarExpr{Star: star, X: base}
 }
 
-// If the result is an identifier, it is not resolved.
-func (p *parser) tryVarType(isParam bool) ast.Expr {
-       if isParam && p.tok == token.ELLIPSIS {
-               pos := p.pos
-               p.next()
-               typ := p.tryIdentOrType() // don't use parseType so we can provide better error message
-               if typ != nil {
-                       p.resolve(typ)
-               } else {
-                       p.error(pos, "'...' parameter is missing type")
-                       typ = &ast.BadExpr{From: pos, To: p.pos}
-               }
-               return &ast.Ellipsis{Ellipsis: pos, Elt: typ}
+func (p *parser) parseDotsType() *ast.Ellipsis {
+       if p.trace {
+               defer un(trace(p, "DotsType"))
        }
-       return p.tryIdentOrType()
+
+       pos := p.expect(token.ELLIPSIS)
+       elt := p.parseType()
+
+       return &ast.Ellipsis{Ellipsis: pos, Elt: elt}
 }
 
-// If the result is an identifier, it is not resolved.
-func (p *parser) parseVarType(isParam bool) ast.Expr {
-       typ := p.tryVarType(isParam)
-       if typ == nil {
-               pos := p.pos
-               p.errorExpected(pos, "type")
-               p.next() // make progress
-               typ = &ast.BadExpr{From: pos, To: p.pos}
+type field struct {
+       name *ast.Ident
+       typ  ast.Expr
+}
+
+func (p *parser) parseParamDecl(name *ast.Ident) (f field) {
+       // TODO(rFindley) compare with parser.paramDeclOrNil in the syntax package
+       if p.trace {
+               defer un(trace(p, "ParamDeclOrNil"))
        }
-       return typ
+
+       ptok := p.tok
+       if name != nil {
+               p.tok = token.IDENT // force token.IDENT case in switch below
+       }
+
+       switch p.tok {
+       case token.IDENT:
+               if name != nil {
+                       f.name = name
+                       p.tok = ptok
+               } else {
+                       f.name = p.parseIdent()
+               }
+               switch p.tok {
+               case token.IDENT, token.MUL, token.ARROW, token.FUNC, token.CHAN, token.MAP, token.STRUCT, token.INTERFACE, token.LPAREN:
+                       // name type
+                       f.typ = p.parseType()
+
+               case token.LBRACK:
+                       // name[type1, type2, ...] or name []type or name [len]type
+                       f.name, f.typ = p.parseArrayFieldOrTypeInstance(f.name)
+
+               case token.ELLIPSIS:
+                       // name ...type
+                       f.typ = p.parseDotsType()
+
+               case token.PERIOD:
+                       // qualified.typename
+                       f.typ = p.parseQualifiedIdent(f.name)
+                       f.name = nil
+               }
+
+       case token.MUL, token.ARROW, token.FUNC, token.LBRACK, token.CHAN, token.MAP, token.STRUCT, token.INTERFACE, token.LPAREN:
+               // type
+               f.typ = p.parseType()
+
+       case token.ELLIPSIS:
+               // ...type
+               // (always accepted)
+               f.typ = p.parseDotsType()
+
+       default:
+               p.errorExpected(p.pos, ")")
+               p.advance(exprEnd)
+       }
+
+       return
 }
 
-func (p *parser) parseParameterList(scope *ast.Scope, ellipsisOk bool) (params []*ast.Field) {
+func (p *parser) parseParameterList(name0 *ast.Ident, closing token.Token, parseParamDecl func(*ast.Ident) field, tparams bool) (params []*ast.Field) {
        if p.trace {
                defer un(trace(p, "ParameterList"))
        }
 
-       // 1st ParameterDecl
-       // A list of identifiers looks like a list of type names.
-       var list []ast.Expr
-       for {
-               list = append(list, p.parseVarType(ellipsisOk))
-               if p.tok != token.COMMA {
-                       break
+       pos := p.pos
+       if name0 != nil {
+               pos = name0.Pos()
+       }
+
+       var list []field
+       var named int // number of parameters that have an explicit name and type
+
+       for name0 != nil || p.tok != closing && p.tok != token.EOF {
+               par := parseParamDecl(name0)
+               name0 = nil // 1st name was consumed if present
+               if par.name != nil || par.typ != nil {
+                       list = append(list, par)
+                       if par.name != nil && par.typ != nil {
+                               named++
+                       }
                }
-               p.next()
-               if p.tok == token.RPAREN {
+               if !p.atComma("parameter list", closing) {
                        break
                }
+               p.next()
        }
 
-       // analyze case
-       if typ := p.tryVarType(ellipsisOk); typ != nil {
-               // IdentifierList Type
-               idents := p.makeIdentList(list)
-               field := &ast.Field{Names: idents, Type: typ}
-               params = append(params, field)
-               // Go spec: The scope of an identifier denoting a function
-               // parameter or result variable is the function body.
-               p.declare(field, nil, scope, ast.Var, idents...)
-               p.resolve(typ)
-               if !p.atComma("parameter list", token.RPAREN) {
-                       return
+       if len(list) == 0 {
+               return // not uncommon
+       }
+
+       // TODO(gri) parameter distribution and conversion to []*ast.Field
+       //           can be combined and made more efficient
+
+       // distribute parameter types
+       if named == 0 {
+               // all unnamed => found names are type names
+               for i := 0; i < len(list); i++ {
+                       par := &list[i]
+                       if typ := par.name; typ != nil {
+                               par.typ = typ
+                               par.name = nil
+                       }
                }
-               p.next()
-               for p.tok != token.RPAREN && p.tok != token.EOF {
-                       idents := p.parseIdentList()
-                       typ := p.parseVarType(ellipsisOk)
-                       field := &ast.Field{Names: idents, Type: typ}
-                       params = append(params, field)
-                       // Go spec: The scope of an identifier denoting a function
-                       // parameter or result variable is the function body.
-                       p.declare(field, nil, scope, ast.Var, idents...)
-                       p.resolve(typ)
-                       if !p.atComma("parameter list", token.RPAREN) {
-                               break
+               if tparams {
+                       p.error(pos, "all type parameters must be named")
+               }
+       } else if named != len(list) {
+               // some named => all must be named
+               ok := true
+               var typ ast.Expr
+               for i := len(list) - 1; i >= 0; i-- {
+                       if par := &list[i]; par.typ != nil {
+                               typ = par.typ
+                               if par.name == nil {
+                                       ok = false
+                                       n := ast.NewIdent("_")
+                                       n.NamePos = typ.Pos() // correct position
+                                       par.name = n
+                               }
+                       } else if typ != nil {
+                               par.typ = typ
+                       } else {
+                               // par.typ == nil && typ == nil => we only have a par.name
+                               ok = false
+                               par.typ = &ast.BadExpr{From: par.name.Pos(), To: p.pos}
                        }
-                       p.next()
+               }
+               if !ok {
+                       if tparams {
+                               p.error(pos, "all type parameters must be named")
+                       } else {
+                               p.error(pos, "mixed named and unnamed parameters")
+                       }
+               }
+       }
+
+       // convert list []*ast.Field
+       if named == 0 {
+               // parameter list consists of types only
+               for _, par := range list {
+                       assert(par.typ != nil, "nil type in unnamed parameter list")
+                       params = append(params, &ast.Field{Type: par.typ})
                }
                return
        }
 
-       // Type { "," Type } (anonymous parameters)
-       params = make([]*ast.Field, len(list))
-       for i, typ := range list {
-               p.resolve(typ)
-               params[i] = &ast.Field{Type: typ}
+       // parameter list consists of named parameters with types
+       var names []*ast.Ident
+       var typ ast.Expr
+       addParams := func() {
+               assert(typ != nil, "nil type in named parameter list")
+               field := &ast.Field{Names: names, Type: typ}
+               params = append(params, field)
+               names = nil
+       }
+       for _, par := range list {
+               if par.typ != typ {
+                       if len(names) > 0 {
+                               addParams()
+                       }
+                       typ = par.typ
+               }
+               names = append(names, par.name)
+       }
+       if len(names) > 0 {
+               addParams()
        }
        return
 }
 
-func (p *parser) parseParameters(scope *ast.Scope, ellipsisOk bool) *ast.FieldList {
+func (p *parser) parseParameters(acceptTParams bool) (tparams, params *ast.FieldList) {
        if p.trace {
                defer un(trace(p, "Parameters"))
        }
 
-       var params []*ast.Field
-       lparen := p.expect(token.LPAREN)
+       if p.parseTypeParams() && acceptTParams && p.tok == token.LBRACK {
+               opening := p.pos
+               p.next()
+               // [T any](params) syntax
+               list := p.parseParameterList(nil, token.RBRACK, p.parseParamDecl, true)
+               rbrack := p.expect(token.RBRACK)
+               tparams = &ast.FieldList{Opening: opening, List: list, Closing: rbrack}
+               // Type parameter lists must not be empty.
+               if tparams.NumFields() == 0 {
+                       p.error(tparams.Closing, "empty type parameter list")
+                       tparams = nil // avoid follow-on errors
+               }
+       }
+
+       opening := p.expect(token.LPAREN)
+
+       var fields []*ast.Field
        if p.tok != token.RPAREN {
-               params = p.parseParameterList(scope, ellipsisOk)
+               fields = p.parseParameterList(nil, token.RPAREN, p.parseParamDecl, false)
        }
+
        rparen := p.expect(token.RPAREN)
+       params = &ast.FieldList{Opening: opening, List: fields, Closing: rparen}
 
-       return &ast.FieldList{Opening: lparen, List: params, Closing: rparen}
+       return
 }
 
-func (p *parser) parseResult(scope *ast.Scope) *ast.FieldList {
+func (p *parser) parseResult() *ast.FieldList {
        if p.trace {
                defer un(trace(p, "Result"))
        }
 
        if p.tok == token.LPAREN {
-               return p.parseParameters(scope, false)
+               _, results := p.parseParameters(false)
+               return results
        }
 
-       typ := p.tryType()
+       typ := p.tryIdentOrType()
        if typ != nil {
                list := make([]*ast.Field, 1)
                list[0] = &ast.Field{Type: typ}
@@ -914,30 +930,22 @@ func (p *parser) parseResult(scope *ast.Scope) *ast.FieldList {
        return nil
 }
 
-func (p *parser) parseSignature(scope *ast.Scope) (params, results *ast.FieldList) {
-       if p.trace {
-               defer un(trace(p, "Signature"))
-       }
-
-       params = p.parseParameters(scope, true)
-       results = p.parseResult(scope)
-
-       return
-}
-
-func (p *parser) parseFuncType() (*ast.FuncType, *ast.Scope) {
+func (p *parser) parseFuncType() *ast.FuncType {
        if p.trace {
                defer un(trace(p, "FuncType"))
        }
 
        pos := p.expect(token.FUNC)
-       scope := ast.NewScope(p.topScope) // function scope
-       params, results := p.parseSignature(scope)
+       tparams, params := p.parseParameters(true)
+       if tparams != nil {
+               p.error(tparams.Pos(), "function type cannot have type parameters")
+       }
+       results := p.parseResult()
 
-       return &ast.FuncType{Func: pos, Params: params, Results: results}, scope
+       return &ast.FuncType{Func: pos, Params: params, Results: results}
 }
 
-func (p *parser) parseMethodSpec(scope *ast.Scope) *ast.Field {
+func (p *parser) parseMethodSpec() *ast.Field {
        if p.trace {
                defer un(trace(p, "MethodSpec"))
        }
@@ -945,22 +953,67 @@ func (p *parser) parseMethodSpec(scope *ast.Scope) *ast.Field {
        doc := p.leadComment
        var idents []*ast.Ident
        var typ ast.Expr
-       x := p.parseTypeName()
-       if ident, isIdent := x.(*ast.Ident); isIdent && p.tok == token.LPAREN {
-               // method
-               idents = []*ast.Ident{ident}
-               scope := ast.NewScope(nil) // method scope
-               params, results := p.parseSignature(scope)
-               typ = &ast.FuncType{Func: token.NoPos, Params: params, Results: results}
+       x := p.parseTypeName(nil)
+       if ident, _ := x.(*ast.Ident); ident != nil {
+               switch {
+               case p.tok == token.LBRACK && p.parseTypeParams():
+                       // generic method or embedded instantiated type
+                       lbrack := p.pos
+                       p.next()
+                       p.exprLev++
+                       x := p.parseExpr()
+                       p.exprLev--
+                       if name0, _ := x.(*ast.Ident); name0 != nil && p.tok != token.COMMA && p.tok != token.RBRACK {
+                               // generic method m[T any]
+                               list := p.parseParameterList(name0, token.RBRACK, p.parseParamDecl, true)
+                               rbrack := p.expect(token.RBRACK)
+                               tparams := &ast.FieldList{Opening: lbrack, List: list, Closing: rbrack}
+                               // TODO(rfindley) refactor to share code with parseFuncType.
+                               _, params := p.parseParameters(false)
+                               results := p.parseResult()
+                               idents = []*ast.Ident{ident}
+                               typ = &ast.FuncType{Func: token.NoPos, Params: params, Results: results}
+                               typeparams.Set(typ, tparams)
+                       } else {
+                               // embedded instantiated type
+                               // TODO(rfindley) should resolve all identifiers in x.
+                               list := []ast.Expr{x}
+                               if p.atComma("type argument list", token.RBRACK) {
+                                       p.exprLev++
+                                       for p.tok != token.RBRACK && p.tok != token.EOF {
+                                               list = append(list, p.parseType())
+                                               if !p.atComma("type argument list", token.RBRACK) {
+                                                       break
+                                               }
+                                               p.next()
+                                       }
+                                       p.exprLev--
+                               }
+                               rbrack := p.expectClosing(token.RBRACK, "type argument list")
+                               typ = &ast.IndexExpr{X: ident, Lbrack: lbrack, Index: typeparams.PackExpr(list), Rbrack: rbrack}
+                       }
+               case p.tok == token.LPAREN:
+                       // ordinary method
+                       // TODO(rfindley) refactor to share code with parseFuncType.
+                       _, params := p.parseParameters(false)
+                       results := p.parseResult()
+                       idents = []*ast.Ident{ident}
+                       typ = &ast.FuncType{Func: token.NoPos, Params: params, Results: results}
+               default:
+                       // embedded type
+                       typ = x
+               }
        } else {
-               // embedded interface
+               // embedded, possibly instantiated type
                typ = x
-               p.resolve(typ)
+               if p.tok == token.LBRACK && p.parseTypeParams() {
+                       // embedded instantiated interface
+                       typ = p.parseTypeInstance(typ)
+               }
        }
        p.expectSemi() // call before accessing p.linecomment
 
        spec := &ast.Field{Doc: doc, Names: idents, Type: typ, Comment: p.lineComment}
-       p.declare(spec, nil, scope, ast.Fun, idents...)
 
        return spec
 }
@@ -972,11 +1025,24 @@ func (p *parser) parseInterfaceType() *ast.InterfaceType {
 
        pos := p.expect(token.INTERFACE)
        lbrace := p.expect(token.LBRACE)
-       scope := ast.NewScope(nil) // interface scope
        var list []*ast.Field
-       for p.tok == token.IDENT {
-               list = append(list, p.parseMethodSpec(scope))
+       for p.tok == token.IDENT || p.parseTypeParams() && p.tok == token.TYPE {
+               if p.tok == token.IDENT {
+                       list = append(list, p.parseMethodSpec())
+               } else {
+                       // all types in a type list share the same field name "type"
+                       // (since type is a keyword, a Go program cannot have that field name)
+                       name := []*ast.Ident{{NamePos: p.pos, Name: "type"}}
+                       p.next()
+                       // add each type as a field named "type"
+                       for _, typ := range p.parseTypeList() {
+                               list = append(list, &ast.Field{Names: name, Type: typ})
+                       }
+                       p.expectSemi()
+               }
        }
+       // TODO(rfindley): the error produced here could be improved, since we could
+       // accept a identifier, 'type', or a '}' at this point.
        rbrace := p.expect(token.RBRACE)
 
        return &ast.InterfaceType{
@@ -1028,19 +1094,50 @@ func (p *parser) parseChanType() *ast.ChanType {
        return &ast.ChanType{Begin: pos, Arrow: arrow, Dir: dir, Value: value}
 }
 
-// If the result is an identifier, it is not resolved.
+func (p *parser) parseTypeInstance(typ ast.Expr) ast.Expr {
+       assert(p.parseTypeParams(), "parseTypeInstance while not parsing type params")
+       if p.trace {
+               defer un(trace(p, "TypeInstance"))
+       }
+
+       opening := p.expect(token.LBRACK)
+
+       p.exprLev++
+       var list []ast.Expr
+       for p.tok != token.RBRACK && p.tok != token.EOF {
+               list = append(list, p.parseType())
+               if !p.atComma("type argument list", token.RBRACK) {
+                       break
+               }
+               p.next()
+       }
+       p.exprLev--
+
+       closing := p.expectClosing(token.RBRACK, "type argument list")
+
+       return &ast.IndexExpr{X: typ, Lbrack: opening, Index: typeparams.PackExpr(list), Rbrack: closing}
+}
+
 func (p *parser) tryIdentOrType() ast.Expr {
        switch p.tok {
        case token.IDENT:
-               return p.parseTypeName()
+               typ := p.parseTypeName(nil)
+               if p.tok == token.LBRACK && p.parseTypeParams() {
+                       typ = p.parseTypeInstance(typ)
+               }
+               return typ
        case token.LBRACK:
-               return p.parseArrayType()
+               lbrack := p.expect(token.LBRACK)
+               alen := p.parseArrayLen()
+               p.expect(token.RBRACK)
+               elt := p.parseType()
+               return &ast.ArrayType{Lbrack: lbrack, Len: alen, Elt: elt}
        case token.STRUCT:
                return p.parseStructType()
        case token.MUL:
                return p.parsePointerType()
        case token.FUNC:
-               typ, _ := p.parseFuncType()
+               typ := p.parseFuncType()
                return typ
        case token.INTERFACE:
                return p.parseInterfaceType()
@@ -1060,14 +1157,6 @@ func (p *parser) tryIdentOrType() ast.Expr {
        return nil
 }
 
-func (p *parser) tryType() ast.Expr {
-       typ := p.tryIdentOrType()
-       if typ != nil {
-               p.resolve(typ)
-       }
-       return typ
-}
-
 // ----------------------------------------------------------------------------
 // Blocks
 
@@ -1083,17 +1172,13 @@ func (p *parser) parseStmtList() (list []ast.Stmt) {
        return
 }
 
-func (p *parser) parseBody(scope *ast.Scope) *ast.BlockStmt {
+func (p *parser) parseBody() *ast.BlockStmt {
        if p.trace {
                defer un(trace(p, "Body"))
        }
 
        lbrace := p.expect(token.LBRACE)
-       p.topScope = scope // open function scope
-       p.openLabelScope()
        list := p.parseStmtList()
-       p.closeLabelScope()
-       p.closeScope()
        rbrace := p.expect2(token.RBRACE)
 
        return &ast.BlockStmt{Lbrace: lbrace, List: list, Rbrace: rbrace}
@@ -1105,9 +1190,7 @@ func (p *parser) parseBlockStmt() *ast.BlockStmt {
        }
 
        lbrace := p.expect(token.LBRACE)
-       p.openScope()
        list := p.parseStmtList()
-       p.closeScope()
        rbrace := p.expect2(token.RBRACE)
 
        return &ast.BlockStmt{Lbrace: lbrace, List: list, Rbrace: rbrace}
@@ -1121,14 +1204,14 @@ func (p *parser) parseFuncTypeOrLit() ast.Expr {
                defer un(trace(p, "FuncTypeOrLit"))
        }
 
-       typ, scope := p.parseFuncType()
+       typ := p.parseFuncType()
        if p.tok != token.LBRACE {
                // function type only
                return typ
        }
 
        p.exprLev++
-       body := p.parseBody(scope)
+       body := p.parseBody()
        p.exprLev--
 
        return &ast.FuncLit{Type: typ, Body: body}
@@ -1136,9 +1219,8 @@ func (p *parser) parseFuncTypeOrLit() ast.Expr {
 
 // parseOperand may return an expression or a raw type (incl. array
 // types of the form [...]T. Callers must verify the result.
-// If lhs is set and the result is an identifier, it is not resolved.
 //
-func (p *parser) parseOperand(lhs bool) ast.Expr {
+func (p *parser) parseOperand() ast.Expr {
        if p.trace {
                defer un(trace(p, "Operand"))
        }
@@ -1146,9 +1228,6 @@ func (p *parser) parseOperand(lhs bool) ast.Expr {
        switch p.tok {
        case token.IDENT:
                x := p.parseIdent()
-               if !lhs {
-                       p.resolve(x)
-               }
                return x
 
        case token.INT, token.FLOAT, token.IMAG, token.CHAR, token.STRING:
@@ -1169,7 +1248,7 @@ func (p *parser) parseOperand(lhs bool) ast.Expr {
                return p.parseFuncTypeOrLit()
        }
 
-       if typ := p.tryIdentOrType(); typ != nil {
+       if typ := p.tryIdentOrType(); typ != nil { // do not consume trailing type parameters
                // could be type for composite literal or conversion
                _, isIdent := typ.(*ast.Ident)
                assert(!isIdent, "type cannot be identifier")
@@ -1211,28 +1290,61 @@ func (p *parser) parseTypeAssertion(x ast.Expr) ast.Expr {
        return &ast.TypeAssertExpr{X: x, Type: typ, Lparen: lparen, Rparen: rparen}
 }
 
-func (p *parser) parseIndexOrSlice(x ast.Expr) ast.Expr {
+func (p *parser) parseIndexOrSliceOrInstance(x ast.Expr) ast.Expr {
        if p.trace {
-               defer un(trace(p, "IndexOrSlice"))
+               defer un(trace(p, "parseIndexOrSliceOrInstance"))
        }
 
-       const N = 3 // change the 3 to 2 to disable 3-index slices
        lbrack := p.expect(token.LBRACK)
+       if p.tok == token.RBRACK {
+               // empty index, slice or index expressions are not permitted;
+               // accept them for parsing tolerance, but complain
+               p.errorExpected(p.pos, "operand")
+               rbrack := p.pos
+               p.next()
+               return &ast.IndexExpr{
+                       X:      x,
+                       Lbrack: lbrack,
+                       Index:  &ast.BadExpr{From: rbrack, To: rbrack},
+                       Rbrack: rbrack,
+               }
+       }
        p.exprLev++
+
+       const N = 3 // change the 3 to 2 to disable 3-index slices
+       var args []ast.Expr
        var index [N]ast.Expr
        var colons [N - 1]token.Pos
+       var firstComma token.Pos
        if p.tok != token.COLON {
-               index[0] = p.parseRhs()
+               // We can't know if we have an index expression or a type instantiation;
+               // so even if we see a (named) type we are not going to be in type context.
+               index[0] = p.parseRhsOrType()
        }
        ncolons := 0
-       for p.tok == token.COLON && ncolons < len(colons) {
-               colons[ncolons] = p.pos
-               ncolons++
-               p.next()
-               if p.tok != token.COLON && p.tok != token.RBRACK && p.tok != token.EOF {
-                       index[ncolons] = p.parseRhs()
+       switch p.tok {
+       case token.COLON:
+               // slice expression
+               for p.tok == token.COLON && ncolons < len(colons) {
+                       colons[ncolons] = p.pos
+                       ncolons++
+                       p.next()
+                       if p.tok != token.COLON && p.tok != token.RBRACK && p.tok != token.EOF {
+                               index[ncolons] = p.parseRhs()
+                       }
+               }
+       case token.COMMA:
+               firstComma = p.pos
+               // instance expression
+               args = append(args, index[0])
+               for p.tok == token.COMMA {
+                       p.next()
+                       if p.tok != token.RBRACK && p.tok != token.EOF {
+                               args = append(args, p.parseType())
+                       }
                }
        }
+
        p.exprLev--
        rbrack := p.expect(token.RBRACK)
 
@@ -1255,7 +1367,18 @@ func (p *parser) parseIndexOrSlice(x ast.Expr) ast.Expr {
                return &ast.SliceExpr{X: x, Lbrack: lbrack, Low: index[0], High: index[1], Max: index[2], Slice3: slice3, Rbrack: rbrack}
        }
 
-       return &ast.IndexExpr{X: x, Lbrack: lbrack, Index: index[0], Rbrack: rbrack}
+       if len(args) == 0 {
+               // index expression
+               return &ast.IndexExpr{X: x, Lbrack: lbrack, Index: index[0], Rbrack: rbrack}
+       }
+
+       if !p.parseTypeParams() {
+               p.error(firstComma, "expected ']' or ':', found ','")
+               return &ast.BadExpr{From: args[0].Pos(), To: args[len(args)-1].End()}
+       }
+
+       // instance expression
+       return &ast.IndexExpr{X: x, Lbrack: lbrack, Index: typeparams.PackExpr(args), Rbrack: rbrack}
 }
 
 func (p *parser) parseCallOrConversion(fun ast.Expr) *ast.CallExpr {
@@ -1284,7 +1407,7 @@ func (p *parser) parseCallOrConversion(fun ast.Expr) *ast.CallExpr {
        return &ast.CallExpr{Fun: fun, Lparen: lparen, Args: list, Ellipsis: ellipsis, Rparen: rparen}
 }
 
-func (p *parser) parseValue(keyOk bool) ast.Expr {
+func (p *parser) parseValue() ast.Expr {
        if p.trace {
                defer un(trace(p, "Element"))
        }
@@ -1293,35 +1416,7 @@ func (p *parser) parseValue(keyOk bool) ast.Expr {
                return p.parseLiteralValue(nil)
        }
 
-       // Because the parser doesn't know the composite literal type, it cannot
-       // know if a key that's an identifier is a struct field name or a name
-       // denoting a value. The former is not resolved by the parser or the
-       // resolver.
-       //
-       // Instead, _try_ to resolve such a key if possible. If it resolves,
-       // it a) has correctly resolved, or b) incorrectly resolved because
-       // the key is a struct field with a name matching another identifier.
-       // In the former case we are done, and in the latter case we don't
-       // care because the type checker will do a separate field lookup.
-       //
-       // If the key does not resolve, it a) must be defined at the top
-       // level in another file of the same package, the universe scope, or be
-       // undeclared; or b) it is a struct field. In the former case, the type
-       // checker can do a top-level lookup, and in the latter case it will do
-       // a separate field lookup.
-       x := p.checkExpr(p.parseExpr(keyOk))
-       if keyOk {
-               if p.tok == token.COLON {
-                       // Try to resolve the key but don't collect it
-                       // as unresolved identifier if it fails so that
-                       // we don't get (possibly false) errors about
-                       // undeclared names.
-                       p.tryResolve(x, false)
-               } else {
-                       // not a key
-                       p.resolve(x)
-               }
-       }
+       x := p.checkExpr(p.parseExpr())
 
        return x
 }
@@ -1331,11 +1426,11 @@ func (p *parser) parseElement() ast.Expr {
                defer un(trace(p, "Element"))
        }
 
-       x := p.parseValue(true)
+       x := p.parseValue()
        if p.tok == token.COLON {
                colon := p.pos
                p.next()
-               x = &ast.KeyValueExpr{Key: x, Colon: colon, Value: p.parseValue(false)}
+               x = &ast.KeyValueExpr{Key: x, Colon: colon, Value: p.parseValue()}
        }
 
        return x
@@ -1404,45 +1499,6 @@ func (p *parser) checkExpr(x ast.Expr) ast.Expr {
        return x
 }
 
-// isTypeName reports whether x is a (qualified) TypeName.
-func isTypeName(x ast.Expr) bool {
-       switch t := x.(type) {
-       case *ast.BadExpr:
-       case *ast.Ident:
-       case *ast.SelectorExpr:
-               _, isIdent := t.X.(*ast.Ident)
-               return isIdent
-       default:
-               return false // all other nodes are not type names
-       }
-       return true
-}
-
-// isLiteralType reports whether x is a legal composite literal type.
-func isLiteralType(x ast.Expr) bool {
-       switch t := x.(type) {
-       case *ast.BadExpr:
-       case *ast.Ident:
-       case *ast.SelectorExpr:
-               _, isIdent := t.X.(*ast.Ident)
-               return isIdent
-       case *ast.ArrayType:
-       case *ast.StructType:
-       case *ast.MapType:
-       default:
-               return false // all other nodes are not legal composite literal types
-       }
-       return true
-}
-
-// If x is of the form *T, deref returns T, otherwise it returns x.
-func deref(x ast.Expr) ast.Expr {
-       if p, isPtr := x.(*ast.StarExpr); isPtr {
-               x = p.X
-       }
-       return x
-}
-
 // If x is of the form (T), unparen returns unparen(T), otherwise it returns x.
 func unparen(x ast.Expr) ast.Expr {
        if p, isParen := x.(*ast.ParenExpr); isParen {
@@ -1469,21 +1525,16 @@ func (p *parser) checkExprOrType(x ast.Expr) ast.Expr {
        return x
 }
 
-// If lhs is set and the result is an identifier, it is not resolved.
-func (p *parser) parsePrimaryExpr(lhs bool) ast.Expr {
+func (p *parser) parsePrimaryExpr() (x ast.Expr) {
        if p.trace {
                defer un(trace(p, "PrimaryExpr"))
        }
 
-       x := p.parseOperand(lhs)
-L:
+       x = p.parseOperand()
        for {
                switch p.tok {
                case token.PERIOD:
                        p.next()
-                       if lhs {
-                               p.resolve(x)
-                       }
                        switch p.tok {
                        case token.IDENT:
                                x = p.parseSelector(p.checkExprOrType(x))
@@ -1492,40 +1543,54 @@ L:
                        default:
                                pos := p.pos
                                p.errorExpected(pos, "selector or type assertion")
-                               p.next() // make progress
+                               // TODO(rFindley) The check for token.RBRACE below is a targeted fix
+                               //                to error recovery sufficient to make the x/tools tests to
+                               //                pass with the new parsing logic introduced for type
+                               //                parameters. Remove this once error recovery has been
+                               //                more generally reconsidered.
+                               if p.tok != token.RBRACE {
+                                       p.next() // make progress
+                               }
                                sel := &ast.Ident{NamePos: pos, Name: "_"}
                                x = &ast.SelectorExpr{X: x, Sel: sel}
                        }
                case token.LBRACK:
-                       if lhs {
-                               p.resolve(x)
-                       }
-                       x = p.parseIndexOrSlice(p.checkExpr(x))
+                       x = p.parseIndexOrSliceOrInstance(p.checkExpr(x))
                case token.LPAREN:
-                       if lhs {
-                               p.resolve(x)
-                       }
                        x = p.parseCallOrConversion(p.checkExprOrType(x))
                case token.LBRACE:
-                       if isLiteralType(x) && (p.exprLev >= 0 || !isTypeName(x)) {
-                               if lhs {
-                                       p.resolve(x)
+                       // operand may have returned a parenthesized complit
+                       // type; accept it but complain if we have a complit
+                       t := unparen(x)
+                       // determine if '{' belongs to a composite literal or a block statement
+                       switch t.(type) {
+                       case *ast.BadExpr, *ast.Ident, *ast.SelectorExpr:
+                               if p.exprLev < 0 {
+                                       return
                                }
-                               x = p.parseLiteralValue(x)
-                       } else {
-                               break L
+                               // x is possibly a composite literal type
+                       case *ast.IndexExpr:
+                               if p.exprLev < 0 {
+                                       return
+                               }
+                               // x is possibly a composite literal type
+                       case *ast.ArrayType, *ast.StructType, *ast.MapType:
+                               // x is a composite literal type
+                       default:
+                               return
+                       }
+                       if t != x {
+                               p.error(t.Pos(), "cannot parenthesize type in composite literal")
+                               // already progressed, no need to advance
                        }
+                       x = p.parseLiteralValue(x)
                default:
-                       break L
+                       return
                }
-               lhs = false // no need to try to resolve again
        }
-
-       return x
 }
 
-// If lhs is set and the result is an identifier, it is not resolved.
-func (p *parser) parseUnaryExpr(lhs bool) ast.Expr {
+func (p *parser) parseUnaryExpr() ast.Expr {
        if p.trace {
                defer un(trace(p, "UnaryExpr"))
        }
@@ -1534,7 +1599,7 @@ func (p *parser) parseUnaryExpr(lhs bool) ast.Expr {
        case token.ADD, token.SUB, token.NOT, token.XOR, token.AND:
                pos, op := p.pos, p.tok
                p.next()
-               x := p.parseUnaryExpr(false)
+               x := p.parseUnaryExpr()
                return &ast.UnaryExpr{OpPos: pos, Op: op, X: p.checkExpr(x)}
 
        case token.ARROW:
@@ -1556,7 +1621,7 @@ func (p *parser) parseUnaryExpr(lhs bool) ast.Expr {
                //   <- (chan type)    =>  (<-chan type)
                //   <- (chan<- type)  =>  (<-chan (<-type))
 
-               x := p.parseUnaryExpr(false)
+               x := p.parseUnaryExpr()
 
                // determine which case we have
                if typ, ok := x.(*ast.ChanType); ok {
@@ -1587,11 +1652,11 @@ func (p *parser) parseUnaryExpr(lhs bool) ast.Expr {
                // pointer type or unary "*" expression
                pos := p.pos
                p.next()
-               x := p.parseUnaryExpr(false)
+               x := p.parseUnaryExpr()
                return &ast.StarExpr{Star: pos, X: p.checkExprOrType(x)}
        }
 
-       return p.parsePrimaryExpr(lhs)
+       return p.parsePrimaryExpr()
 }
 
 func (p *parser) tokPrec() (token.Token, int) {
@@ -1602,44 +1667,38 @@ func (p *parser) tokPrec() (token.Token, int) {
        return tok, tok.Precedence()
 }
 
-// If lhs is set and the result is an identifier, it is not resolved.
-func (p *parser) parseBinaryExpr(lhs bool, prec1 int) ast.Expr {
+func (p *parser) parseBinaryExpr(prec1 int) ast.Expr {
        if p.trace {
                defer un(trace(p, "BinaryExpr"))
        }
 
-       x := p.parseUnaryExpr(lhs)
+       x := p.parseUnaryExpr()
        for {
                op, oprec := p.tokPrec()
                if oprec < prec1 {
                        return x
                }
                pos := p.expect(op)
-               if lhs {
-                       p.resolve(x)
-                       lhs = false
-               }
-               y := p.parseBinaryExpr(false, oprec+1)
+               y := p.parseBinaryExpr(oprec + 1)
                x = &ast.BinaryExpr{X: p.checkExpr(x), OpPos: pos, Op: op, Y: p.checkExpr(y)}
        }
 }
 
-// If lhs is set and the result is an identifier, it is not resolved.
 // The result may be a type or even a raw type ([...]int). Callers must
 // check the result (using checkExpr or checkExprOrType), depending on
 // context.
-func (p *parser) parseExpr(lhs bool) ast.Expr {
+func (p *parser) parseExpr() ast.Expr {
        if p.trace {
                defer un(trace(p, "Expression"))
        }
 
-       return p.parseBinaryExpr(lhs, token.LowestPrec+1)
+       return p.parseBinaryExpr(token.LowestPrec + 1)
 }
 
 func (p *parser) parseRhs() ast.Expr {
        old := p.inRhs
        p.inRhs = true
-       x := p.checkExpr(p.parseExpr(false))
+       x := p.checkExpr(p.parseExpr())
        p.inRhs = old
        return x
 }
@@ -1647,7 +1706,7 @@ func (p *parser) parseRhs() ast.Expr {
 func (p *parser) parseRhsOrType() ast.Expr {
        old := p.inRhs
        p.inRhs = true
-       x := p.checkExprOrType(p.parseExpr(false))
+       x := p.checkExprOrType(p.parseExpr())
        p.inRhs = old
        return x
 }
@@ -1671,7 +1730,7 @@ func (p *parser) parseSimpleStmt(mode int) (ast.Stmt, bool) {
                defer un(trace(p, "SimpleStmt"))
        }
 
-       x := p.parseLhsList()
+       x := p.parseList(false)
 
        switch p.tok {
        case
@@ -1690,11 +1749,11 @@ func (p *parser) parseSimpleStmt(mode int) (ast.Stmt, bool) {
                        y = []ast.Expr{&ast.UnaryExpr{OpPos: pos, Op: token.RANGE, X: p.parseRhs()}}
                        isRange = true
                } else {
-                       y = p.parseRhsList()
+                       y = p.parseList(true)
                }
                as := &ast.AssignStmt{Lhs: x, TokPos: pos, Tok: tok, Rhs: y}
                if tok == token.DEFINE {
-                       p.shortVarDecl(as, x)
+                       p.checkAssignStmt(as)
                }
                return as, isRange
        }
@@ -1714,7 +1773,6 @@ func (p *parser) parseSimpleStmt(mode int) (ast.Stmt, bool) {
                        // in which it is declared and excludes the body of any nested
                        // function.
                        stmt := &ast.LabeledStmt{Label: label, Colon: colon, Stmt: p.parseStmt()}
-                       p.declare(stmt, nil, p.labelScope, ast.Lbl, label)
                        return stmt, false
                }
                // The label declaration typically starts at x[0].Pos(), but the label
@@ -1744,6 +1802,14 @@ func (p *parser) parseSimpleStmt(mode int) (ast.Stmt, bool) {
        return &ast.ExprStmt{X: x[0]}, false
 }
 
+func (p *parser) checkAssignStmt(as *ast.AssignStmt) {
+       for _, x := range as.Lhs {
+               if _, isIdent := x.(*ast.Ident); !isIdent {
+                       p.errorExpected(x.Pos(), "identifier on left side of :=")
+               }
+       }
+}
+
 func (p *parser) parseCallExpr(callType string) *ast.CallExpr {
        x := p.parseRhsOrType() // could be a conversion: (some type)(x)
        if call, isCall := x.(*ast.CallExpr); isCall {
@@ -1795,7 +1861,7 @@ func (p *parser) parseReturnStmt() *ast.ReturnStmt {
        p.expect(token.RETURN)
        var x []ast.Expr
        if p.tok != token.SEMICOLON && p.tok != token.RBRACE {
-               x = p.parseRhsList()
+               x = p.parseList(true)
        }
        p.expectSemi()
 
@@ -1811,9 +1877,6 @@ func (p *parser) parseBranchStmt(tok token.Token) *ast.BranchStmt {
        var label *ast.Ident
        if tok != token.FALLTHROUGH && p.tok == token.IDENT {
                label = p.parseIdent()
-               // add to list of unresolved targets
-               n := len(p.targetStack) - 1
-               p.targetStack[n] = append(p.targetStack[n], label)
        }
        p.expectSemi()
 
@@ -1846,14 +1909,14 @@ func (p *parser) parseIfHeader() (init ast.Stmt, cond ast.Expr) {
        }
        // p.tok != token.LBRACE
 
-       outer := p.exprLev
+       prevLev := p.exprLev
        p.exprLev = -1
 
        if p.tok != token.SEMICOLON {
                // accept potential variable declaration but complain
                if p.tok == token.VAR {
                        p.next()
-                       p.error(p.pos, fmt.Sprintf("var declaration not allowed in 'IF' initializer"))
+                       p.error(p.pos, "var declaration not allowed in 'IF' initializer")
                }
                init, _ = p.parseSimpleStmt(basic)
        }
@@ -1894,7 +1957,7 @@ func (p *parser) parseIfHeader() (init ast.Stmt, cond ast.Expr) {
                cond = &ast.BadExpr{From: p.pos, To: p.pos}
        }
 
-       p.exprLev = outer
+       p.exprLev = prevLev
        return
 }
 
@@ -1904,8 +1967,6 @@ func (p *parser) parseIfStmt() *ast.IfStmt {
        }
 
        pos := p.expect(token.IF)
-       p.openScope()
-       defer p.closeScope()
 
        init, cond := p.parseIfHeader()
        body := p.parseBlockStmt()
@@ -1956,16 +2017,14 @@ func (p *parser) parseCaseClause(typeSwitch bool) *ast.CaseClause {
                if typeSwitch {
                        list = p.parseTypeList()
                } else {
-                       list = p.parseRhsList()
+                       list = p.parseList(true)
                }
        } else {
                p.expect(token.DEFAULT)
        }
 
        colon := p.expect(token.COLON)
-       p.openScope()
        body := p.parseStmtList()
-       p.closeScope()
 
        return &ast.CaseClause{Case: pos, List: list, Colon: colon, Body: body}
 }
@@ -2002,8 +2061,6 @@ func (p *parser) parseSwitchStmt() ast.Stmt {
        }
 
        pos := p.expect(token.SWITCH)
-       p.openScope()
-       defer p.closeScope()
 
        var s1, s2 ast.Stmt
        if p.tok != token.LBRACE {
@@ -2029,8 +2086,6 @@ func (p *parser) parseSwitchStmt() ast.Stmt {
                                //
                                // If we don't have a type switch, s2 must be an expression.
                                // Having the extra nested but empty scope won't affect it.
-                               p.openScope()
-                               defer p.closeScope()
                                s2, _ = p.parseSimpleStmt(basic)
                        }
                }
@@ -2059,12 +2114,11 @@ func (p *parser) parseCommClause() *ast.CommClause {
                defer un(trace(p, "CommClause"))
        }
 
-       p.openScope()
        pos := p.pos
        var comm ast.Stmt
        if p.tok == token.CASE {
                p.next()
-               lhs := p.parseLhsList()
+               lhs := p.parseList(false)
                if p.tok == token.ARROW {
                        // SendStmt
                        if len(lhs) > 1 {
@@ -2089,7 +2143,7 @@ func (p *parser) parseCommClause() *ast.CommClause {
                                rhs := p.parseRhs()
                                as := &ast.AssignStmt{Lhs: lhs, TokPos: pos, Tok: tok, Rhs: []ast.Expr{rhs}}
                                if tok == token.DEFINE {
-                                       p.shortVarDecl(as, lhs)
+                                       p.checkAssignStmt(as)
                                }
                                comm = as
                        } else {
@@ -2107,7 +2161,6 @@ func (p *parser) parseCommClause() *ast.CommClause {
 
        colon := p.expect(token.COLON)
        body := p.parseStmtList()
-       p.closeScope()
 
        return &ast.CommClause{Case: pos, Comm: comm, Colon: colon, Body: body}
 }
@@ -2136,8 +2189,6 @@ func (p *parser) parseForStmt() ast.Stmt {
        }
 
        pos := p.expect(token.FOR)
-       p.openScope()
-       defer p.closeScope()
 
        var s1, s2, s3 ast.Stmt
        var isRange bool
@@ -2275,7 +2326,7 @@ func (p *parser) parseStmt() (s ast.Stmt) {
 // ----------------------------------------------------------------------------
 // Declarations
 
-type parseSpecFunction func(doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec
+type parseSpecFunction func(doc *ast.CommentGroup, pos token.Pos, keyword token.Token, iota int) ast.Spec
 
 func isValidImport(lit string) bool {
        const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD"
@@ -2288,7 +2339,7 @@ func isValidImport(lit string) bool {
        return s != ""
 }
 
-func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Token, _ int) ast.Spec {
+func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Pos, _ token.Token, _ int) ast.Spec {
        if p.trace {
                defer un(trace(p, "ImportSpec"))
        }
@@ -2327,19 +2378,19 @@ func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Token, _ int) as
        return spec
 }
 
-func (p *parser) parseValueSpec(doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec {
+func (p *parser) parseValueSpec(doc *ast.CommentGroup, _ token.Pos, keyword token.Token, iota int) ast.Spec {
        if p.trace {
                defer un(trace(p, keyword.String()+"Spec"))
        }
 
        pos := p.pos
        idents := p.parseIdentList()
-       typ := p.tryType()
+       typ := p.tryIdentOrType()
        var values []ast.Expr
        // always permit optional initialization for more tolerant parsing
        if p.tok == token.ASSIGN {
                p.next()
-               values = p.parseRhsList()
+               values = p.parseList(true)
        }
        p.expectSemi() // call before accessing p.linecomment
 
@@ -2354,10 +2405,6 @@ func (p *parser) parseValueSpec(doc *ast.CommentGroup, keyword token.Token, iota
                }
        }
 
-       // Go spec: The scope of a constant or variable identifier declared inside
-       // a function begins at the end of the ConstSpec or VarSpec and ends at
-       // the end of the innermost containing block.
-       // (Global identifiers are resolved in a separate phase after parsing.)
        spec := &ast.ValueSpec{
                Doc:     doc,
                Names:   idents,
@@ -2365,33 +2412,66 @@ func (p *parser) parseValueSpec(doc *ast.CommentGroup, keyword token.Token, iota
                Values:  values,
                Comment: p.lineComment,
        }
-       kind := ast.Con
-       if keyword == token.VAR {
-               kind = ast.Var
-       }
-       p.declare(spec, iota, p.topScope, kind, idents...)
-
        return spec
 }
 
-func (p *parser) parseTypeSpec(doc *ast.CommentGroup, _ token.Token, _ int) ast.Spec {
+func (p *parser) parseGenericType(spec *ast.TypeSpec, openPos token.Pos, name0 *ast.Ident, closeTok token.Token) {
+       list := p.parseParameterList(name0, closeTok, p.parseParamDecl, true)
+       closePos := p.expect(closeTok)
+       typeparams.Set(spec, &ast.FieldList{Opening: openPos, List: list, Closing: closePos})
+       // Type alias cannot have type parameters. Accept them for robustness but complain.
+       if p.tok == token.ASSIGN {
+               p.error(p.pos, "generic type cannot be alias")
+               p.next()
+       }
+       spec.Type = p.parseType()
+}
+
+func (p *parser) parseTypeSpec(doc *ast.CommentGroup, _ token.Pos, _ token.Token, _ int) ast.Spec {
        if p.trace {
                defer un(trace(p, "TypeSpec"))
        }
 
        ident := p.parseIdent()
-
-       // Go spec: The scope of a type identifier declared inside a function begins
-       // at the identifier in the TypeSpec and ends at the end of the innermost
-       // containing block.
-       // (Global identifiers are resolved in a separate phase after parsing.)
        spec := &ast.TypeSpec{Doc: doc, Name: ident}
-       p.declare(spec, nil, p.topScope, ast.Typ, ident)
-       if p.tok == token.ASSIGN {
-               spec.Assign = p.pos
+
+       switch p.tok {
+       case token.LBRACK:
+               lbrack := p.pos
                p.next()
+               if p.tok == token.IDENT {
+                       // array type or generic type [T any]
+                       p.exprLev++
+                       x := p.parseExpr()
+                       p.exprLev--
+                       if name0, _ := x.(*ast.Ident); p.parseTypeParams() && name0 != nil && p.tok != token.RBRACK {
+                               // generic type [T any];
+                               p.parseGenericType(spec, lbrack, name0, token.RBRACK)
+                       } else {
+                               // array type
+                               // TODO(rfindley) should resolve all identifiers in x.
+                               p.expect(token.RBRACK)
+                               elt := p.parseType()
+                               spec.Type = &ast.ArrayType{Lbrack: lbrack, Len: x, Elt: elt}
+                       }
+               } else {
+                       // array type
+                       alen := p.parseArrayLen()
+                       p.expect(token.RBRACK)
+                       elt := p.parseType()
+                       spec.Type = &ast.ArrayType{Lbrack: lbrack, Len: alen, Elt: elt}
+               }
+
+       default:
+               // no type parameters
+               if p.tok == token.ASSIGN {
+                       // type alias
+                       spec.Assign = p.pos
+                       p.next()
+               }
+               spec.Type = p.parseType()
        }
-       spec.Type = p.parseType()
+
        p.expectSemi() // call before accessing p.linecomment
        spec.Comment = p.lineComment
 
@@ -2411,12 +2491,12 @@ func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.Gen
                lparen = p.pos
                p.next()
                for iota := 0; p.tok != token.RPAREN && p.tok != token.EOF; iota++ {
-                       list = append(list, f(p.leadComment, keyword, iota))
+                       list = append(list, f(p.leadComment, pos, keyword, iota))
                }
                rparen = p.expect(token.RPAREN)
                p.expectSemi()
        } else {
-               list = append(list, f(nil, keyword, 0))
+               list = append(list, f(nil, pos, keyword, 0))
        }
 
        return &ast.GenDecl{
@@ -2436,27 +2516,27 @@ func (p *parser) parseFuncDecl() *ast.FuncDecl {
 
        doc := p.leadComment
        pos := p.expect(token.FUNC)
-       scope := ast.NewScope(p.topScope) // function scope
 
        var recv *ast.FieldList
        if p.tok == token.LPAREN {
-               recv = p.parseParameters(scope, false)
+               _, recv = p.parseParameters(false)
        }
 
        ident := p.parseIdent()
 
-       params, results := p.parseSignature(scope)
+       tparams, params := p.parseParameters(true)
+       results := p.parseResult()
 
        var body *ast.BlockStmt
        if p.tok == token.LBRACE {
-               body = p.parseBody(scope)
+               body = p.parseBody()
                p.expectSemi()
        } else if p.tok == token.SEMICOLON {
                p.next()
                if p.tok == token.LBRACE {
                        // opening { of function declaration on next line
                        p.error(p.pos, "unexpected semicolon or newline before {")
-                       body = p.parseBody(scope)
+                       body = p.parseBody()
                        p.expectSemi()
                }
        } else {
@@ -2474,18 +2554,7 @@ func (p *parser) parseFuncDecl() *ast.FuncDecl {
                },
                Body: body,
        }
-       if recv == nil {
-               // Go spec: The scope of an identifier denoting a constant, type,
-               // variable, or function (but not method) declared at top level
-               // (outside any function) is the package block.
-               //
-               // init() functions cannot be referred to and there may
-               // be more than one - don't put them in the pkgScope
-               if ident.Name != "init" {
-                       p.declare(decl, nil, p.pkgScope, ast.Fun, ident)
-               }
-       }
-
+       typeparams.Set(decl.Type, tparams)
        return decl
 }
 
@@ -2546,8 +2615,6 @@ func (p *parser) parseFile() *ast.File {
                return nil
        }
 
-       p.openScope()
-       p.pkgScope = p.topScope
        var decls []ast.Decl
        if p.mode&PackageClauseOnly == 0 {
                // import decls
@@ -2562,30 +2629,22 @@ func (p *parser) parseFile() *ast.File {
                        }
                }
        }
-       p.closeScope()
-       assert(p.topScope == nil, "unbalanced scopes")
-       assert(p.labelScope == nil, "unbalanced label scopes")
 
-       // resolve global identifiers within the same file
-       i := 0
-       for _, ident := range p.unresolved {
-               // i <= index for current ident
-               assert(ident.Obj == unresolved, "object already resolved")
-               ident.Obj = p.pkgScope.Lookup(ident.Name) // also removes unresolved sentinel
-               if ident.Obj == nil {
-                       p.unresolved[i] = ident
-                       i++
-               }
+       f := &ast.File{
+               Doc:      doc,
+               Package:  pos,
+               Name:     ident,
+               Decls:    decls,
+               Imports:  p.imports,
+               Comments: p.comments,
        }
-
-       return &ast.File{
-               Doc:        doc,
-               Package:    pos,
-               Name:       ident,
-               Decls:      decls,
-               Scope:      p.pkgScope,
-               Imports:    p.imports,
-               Unresolved: p.unresolved[0:i],
-               Comments:   p.comments,
+       var declErr func(token.Pos, string)
+       if p.mode&DeclarationErrors != 0 {
+               declErr = p.error
        }
+       if p.mode&SkipObjectResolution == 0 {
+               resolveFile(f, p.file, declErr)
+       }
+
+       return f
 }
index f81bcee969b49d92ba1ec8790bf96d9581a0ed51..6f8a97770bc143aa74ccd2e06be19e92562e7ffa 100644 (file)
@@ -10,6 +10,8 @@ import (
        "testing"
 )
 
+// TODO(rFindley): use a testdata file or file from another package here, to
+//                 avoid a moving target.
 var src = readFile("parser.go")
 
 func readFile(filename string) []byte {
@@ -28,3 +30,27 @@ func BenchmarkParse(b *testing.B) {
                }
        }
 }
+
+func BenchmarkParseOnly(b *testing.B) {
+       b.SetBytes(int64(len(src)))
+       for i := 0; i < b.N; i++ {
+               if _, err := ParseFile(token.NewFileSet(), "", src, ParseComments|SkipObjectResolution); err != nil {
+                       b.Fatalf("benchmark failed due to parse error: %s", err)
+               }
+       }
+}
+
+func BenchmarkResolve(b *testing.B) {
+       b.SetBytes(int64(len(src)))
+       for i := 0; i < b.N; i++ {
+               b.StopTimer()
+               fset := token.NewFileSet()
+               file, err := ParseFile(fset, "", src, SkipObjectResolution)
+               if err != nil {
+                       b.Fatalf("benchmark failed due to parse error: %s", err)
+               }
+               b.StartTimer()
+               handle := fset.File(file.Package)
+               resolveFile(file, handle, nil)
+       }
+}
diff --git a/libgo/go/go/parser/resolver.go b/libgo/go/go/parser/resolver.go
new file mode 100644 (file)
index 0000000..cf92c7e
--- /dev/null
@@ -0,0 +1,556 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package parser
+
+import (
+       "fmt"
+       "go/ast"
+       "go/internal/typeparams"
+       "go/token"
+)
+
+const debugResolve = false
+
+// resolveFile walks the given file to resolve identifiers within the file
+// scope, updating ast.Ident.Obj fields with declaration information.
+//
+// If declErr is non-nil, it is used to report declaration errors during
+// resolution. tok is used to format position in error messages.
+func resolveFile(file *ast.File, handle *token.File, declErr func(token.Pos, string)) {
+       pkgScope := ast.NewScope(nil)
+       r := &resolver{
+               handle:   handle,
+               declErr:  declErr,
+               topScope: pkgScope,
+               pkgScope: pkgScope,
+       }
+
+       for _, decl := range file.Decls {
+               ast.Walk(r, decl)
+       }
+
+       r.closeScope()
+       assert(r.topScope == nil, "unbalanced scopes")
+       assert(r.labelScope == nil, "unbalanced label scopes")
+
+       // resolve global identifiers within the same file
+       i := 0
+       for _, ident := range r.unresolved {
+               // i <= index for current ident
+               assert(ident.Obj == unresolved, "object already resolved")
+               ident.Obj = r.pkgScope.Lookup(ident.Name) // also removes unresolved sentinel
+               if ident.Obj == nil {
+                       r.unresolved[i] = ident
+                       i++
+               } else if debugResolve {
+                       pos := ident.Obj.Decl.(interface{ Pos() token.Pos }).Pos()
+                       r.dump("resolved %s@%v to package object %v", ident.Name, ident.Pos(), pos)
+               }
+       }
+       file.Scope = r.pkgScope
+       file.Unresolved = r.unresolved[0:i]
+}
+
+type resolver struct {
+       handle  *token.File
+       declErr func(token.Pos, string)
+
+       // Ordinary identifier scopes
+       pkgScope   *ast.Scope   // pkgScope.Outer == nil
+       topScope   *ast.Scope   // top-most scope; may be pkgScope
+       unresolved []*ast.Ident // unresolved identifiers
+
+       // Label scopes
+       // (maintained by open/close LabelScope)
+       labelScope  *ast.Scope     // label scope for current function
+       targetStack [][]*ast.Ident // stack of unresolved labels
+}
+
+func (r *resolver) dump(format string, args ...interface{}) {
+       fmt.Println(">>> " + r.sprintf(format, args...))
+}
+
+func (r *resolver) sprintf(format string, args ...interface{}) string {
+       for i, arg := range args {
+               switch arg := arg.(type) {
+               case token.Pos:
+                       args[i] = r.handle.Position(arg)
+               }
+       }
+       return fmt.Sprintf(format, args...)
+}
+
+func (r *resolver) openScope(pos token.Pos) {
+       if debugResolve {
+               r.dump("opening scope @%v", pos)
+       }
+       r.topScope = ast.NewScope(r.topScope)
+}
+
+func (r *resolver) closeScope() {
+       if debugResolve {
+               r.dump("closing scope")
+       }
+       r.topScope = r.topScope.Outer
+}
+
+func (r *resolver) openLabelScope() {
+       r.labelScope = ast.NewScope(r.labelScope)
+       r.targetStack = append(r.targetStack, nil)
+}
+
+func (r *resolver) closeLabelScope() {
+       // resolve labels
+       n := len(r.targetStack) - 1
+       scope := r.labelScope
+       for _, ident := range r.targetStack[n] {
+               ident.Obj = scope.Lookup(ident.Name)
+               if ident.Obj == nil && r.declErr != nil {
+                       r.declErr(ident.Pos(), fmt.Sprintf("label %s undefined", ident.Name))
+               }
+       }
+       // pop label scope
+       r.targetStack = r.targetStack[0:n]
+       r.labelScope = r.labelScope.Outer
+}
+
+func (r *resolver) declare(decl, data interface{}, scope *ast.Scope, kind ast.ObjKind, idents ...*ast.Ident) {
+       for _, ident := range idents {
+               // "type" is used for type lists in interfaces, and is otherwise an invalid
+               // identifier. The 'type' identifier is also artificially duplicated in the
+               // type list, so could cause panics below if we were to proceed.
+               if ident.Name == "type" {
+                       continue
+               }
+               assert(ident.Obj == nil, "identifier already declared or resolved")
+               obj := ast.NewObj(kind, ident.Name)
+               // remember the corresponding declaration for redeclaration
+               // errors and global variable resolution/typechecking phase
+               obj.Decl = decl
+               obj.Data = data
+               ident.Obj = obj
+               if ident.Name != "_" {
+                       if debugResolve {
+                               r.dump("declaring %s@%v", ident.Name, ident.Pos())
+                       }
+                       if alt := scope.Insert(obj); alt != nil && r.declErr != nil {
+                               prevDecl := ""
+                               if pos := alt.Pos(); pos.IsValid() {
+                                       prevDecl = fmt.Sprintf("\n\tprevious declaration at %s", r.handle.Position(pos))
+                               }
+                               r.declErr(ident.Pos(), fmt.Sprintf("%s redeclared in this block%s", ident.Name, prevDecl))
+                       }
+               }
+       }
+}
+
+func (r *resolver) shortVarDecl(decl *ast.AssignStmt) {
+       // Go spec: A short variable declaration may redeclare variables
+       // provided they were originally declared in the same block with
+       // the same type, and at least one of the non-blank variables is new.
+       n := 0 // number of new variables
+       for _, x := range decl.Lhs {
+               if ident, isIdent := x.(*ast.Ident); isIdent {
+                       assert(ident.Obj == nil, "identifier already declared or resolved")
+                       obj := ast.NewObj(ast.Var, ident.Name)
+                       // remember corresponding assignment for other tools
+                       obj.Decl = decl
+                       ident.Obj = obj
+                       if ident.Name != "_" {
+                               if debugResolve {
+                                       r.dump("declaring %s@%v", ident.Name, ident.Pos())
+                               }
+                               if alt := r.topScope.Insert(obj); alt != nil {
+                                       ident.Obj = alt // redeclaration
+                               } else {
+                                       n++ // new declaration
+                               }
+                       }
+               }
+       }
+       if n == 0 && r.declErr != nil {
+               r.declErr(decl.Lhs[0].Pos(), "no new variables on left side of :=")
+       }
+}
+
+// The unresolved object is a sentinel to mark identifiers that have been added
+// to the list of unresolved identifiers. The sentinel is only used for verifying
+// internal consistency.
+var unresolved = new(ast.Object)
+
+// If x is an identifier, resolve attempts to resolve x by looking up
+// the object it denotes. If no object is found and collectUnresolved is
+// set, x is marked as unresolved and collected in the list of unresolved
+// identifiers.
+//
+func (r *resolver) resolve(ident *ast.Ident, collectUnresolved bool) {
+       if ident.Obj != nil {
+               panic(fmt.Sprintf("%s: identifier %s already declared or resolved", r.handle.Position(ident.Pos()), ident.Name))
+       }
+       // '_' and 'type' should never refer to existing declarations: '_' because it
+       // has special handling in the spec, and 'type' because it is a keyword, and
+       // only valid in an interface type list.
+       if ident.Name == "_" || ident.Name == "type" {
+               return
+       }
+       for s := r.topScope; s != nil; s = s.Outer {
+               if obj := s.Lookup(ident.Name); obj != nil {
+                       assert(obj.Name != "", "obj with no name")
+                       ident.Obj = obj
+                       return
+               }
+       }
+       // all local scopes are known, so any unresolved identifier
+       // must be found either in the file scope, package scope
+       // (perhaps in another file), or universe scope --- collect
+       // them so that they can be resolved later
+       if collectUnresolved {
+               ident.Obj = unresolved
+               r.unresolved = append(r.unresolved, ident)
+       }
+}
+
+func (r *resolver) walkExprs(list []ast.Expr) {
+       for _, node := range list {
+               ast.Walk(r, node)
+       }
+}
+
+func (r *resolver) walkLHS(list []ast.Expr) {
+       for _, expr := range list {
+               expr := unparen(expr)
+               if _, ok := expr.(*ast.Ident); !ok && expr != nil {
+                       ast.Walk(r, expr)
+               }
+       }
+}
+
+func (r *resolver) walkStmts(list []ast.Stmt) {
+       for _, stmt := range list {
+               ast.Walk(r, stmt)
+       }
+}
+
+func (r *resolver) Visit(node ast.Node) ast.Visitor {
+       if debugResolve && node != nil {
+               r.dump("node %T@%v", node, node.Pos())
+       }
+
+       switch n := node.(type) {
+
+       // Expressions.
+       case *ast.Ident:
+               r.resolve(n, true)
+
+       case *ast.FuncLit:
+               r.openScope(n.Pos())
+               defer r.closeScope()
+               r.walkFuncType(n.Type)
+               r.walkBody(n.Body)
+
+       case *ast.SelectorExpr:
+               ast.Walk(r, n.X)
+               // Note: don't try to resolve n.Sel, as we don't support qualified
+               // resolution.
+
+       case *ast.StructType:
+               r.openScope(n.Pos())
+               defer r.closeScope()
+               r.walkFieldList(n.Fields, ast.Var)
+
+       case *ast.FuncType:
+               r.openScope(n.Pos())
+               defer r.closeScope()
+               r.walkFuncType(n)
+
+       case *ast.CompositeLit:
+               if n.Type != nil {
+                       ast.Walk(r, n.Type)
+               }
+               for _, e := range n.Elts {
+                       if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
+                               // See issue #45160: try to resolve composite lit keys, but don't
+                               // collect them as unresolved if resolution failed. This replicates
+                               // existing behavior when resolving during parsing.
+                               if ident, _ := kv.Key.(*ast.Ident); ident != nil {
+                                       r.resolve(ident, false)
+                               } else {
+                                       ast.Walk(r, kv.Key)
+                               }
+                               ast.Walk(r, kv.Value)
+                       } else {
+                               ast.Walk(r, e)
+                       }
+               }
+
+       case *ast.InterfaceType:
+               r.openScope(n.Pos())
+               defer r.closeScope()
+               r.walkFieldList(n.Methods, ast.Fun)
+
+       // Statements
+       case *ast.LabeledStmt:
+               r.declare(n, nil, r.labelScope, ast.Lbl, n.Label)
+               ast.Walk(r, n.Stmt)
+
+       case *ast.AssignStmt:
+               r.walkExprs(n.Rhs)
+               if n.Tok == token.DEFINE {
+                       r.shortVarDecl(n)
+               } else {
+                       r.walkExprs(n.Lhs)
+               }
+
+       case *ast.BranchStmt:
+               // add to list of unresolved targets
+               if n.Tok != token.FALLTHROUGH && n.Label != nil {
+                       depth := len(r.targetStack) - 1
+                       r.targetStack[depth] = append(r.targetStack[depth], n.Label)
+               }
+
+       case *ast.BlockStmt:
+               r.openScope(n.Pos())
+               defer r.closeScope()
+               r.walkStmts(n.List)
+
+       case *ast.IfStmt:
+               r.openScope(n.Pos())
+               defer r.closeScope()
+               if n.Init != nil {
+                       ast.Walk(r, n.Init)
+               }
+               ast.Walk(r, n.Cond)
+               ast.Walk(r, n.Body)
+               if n.Else != nil {
+                       ast.Walk(r, n.Else)
+               }
+
+       case *ast.CaseClause:
+               r.walkExprs(n.List)
+               r.openScope(n.Pos())
+               defer r.closeScope()
+               r.walkStmts(n.Body)
+
+       case *ast.SwitchStmt:
+               r.openScope(n.Pos())
+               defer r.closeScope()
+               if n.Init != nil {
+                       ast.Walk(r, n.Init)
+               }
+               if n.Tag != nil {
+                       // The scope below reproduces some unnecessary behavior of the parser,
+                       // opening an extra scope in case this is a type switch. It's not needed
+                       // for expression switches.
+                       // TODO: remove this once we've matched the parser resolution exactly.
+                       if n.Init != nil {
+                               r.openScope(n.Tag.Pos())
+                               defer r.closeScope()
+                       }
+                       ast.Walk(r, n.Tag)
+               }
+               if n.Body != nil {
+                       r.walkStmts(n.Body.List)
+               }
+
+       case *ast.TypeSwitchStmt:
+               if n.Init != nil {
+                       r.openScope(n.Pos())
+                       defer r.closeScope()
+                       ast.Walk(r, n.Init)
+               }
+               r.openScope(n.Assign.Pos())
+               defer r.closeScope()
+               ast.Walk(r, n.Assign)
+               // s.Body consists only of case clauses, so does not get its own
+               // scope.
+               if n.Body != nil {
+                       r.walkStmts(n.Body.List)
+               }
+
+       case *ast.CommClause:
+               r.openScope(n.Pos())
+               defer r.closeScope()
+               if n.Comm != nil {
+                       ast.Walk(r, n.Comm)
+               }
+               r.walkStmts(n.Body)
+
+       case *ast.SelectStmt:
+               // as for switch statements, select statement bodies don't get their own
+               // scope.
+               if n.Body != nil {
+                       r.walkStmts(n.Body.List)
+               }
+
+       case *ast.ForStmt:
+               r.openScope(n.Pos())
+               defer r.closeScope()
+               if n.Init != nil {
+                       ast.Walk(r, n.Init)
+               }
+               if n.Cond != nil {
+                       ast.Walk(r, n.Cond)
+               }
+               if n.Post != nil {
+                       ast.Walk(r, n.Post)
+               }
+               ast.Walk(r, n.Body)
+
+       case *ast.RangeStmt:
+               r.openScope(n.Pos())
+               defer r.closeScope()
+               ast.Walk(r, n.X)
+               var lhs []ast.Expr
+               if n.Key != nil {
+                       lhs = append(lhs, n.Key)
+               }
+               if n.Value != nil {
+                       lhs = append(lhs, n.Value)
+               }
+               if len(lhs) > 0 {
+                       if n.Tok == token.DEFINE {
+                               // Note: we can't exactly match the behavior of object resolution
+                               // during the parsing pass here, as it uses the position of the RANGE
+                               // token for the RHS OpPos. That information is not contained within
+                               // the AST.
+                               as := &ast.AssignStmt{
+                                       Lhs:    lhs,
+                                       Tok:    token.DEFINE,
+                                       TokPos: n.TokPos,
+                                       Rhs:    []ast.Expr{&ast.UnaryExpr{Op: token.RANGE, X: n.X}},
+                               }
+                               // TODO(rFindley): this walkLHS reproduced the parser resolution, but
+                               // is it necessary? By comparison, for a normal AssignStmt we don't
+                               // walk the LHS in case there is an invalid identifier list.
+                               r.walkLHS(lhs)
+                               r.shortVarDecl(as)
+                       } else {
+                               r.walkExprs(lhs)
+                       }
+               }
+               ast.Walk(r, n.Body)
+
+       // Declarations
+       case *ast.GenDecl:
+               switch n.Tok {
+               case token.CONST, token.VAR:
+                       for i, spec := range n.Specs {
+                               spec := spec.(*ast.ValueSpec)
+                               kind := ast.Con
+                               if n.Tok == token.VAR {
+                                       kind = ast.Var
+                               }
+                               r.walkExprs(spec.Values)
+                               if spec.Type != nil {
+                                       ast.Walk(r, spec.Type)
+                               }
+                               r.declare(spec, i, r.topScope, kind, spec.Names...)
+                       }
+               case token.TYPE:
+                       for _, spec := range n.Specs {
+                               spec := spec.(*ast.TypeSpec)
+                               // Go spec: The scope of a type identifier declared inside a function begins
+                               // at the identifier in the TypeSpec and ends at the end of the innermost
+                               // containing block.
+                               r.declare(spec, nil, r.topScope, ast.Typ, spec.Name)
+                               if tparams := typeparams.Get(spec); tparams != nil {
+                                       r.openScope(spec.Pos())
+                                       defer r.closeScope()
+                                       r.walkTParams(tparams)
+                               }
+                               ast.Walk(r, spec.Type)
+                       }
+               }
+
+       case *ast.FuncDecl:
+               // Open the function scope.
+               r.openScope(n.Pos())
+               defer r.closeScope()
+
+               // Resolve the receiver first, without declaring.
+               r.resolveList(n.Recv)
+
+               // Type parameters are walked normally: they can reference each other, and
+               // can be referenced by normal parameters.
+               if tparams := typeparams.Get(n.Type); tparams != nil {
+                       r.walkTParams(tparams)
+                       // TODO(rFindley): need to address receiver type parameters.
+               }
+
+               // Resolve and declare parameters in a specific order to get duplicate
+               // declaration errors in the correct location.
+               r.resolveList(n.Type.Params)
+               r.resolveList(n.Type.Results)
+               r.declareList(n.Recv, ast.Var)
+               r.declareList(n.Type.Params, ast.Var)
+               r.declareList(n.Type.Results, ast.Var)
+
+               r.walkBody(n.Body)
+               if n.Recv == nil && n.Name.Name != "init" {
+                       r.declare(n, nil, r.pkgScope, ast.Fun, n.Name)
+               }
+
+       default:
+               return r
+       }
+
+       return nil
+}
+
+func (r *resolver) walkFuncType(typ *ast.FuncType) {
+       // typ.TParams must be walked separately for FuncDecls.
+       r.resolveList(typ.Params)
+       r.resolveList(typ.Results)
+       r.declareList(typ.Params, ast.Var)
+       r.declareList(typ.Results, ast.Var)
+}
+
+func (r *resolver) resolveList(list *ast.FieldList) {
+       if list == nil {
+               return
+       }
+       for _, f := range list.List {
+               if f.Type != nil {
+                       ast.Walk(r, f.Type)
+               }
+       }
+}
+
+func (r *resolver) declareList(list *ast.FieldList, kind ast.ObjKind) {
+       if list == nil {
+               return
+       }
+       for _, f := range list.List {
+               r.declare(f, nil, r.topScope, kind, f.Names...)
+       }
+}
+
+func (r *resolver) walkFieldList(list *ast.FieldList, kind ast.ObjKind) {
+       if list == nil {
+               return
+       }
+       r.resolveList(list)
+       r.declareList(list, kind)
+}
+
+// walkTParams is like walkFieldList, but declares type parameters eagerly so
+// that they may be resolved in the constraint expressions held in the field
+// Type.
+func (r *resolver) walkTParams(list *ast.FieldList) {
+       if list == nil {
+               return
+       }
+       r.declareList(list, ast.Typ)
+       r.resolveList(list)
+}
+
+func (r *resolver) walkBody(body *ast.BlockStmt) {
+       if body == nil {
+               return
+       }
+       r.openLabelScope()
+       defer r.closeLabelScope()
+       r.walkStmts(body.List)
+}
diff --git a/libgo/go/go/parser/resolver_test.go b/libgo/go/go/parser/resolver_test.go
new file mode 100644 (file)
index 0000000..625c009
--- /dev/null
@@ -0,0 +1,180 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package parser
+
+import (
+       "fmt"
+       "go/ast"
+       "go/internal/typeparams"
+       "go/scanner"
+       "go/token"
+       "os"
+       "path/filepath"
+       "strings"
+       "testing"
+)
+
+// TestResolution checks that identifiers are resolved to the declarations
+// annotated in the source, by comparing the positions of the resulting
+// Ident.Obj.Decl to positions marked in the source via special comments.
+//
+// In the test source, any comment prefixed with '=' or '@' (or both) marks the
+// previous token position as the declaration ('=') or a use ('@') of an
+// identifier. The text following '=' and '@' in the comment string is the
+// label to use for the location.  Declaration labels must be unique within the
+// file, and use labels must refer to an existing declaration label. It's OK
+// for a comment to denote both the declaration and use of a label (e.g.
+// '=@foo'). Leading and trailing whitespace is ignored. Any comment not
+// beginning with '=' or '@' is ignored.
+func TestResolution(t *testing.T) {
+       dir := filepath.Join("testdata", "resolution")
+       fis, err := os.ReadDir(dir)
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       for _, fi := range fis {
+               t.Run(fi.Name(), func(t *testing.T) {
+                       fset := token.NewFileSet()
+                       path := filepath.Join(dir, fi.Name())
+                       src := readFile(path) // panics on failure
+                       var mode Mode
+                       if strings.HasSuffix(path, ".go2") {
+                               if !typeparams.Enabled {
+                                       t.Skip("type params are not enabled")
+                               }
+                       } else {
+                               mode |= typeparams.DisallowParsing
+                       }
+                       file, err := ParseFile(fset, path, src, mode)
+                       if err != nil {
+                               t.Fatal(err)
+                       }
+
+                       // Compare the positions of objects resolved during parsing (fromParser)
+                       // to those annotated in source comments (fromComments).
+
+                       handle := fset.File(file.Package)
+                       fromParser := declsFromParser(file)
+                       fromComments := declsFromComments(handle, src)
+
+                       pos := func(pos token.Pos) token.Position {
+                               p := handle.Position(pos)
+                               // The file name is implied by the subtest, so remove it to avoid
+                               // clutter in error messages.
+                               p.Filename = ""
+                               return p
+                       }
+                       for k, want := range fromComments {
+                               if got := fromParser[k]; got != want {
+                                       t.Errorf("%s resolved to %s, want %s", pos(k), pos(got), pos(want))
+                               }
+                               delete(fromParser, k)
+                       }
+                       // What remains in fromParser are unexpected resolutions.
+                       for k, got := range fromParser {
+                               t.Errorf("%s resolved to %s, want no object", pos(k), pos(got))
+                       }
+               })
+       }
+}
+
+// declsFromParser walks the file and collects the map associating an
+// identifier position with its declaration position.
+func declsFromParser(file *ast.File) map[token.Pos]token.Pos {
+       objmap := map[token.Pos]token.Pos{}
+       ast.Inspect(file, func(node ast.Node) bool {
+               // Ignore blank identifiers to reduce noise.
+               if ident, _ := node.(*ast.Ident); ident != nil && ident.Obj != nil && ident.Name != "_" {
+                       objmap[ident.Pos()] = ident.Obj.Pos()
+               }
+               return true
+       })
+       return objmap
+}
+
+// declsFromComments looks at comments annotating uses and declarations, and
+// maps each identifier use to its corresponding declaration. See the
+// description of these annotations in the documentation for TestResolution.
+func declsFromComments(handle *token.File, src []byte) map[token.Pos]token.Pos {
+       decls, uses := positionMarkers(handle, src)
+
+       objmap := make(map[token.Pos]token.Pos)
+       // Join decls and uses on name, to build the map of use->decl.
+       for name, posns := range uses {
+               declpos, ok := decls[name]
+               if !ok {
+                       panic(fmt.Sprintf("missing declaration for %s", name))
+               }
+               for _, pos := range posns {
+                       objmap[pos] = declpos
+               }
+       }
+       return objmap
+}
+
+// positionMarkers extracts named positions from the source denoted by comments
+// prefixed with '=' (declarations) and '@' (uses): for example '@foo' or
+// '=@bar'. It returns a map of name->position for declarations, and
+// name->position(s) for uses.
+func positionMarkers(handle *token.File, src []byte) (decls map[string]token.Pos, uses map[string][]token.Pos) {
+       var s scanner.Scanner
+       s.Init(handle, src, nil, scanner.ScanComments)
+       decls = make(map[string]token.Pos)
+       uses = make(map[string][]token.Pos)
+       var prev token.Pos // position of last non-comment, non-semicolon token
+
+scanFile:
+       for {
+               pos, tok, lit := s.Scan()
+               switch tok {
+               case token.EOF:
+                       break scanFile
+               case token.COMMENT:
+                       name, decl, use := annotatedObj(lit)
+                       if len(name) > 0 {
+                               if decl {
+                                       if _, ok := decls[name]; ok {
+                                               panic(fmt.Sprintf("duplicate declaration markers for %s", name))
+                                       }
+                                       decls[name] = prev
+                               }
+                               if use {
+                                       uses[name] = append(uses[name], prev)
+                               }
+                       }
+               case token.SEMICOLON:
+                       // ignore automatically inserted semicolon
+                       if lit == "\n" {
+                               continue scanFile
+                       }
+                       fallthrough
+               default:
+                       prev = pos
+               }
+       }
+       return decls, uses
+}
+
+func annotatedObj(lit string) (name string, decl, use bool) {
+       if lit[1] == '*' {
+               lit = lit[:len(lit)-2] // strip trailing */
+       }
+       lit = strings.TrimSpace(lit[2:])
+
+scanLit:
+       for idx, r := range lit {
+               switch r {
+               case '=':
+                       decl = true
+               case '@':
+                       use = true
+               default:
+                       name = lit[idx:]
+                       break scanLit
+               }
+       }
+       return
+}
index 49bb681e09e66ea275934c5d85dd2f95925fb4b4..67fef15665583db4e4a1ba7aad93a081b8c9bfc9 100644 (file)
@@ -6,7 +6,10 @@
 
 package parser
 
-import "testing"
+import (
+       "go/internal/typeparams"
+       "testing"
+)
 
 var valids = []string{
        "package p\n",
@@ -48,12 +51,104 @@ var valids = []string{
        `package p; var _ = map[*P]int{&P{}:0, {}:1}`,
        `package p; type T = int`,
        `package p; type (T = p.T; _ = struct{}; x = *T)`,
+       `package p; type T (*int)`,
+       `package p; type _ struct{ ((int)) }`,
+       `package p; type _ struct{ (*(int)) }`,
+       `package p; type _ struct{ ([]byte) }`, // disallowed by type-checker
+       `package p; var _ = func()T(nil)`,
+       `package p; func _(T (P))`,
+       `package p; func _(T []E)`,
+       `package p; func _(T [P]E)`,
+       `package p; type _ [A+B]struct{}`,
+       `package p; func (R) _()`,
+       `package p; type _ struct{ f [n]E }`,
+       `package p; type _ struct{ f [a+b+c+d]E }`,
+       `package p; type I1 interface{}; type I2 interface{ I1 }`,
+}
+
+// validWithTParamsOnly holds source code examples that are valid if
+// parseTypeParams is set, but invalid if not. When checking with the
+// parseTypeParams set, errors are ignored.
+var validWithTParamsOnly = []string{
+       `package p; type _ []T[ /* ERROR "expected ';', found '\['" */ int]`,
+       `package p; type T[P any /* ERROR "expected ']', found any" */ ] struct { P }`,
+       `package p; type T[P comparable /* ERROR "expected ']', found comparable" */ ] struct { P }`,
+       `package p; type T[P comparable /* ERROR "expected ']', found comparable" */ [P]] struct { P }`,
+       `package p; type T[P1, /* ERROR "expected ']', found ','" */ P2 any] struct { P1; f []P2 }`,
+       `package p; func _[ /* ERROR "expected '\(', found '\['" */ T any]()()`,
+       `package p; func _(T (P))`,
+       `package p; func f[ /* ERROR "expected '\(', found '\['" */ A, B any](); func _() { _ = f[int, int] }`,
+       `package p; func _(x /* ERROR "mixed named and unnamed parameters" */ T[P1, P2, P3])`,
+       `package p; func _(x /* ERROR "mixed named and unnamed parameters" */ p.T[Q])`,
+       `package p; func _(p.T[ /* ERROR "missing ',' in parameter list" */ Q])`,
+       `package p; type _[A interface /* ERROR "expected ']', found 'interface'" */ {},] struct{}`,
+       `package p; type _[A interface /* ERROR "expected ']', found 'interface'" */ {}] struct{}`,
+       `package p; type _[A, /* ERROR "expected ']', found ','" */  B any,] struct{}`,
+       `package p; type _[A, /* ERROR "expected ']', found ','" */ B any] struct{}`,
+       `package p; type _[A any /* ERROR "expected ']', found any" */,] struct{}`,
+       `package p; type _[A any /* ERROR "expected ']', found any" */ ]struct{}`,
+       `package p; type _[A any /* ERROR "expected ']', found any" */ ] struct{ A }`,
+       `package p; func _[ /* ERROR "expected '\(', found '\['" */ T any]()`,
+       `package p; func _[ /* ERROR "expected '\(', found '\['" */ T any](x T)`,
+       `package p; func _[ /* ERROR "expected '\(', found '\['" */ T1, T2 any](x T)`,
+       `package p; func _[ /* ERROR "expected '\(', found '\['" */ A, B any](a A) B`,
+       `package p; func _[ /* ERROR "expected '\(', found '\['" */ A, B C](a A) B`,
+       `package p; func _[ /* ERROR "expected '\(', found '\['" */ A, B C[A, B]](a A) B`,
+       `package p; func (T) _[ /* ERROR "expected '\(', found '\['" */ A, B any](a A) B`,
+       `package p; func (T) _[ /* ERROR "expected '\(', found '\['" */ A, B C](a A) B`,
+       `package p; func (T) _[ /* ERROR "expected '\(', found '\['" */ A, B C[A, B]](a A) B`,
+       `package p; type _[A, /* ERROR "expected ']', found ','" */ B any] interface { _(a A) B }`,
+       `package p; type _[A, /* ERROR "expected ']', found ','" */ B C[A, B]] interface { _(a A) B }`,
+       `package p; func _[ /* ERROR "expected '\(', found '\['" */ T1, T2 interface{}](x T1) T2`,
+       `package p; func _[ /* ERROR "expected '\(', found '\['" */ T1 interface{ m() }, T2, T3 interface{}](x T1, y T3) T2`,
+       `package p; var _ = [ /* ERROR "expected expression" */ ]T[int]{}`,
+       `package p; var _ = [ /* ERROR "expected expression" */ 10]T[int]{}`,
+       `package p; var _ = func /* ERROR "expected expression" */ ()T[int]{}`,
+       `package p; var _ = map /* ERROR "expected expression" */ [T[int]]T[int]{}`,
+       `package p; var _ = chan /* ERROR "expected expression" */ T[int](x)`,
+       `package p; func _(_ T[ /* ERROR "missing ',' in parameter list" */ P], T P) T[P]`,
+       `package p; var _ T[ /* ERROR "expected ';', found '\['" */ chan int]`,
+
+       // TODO(rfindley) this error message could be improved.
+       `package p; func (_ /* ERROR "mixed named and unnamed parameters" */ R[P]) _[T any](x T)`,
+       `package p; func (_ /* ERROR "mixed named and unnamed parameters" */ R[ P, Q]) _[T1, T2 any](x T)`,
+
+       `package p; func (R[P] /* ERROR "missing element type" */ ) _[T any]()`,
+       `package p; func _(T[P] /* ERROR "missing element type" */ )`,
+       `package p; func _(T[P1, /* ERROR "expected ']', found ','" */ P2, P3 ])`,
+       `package p; func _(T[P] /* ERROR "missing element type" */ ) T[P]`,
+       `package p; type _ struct{ T[P] /* ERROR "missing element type" */ }`,
+       `package p; type _ struct{ T[struct /* ERROR "expected expression" */ {a, b, c int}] }`,
+       `package p; type _ interface{type /* ERROR "expected '}', found 'type'" */ int}`,
+       `package p; type _ interface{type /* ERROR "expected '}', found 'type'" */ int, float32; type bool; m(); type string;}`,
+       `package p; type I1[T any /* ERROR "expected ']', found any" */ ] interface{}; type I2 interface{ I1[int] }`,
+       `package p; type I1[T any /* ERROR "expected ']', found any" */ ] interface{}; type I2[T any] interface{ I1[T] }`,
+       `package p; type _ interface { f[ /* ERROR "expected ';', found '\['" */ T any]() }`,
 }
 
 func TestValid(t *testing.T) {
-       for _, src := range valids {
-               checkErrors(t, src, src)
-       }
+       t.Run("no tparams", func(t *testing.T) {
+               for _, src := range valids {
+                       checkErrors(t, src, src, DeclarationErrors|AllErrors, false)
+               }
+       })
+       t.Run("tparams", func(t *testing.T) {
+               if !typeparams.Enabled {
+                       t.Skip("type params are not enabled")
+               }
+               for _, src := range valids {
+                       checkErrors(t, src, src, DeclarationErrors|AllErrors, false)
+               }
+               for _, src := range validWithTParamsOnly {
+                       checkErrors(t, src, src, DeclarationErrors|AllErrors, false)
+               }
+       })
+}
+
+// TestSingle is useful to track down a problem with a single short test program.
+func TestSingle(t *testing.T) {
+       const src = `package p; var _ = T{}`
+       checkErrors(t, src, src, DeclarationErrors|AllErrors, true)
 }
 
 var invalids = []string{
@@ -79,7 +174,6 @@ var invalids = []string{
        `package p; var a = chan /* ERROR "expected expression" */ int;`,
        `package p; var a = []int{[ /* ERROR "expected expression" */ ]int};`,
        `package p; var a = ( /* ERROR "expected expression" */ []int);`,
-       `package p; var a = a[[ /* ERROR "expected expression" */ ]int:[]int];`,
        `package p; var a = <- /* ERROR "expected expression" */ chan int;`,
        `package p; func f() { select { case _ <- chan /* ERROR "expected expression" */ int: } };`,
        `package p; func f() { _ = (<-<- /* ERROR "expected 'chan'" */ chan int)(nil) };`,
@@ -102,7 +196,14 @@ var invalids = []string{
        `package p; func f() { go f /* ERROR HERE "function must be invoked" */ }`,
        `package p; func f() { defer func() {} /* ERROR HERE "function must be invoked" */ }`,
        `package p; func f() { go func() { func() { f(x func /* ERROR "missing ','" */ (){}) } } }`,
-       `package p; func f(x func(), u v func /* ERROR "missing ','" */ ()){}`,
+       `package p; func _() (type /* ERROR "found 'type'" */ T)(T)`,
+       `package p; func (type /* ERROR "found 'type'" */ T)(T) _()`,
+       `package p; type _[A+B, /* ERROR "expected ']'" */ ] int`,
+
+       // TODO: this error should be positioned on the ':'
+       `package p; var a = a[[]int:[ /* ERROR "expected expression" */ ]int];`,
+       // TODO: the compiler error is better here: "cannot parenthesize embedded type"
+       `package p; type I1 interface{}; type I2 interface{ (/* ERROR "expected '}', found '\('" */ I1) }`,
 
        // issue 8656
        `package p; func f() (a b string /* ERROR "missing ','" */ , ok bool)`,
@@ -118,19 +219,61 @@ var invalids = []string{
        `package p; var _ = struct { x int, /* ERROR "expected ';', found ','" */ y float }{};`,
 
        // issue 11611
-       `package p; type _ struct { int, } /* ERROR "expected type, found '}'" */ ;`,
+       `package p; type _ struct { int, } /* ERROR "expected 'IDENT', found '}'" */ ;`,
        `package p; type _ struct { int, float } /* ERROR "expected type, found '}'" */ ;`,
-       `package p; type _ struct { ( /* ERROR "expected anonymous field" */ int) };`,
-       `package p; func _()(x, y, z ... /* ERROR "expected '\)', found '...'" */ int){}`,
-       `package p; func _()(... /* ERROR "expected type, found '...'" */ int){}`,
 
        // issue 13475
        `package p; func f() { if true {} else ; /* ERROR "expected if statement or block" */ }`,
        `package p; func f() { if true {} else defer /* ERROR "expected if statement or block" */ f() }`,
 }
 
+// invalidNoTParamErrs holds invalid source code examples annotated with the
+// error messages produced when ParseTypeParams is not set.
+var invalidNoTParamErrs = []string{
+       `package p; type _[_ any /* ERROR "expected ']', found any" */ ] int; var _ = T[]{}`,
+       `package p; type T[P any /* ERROR "expected ']', found any" */ ] = T0`,
+       `package p; var _ func[ /* ERROR "expected '\(', found '\['" */ T any](T)`,
+       `package p; func _[ /* ERROR "expected '\(', found '\['" */ ]()`,
+       `package p; type _[A, /* ERROR "expected ']', found ','" */] struct{ A }`,
+       `package p; func _[ /* ERROR "expected '\(', found '\['" */ type P, *Q interface{}]()`,
+}
+
+// invalidTParamErrs holds invalid source code examples annotated with the
+// error messages produced when ParseTypeParams is set.
+var invalidTParamErrs = []string{
+       `package p; type _[_ any] int; var _ = T[] /* ERROR "expected operand" */ {}`,
+       `package p; type T[P any] = /* ERROR "cannot be alias" */ T0`,
+       `package p; var _ func[ /* ERROR "cannot have type parameters" */ T any](T)`,
+       `package p; func _[]/* ERROR "empty type parameter list" */()`,
+
+       // TODO(rfindley) a better location would be after the ']'
+       `package p; type _[A/* ERROR "all type parameters must be named" */,] struct{ A }`,
+
+       // TODO(rfindley) this error is confusing.
+       `package p; func _[type /* ERROR "all type parameters must be named" */P, *Q interface{}]()`,
+}
+
 func TestInvalid(t *testing.T) {
-       for _, src := range invalids {
-               checkErrors(t, src, src)
-       }
+       t.Run("no tparams", func(t *testing.T) {
+               for _, src := range invalids {
+                       checkErrors(t, src, src, DeclarationErrors|AllErrors|typeparams.DisallowParsing, true)
+               }
+               for _, src := range validWithTParamsOnly {
+                       checkErrors(t, src, src, DeclarationErrors|AllErrors|typeparams.DisallowParsing, true)
+               }
+               for _, src := range invalidNoTParamErrs {
+                       checkErrors(t, src, src, DeclarationErrors|AllErrors|typeparams.DisallowParsing, true)
+               }
+       })
+       t.Run("tparams", func(t *testing.T) {
+               if !typeparams.Enabled {
+                       t.Skip("type params are not enabled")
+               }
+               for _, src := range invalids {
+                       checkErrors(t, src, src, DeclarationErrors|AllErrors, true)
+               }
+               for _, src := range invalidTParamErrs {
+                       checkErrors(t, src, src, DeclarationErrors|AllErrors, true)
+               }
+       })
 }
diff --git a/libgo/go/go/parser/testdata/chans.go2 b/libgo/go/go/parser/testdata/chans.go2
new file mode 100644 (file)
index 0000000..fad2bce
--- /dev/null
@@ -0,0 +1,62 @@
+package chans
+
+import "runtime"
+
+// Ranger returns a Sender and a Receiver. The Receiver provides a
+// Next method to retrieve values. The Sender provides a Send method
+// to send values and a Close method to stop sending values. The Next
+// method indicates when the Sender has been closed, and the Send
+// method indicates when the Receiver has been freed.
+//
+// This is a convenient way to exit a goroutine sending values when
+// the receiver stops reading them.
+func Ranger[T any]() (*Sender[T], *Receiver[T]) {
+       c := make(chan T)
+       d := make(chan bool)
+       s := &Sender[T]{values: c, done: d}
+       r := &Receiver[T]{values: c, done: d}
+       runtime.SetFinalizer(r, r.finalize)
+       return s, r
+}
+
+// A sender is used to send values to a Receiver.
+type Sender[T any] struct {
+       values chan<- T
+       done <-chan bool
+}
+
+// Send sends a value to the receiver. It returns whether any more
+// values may be sent; if it returns false the value was not sent.
+func (s *Sender[T]) Send(v T) bool {
+       select {
+       case s.values <- v:
+               return true
+       case <-s.done:
+               return false
+       }
+}
+
+// Close tells the receiver that no more values will arrive.
+// After Close is called, the Sender may no longer be used.
+func (s *Sender[T]) Close() {
+       close(s.values)
+}
+
+// A Receiver receives values from a Sender.
+type Receiver[T any] struct {
+       values <-chan T
+       done chan<- bool
+}
+
+// Next returns the next value from the channel. The bool result
+// indicates whether the value is valid, or whether the Sender has
+// been closed and no more values will be received.
+func (r *Receiver[T]) Next() (T, bool) {
+       v, ok := <-r.values
+       return v, ok
+}
+
+// finalize is a finalizer for the receiver.
+func (r *Receiver[T]) finalize() {
+       close(r.done)
+}
diff --git a/libgo/go/go/parser/testdata/issue11377.src b/libgo/go/go/parser/testdata/issue11377.src
new file mode 100644 (file)
index 0000000..1c43800
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test case for issue 11377: Better synchronization of
+// parser after certain syntax errors.
+
+package p
+
+func bad1() {
+    if f()) /* ERROR "expected ';', found '\)'" */ {
+        return
+    }
+}
+
+// There shouldn't be any errors down below.
+
+func F1() {}
+func F2() {}
+func F3() {}
+func F4() {}
+func F5() {}
+func F6() {}
+func F7() {}
+func F8() {}
+func F9() {}
+func F10() {}
diff --git a/libgo/go/go/parser/testdata/issue23434.src b/libgo/go/go/parser/testdata/issue23434.src
new file mode 100644 (file)
index 0000000..24a0832
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test case for issue 23434: Better synchronization of
+// parser after missing type. There should be exactly
+// one error each time, with now follow errors.
+
+package p
+
+func g() {
+       m := make(map[string]! /* ERROR "expected type, found '!'" */ )
+       for {
+               x := 1
+               print(x)
+       }
+}
+
+func f() {
+       m := make(map[string]) /* ERROR "expected type, found '\)'" */
+       for {
+               x := 1
+               print(x)
+       }
+}
diff --git a/libgo/go/go/parser/testdata/issue34946.src b/libgo/go/go/parser/testdata/issue34946.src
new file mode 100644 (file)
index 0000000..6bb15e1
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test case for issue 34946: Better synchronization of
+// parser for function declarations that start their
+// body's opening { on a new line.
+
+package p
+
+// accept Allman/BSD-style declaration but complain
+// (implicit semicolon between signature and body)
+func _() int
+{ /* ERROR "unexpected semicolon or newline before {" */
+       { return 0 }
+}
+
+func _() {}
+
+func _(); { /* ERROR "unexpected semicolon or newline before {" */ }
+
+func _() {}
diff --git a/libgo/go/go/parser/testdata/issue44504.src b/libgo/go/go/parser/testdata/issue44504.src
new file mode 100644 (file)
index 0000000..7791f4a
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test case for issue 44504: panic due to duplicate resolution of slice/index
+// operands. We should not try to resolve a LHS expression with invalid syntax.
+
+package p
+
+func _() {
+  var items []bool
+  items[] /* ERROR "operand" */ = false
+}
diff --git a/libgo/go/go/parser/testdata/linalg.go2 b/libgo/go/go/parser/testdata/linalg.go2
new file mode 100644 (file)
index 0000000..fba0d02
--- /dev/null
@@ -0,0 +1,83 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package linalg
+
+import "math"
+
+// Numeric is type bound that matches any numeric type.
+// It would likely be in a constraints package in the standard library.
+type Numeric interface {
+       type int, int8, int16, int32, int64,
+               uint, uint8, uint16, uint32, uint64, uintptr,
+               float32, float64,
+               complex64, complex128
+}
+
+func DotProduct[T Numeric](s1, s2 []T) T {
+       if len(s1) != len(s2) {
+               panic("DotProduct: slices of unequal length")
+       }
+       var r T
+       for i := range s1 {
+               r += s1[i] * s2[i]
+       }
+       return r
+}
+
+// NumericAbs matches numeric types with an Abs method.
+type NumericAbs[T any] interface {
+       Numeric
+
+       Abs() T
+}
+
+// AbsDifference computes the absolute value of the difference of
+// a and b, where the absolute value is determined by the Abs method.
+func AbsDifference[T NumericAbs](a, b T) T {
+       d := a - b
+       return d.Abs()
+}
+
+// OrderedNumeric is a type bound that matches numeric types that support the < operator.
+type OrderedNumeric interface {
+       type int, int8, int16, int32, int64,
+               uint, uint8, uint16, uint32, uint64, uintptr,
+               float32, float64
+}
+
+// Complex is a type bound that matches the two complex types, which do not have a < operator.
+type Complex interface {
+       type complex64, complex128
+}
+
+// OrderedAbs is a helper type that defines an Abs method for
+// ordered numeric types.
+type OrderedAbs[T OrderedNumeric] T
+
+func (a OrderedAbs[T]) Abs() OrderedAbs[T] {
+       if a < 0 {
+               return -a
+       }
+       return a
+}
+
+// ComplexAbs is a helper type that defines an Abs method for
+// complex types.
+type ComplexAbs[T Complex] T
+
+func (a ComplexAbs[T]) Abs() ComplexAbs[T] {
+       r := float64(real(a))
+       i := float64(imag(a))
+       d := math.Sqrt(r * r + i * i)
+       return ComplexAbs[T](complex(d, 0))
+}
+
+func OrderedAbsDifference[T OrderedNumeric](a, b T) T {
+       return T(AbsDifference(OrderedAbs[T](a), OrderedAbs[T](b)))
+}
+
+func ComplexAbsDifference[T Complex](a, b T) T {
+       return T(AbsDifference(ComplexAbs[T](a), ComplexAbs[T](b)))
+}
diff --git a/libgo/go/go/parser/testdata/map.go2 b/libgo/go/go/parser/testdata/map.go2
new file mode 100644 (file)
index 0000000..74c79ae
--- /dev/null
@@ -0,0 +1,109 @@
+// Package orderedmap provides an ordered map, implemented as a binary tree.
+package orderedmap
+
+import "chans"
+
+// Map is an ordered map.
+type Map[K, V any] struct {
+       root    *node[K, V]
+       compare func(K, K) int
+}
+
+// node is the type of a node in the binary tree.
+type node[K, V any] struct {
+       key         K
+       val         V
+       left, right *node[K, V]
+}
+
+// New returns a new map.
+func New[K, V any](compare func(K, K) int) *Map[K, V] {
+        return &Map[K, V]{compare: compare}
+}
+
+// find looks up key in the map, and returns either a pointer
+// to the node holding key, or a pointer to the location where
+// such a node would go.
+func (m *Map[K, V]) find(key K) **node[K, V] {
+       pn := &m.root
+       for *pn != nil {
+               switch cmp := m.compare(key, (*pn).key); {
+               case cmp < 0:
+                       pn = &(*pn).left
+               case cmp > 0:
+                       pn = &(*pn).right
+               default:
+                       return pn
+               }
+       }
+       return pn
+}
+
+// Insert inserts a new key/value into the map.
+// If the key is already present, the value is replaced.
+// Returns true if this is a new key, false if already present.
+func (m *Map[K, V]) Insert(key K, val V) bool {
+       pn := m.find(key)
+       if *pn != nil {
+               (*pn).val = val
+               return false
+       }
+        *pn = &node[K, V]{key: key, val: val}
+       return true
+}
+
+// Find returns the value associated with a key, or zero if not present.
+// The found result reports whether the key was found.
+func (m *Map[K, V]) Find(key K) (V, bool) {
+       pn := m.find(key)
+       if *pn == nil {
+               var zero V // see the discussion of zero values, above
+               return zero, false
+       }
+       return (*pn).val, true
+}
+
+// keyValue is a pair of key and value used when iterating.
+type keyValue[K, V any] struct {
+       key K
+       val V
+}
+
+// InOrder returns an iterator that does an in-order traversal of the map.
+func (m *Map[K, V]) InOrder() *Iterator[K, V] {
+       sender, receiver := chans.Ranger[keyValue[K, V]]()
+       var f func(*node[K, V]) bool
+       f = func(n *node[K, V]) bool {
+               if n == nil {
+                       return true
+               }
+               // Stop sending values if sender.Send returns false,
+               // meaning that nothing is listening at the receiver end.
+               return f(n.left) &&
+                        // TODO
+                       // sender.Send(keyValue[K, V]{n.key, n.val}) &&
+                       f(n.right)
+       }
+       go func() {
+               f(m.root)
+               sender.Close()
+       }()
+       return &Iterator{receiver}
+}
+
+// Iterator is used to iterate over the map.
+type Iterator[K, V any] struct {
+       r *chans.Receiver[keyValue[K, V]]
+}
+
+// Next returns the next key and value pair, and a boolean indicating
+// whether they are valid or whether we have reached the end.
+func (it *Iterator[K, V]) Next() (K, V, bool) {
+       keyval, ok := it.r.Next()
+       if !ok {
+               var zerok K
+               var zerov V
+               return zerok, zerov, false
+       }
+       return keyval.key, keyval.val, true
+}
diff --git a/libgo/go/go/parser/testdata/metrics.go2 b/libgo/go/go/parser/testdata/metrics.go2
new file mode 100644 (file)
index 0000000..ef1c66b
--- /dev/null
@@ -0,0 +1,58 @@
+package metrics
+
+import "sync"
+
+type Metric1[T comparable] struct {
+       mu sync.Mutex
+       m  map[T]int
+}
+
+func (m *Metric1[T]) Add(v T) {
+       m.mu.Lock()
+       defer m.mu.Unlock()
+       if m.m == nil {
+               m.m = make(map[T]int)
+       }
+       m[v]++
+}
+
+type key2[T1, T2 comparable] struct {
+       f1 T1
+       f2 T2
+}
+
+type Metric2[T1, T2 cmp2] struct {
+       mu sync.Mutex
+       m  map[key2[T1, T2]]int
+}
+
+func (m *Metric2[T1, T2]) Add(v1 T1, v2 T2) {
+       m.mu.Lock()
+       defer m.mu.Unlock()
+       if m.m == nil {
+               m.m = make(map[key2[T1, T2]]int)
+       }
+       m[key[T1, T2]{v1, v2}]++
+}
+
+type key3[T1, T2, T3 comparable] struct {
+       f1 T1
+       f2 T2
+       f3 T3
+}
+
+type Metric3[T1, T2, T3 comparable] struct {
+       mu sync.Mutex
+       m  map[key3[T1, T2, T3]]int
+}
+
+func (m *Metric3[T1, T2, T3]) Add(v1 T1, v2 T2, v3 T3) {
+       m.mu.Lock()
+       defer m.mu.Unlock()
+       if m.m == nil {
+               m.m = make(map[key3]int)
+       }
+       m[key[T1, T2, T3]{v1, v2, v3}]++
+}
+
+// Repeat for the maximum number of permitted arguments.
diff --git a/libgo/go/go/parser/testdata/resolution/issue45136.src b/libgo/go/go/parser/testdata/resolution/issue45136.src
new file mode 100644 (file)
index 0000000..e1d63d8
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package issue45136
+
+type obj /* =@obj */ struct {
+       name /*=@name */ string
+}
+
+func _() {
+       var foo /* =@foo */ = "foo"
+       obj /* @obj */ ["foo"]
+       obj /* @obj */ .run()
+       obj /* @obj */ {
+               name: foo /* @foo */,
+       }
+       obj /* @obj */ {
+               name: "bar",
+       }.run()
+
+       var _ = File{key: obj /* @obj */ {}}
+       var _ = File{obj /* @obj */ {}}
+
+       []obj /* @obj */ {foo /* @foo */}
+       x /* =@x1 */ := obj /* @obj */{}
+}
diff --git a/libgo/go/go/parser/testdata/resolution/issue45160.src b/libgo/go/go/parser/testdata/resolution/issue45160.src
new file mode 100644 (file)
index 0000000..6be933b
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package issue45160
+
+func mklink1 /* =@mklink1func */() {}
+
+func _() {
+       var tests /* =@tests */ = []dirLinkTest /* @dirLinkTest */ {
+               {
+                       mklink1 /* @mklink1func */: func() {},
+                       mklink2: func(link /* =@link */, target /* =@target */ string) error {
+                               return nil
+                       },
+               },
+       }
+}
+
+type dirLinkTest /* =@dirLinkTest */ struct {
+       mklink1 /* =@mklink1field */ func(string, string) error
+       mklink2 /* =@mklink2field */ func(string, string) error
+}
+
+func mklink2 /* =@mklink2func */() {}
diff --git a/libgo/go/go/parser/testdata/resolution/resolution.src b/libgo/go/go/parser/testdata/resolution/resolution.src
new file mode 100644 (file)
index 0000000..a880dd1
--- /dev/null
@@ -0,0 +1,63 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package resolution
+
+func f /* =@fdecl */(n /* =@narg */ ast.Node) bool {
+               if n /* =@ninit */, ok /* =@ok */ := n /* @narg */ .(*ast.SelectorExpr); ok /* @ok */ {
+                       sel = n /* @ninit */
+       }
+}
+
+type c /* =@cdecl */ map[token.Pos]resolvedObj
+
+func (v /* =@vdecl */ c /* @cdecl */) Visit(node /* =@nodearg */ ast.Node) (w /* =@w */ ast.Visitor) {}
+
+const (
+       basic /* =@basic */ = iota
+       labelOk // =@labelOk
+)
+
+type T /* =@T */ int
+
+func _(count /* =@count */ T /* @T */) {
+       x /* =@x1 */ := c /* @cdecl */{}
+       switch x /* =@x2 */ := x /* @x1 */; x /* =@x3 */ := x /* @x2 */.(type) {
+       case c /* @cdecl */:
+       default:
+       }
+loop /* =@loop */:
+       for {
+               if true {
+                       break loop /* @loop */
+               }
+       }
+       select {
+       case err /* =@err1 */ := <-_:
+               return err /* @err1 */
+       case err /* =@err2 */ := <-_:
+               return err /* @err2 */
+       }
+
+       _ = func(p1 /* =@p1 */ int, p2 /* =@p2 */ p1) {
+               closed /* =@closed */ := p1 // @p1
+               shadowed /* =@shadowed1 */ := p2 // @p2
+               _ = func(shadowed /* =@shadowed2 */ p2 /* @p2 */) {
+                       closed /* @closed */ = 1
+                       shadowed /* @shadowed2 */ = 2
+               }
+       }
+}
+
+func (r /* =@r */ c /* @cdecl */) m(_ r) c /* @cdecl */ { return r /* @r */ }
+
+var cycle /* =@cycle */ = cycle /* @cycle */ + 1
+
+type chain /* =@chain */ struct {
+       next /* =@next */ *chain /* @chain */
+}
+
+func recursive /* =@recursive */() {
+       recursive /* @recursive */ ()
+}
diff --git a/libgo/go/go/parser/testdata/resolution/typeparams.go2 b/libgo/go/go/parser/testdata/resolution/typeparams.go2
new file mode 100644 (file)
index 0000000..0ffecd6
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package resolution
+
+type List /* =@List */ [E /* =@E */ any] []E // @E
+
+type Pair /* =@Pair */ [L /* =@L */, R /* =@R */ any] struct {
+       Left /* =@Left */ L // @L
+       Right /* =@Right */ R // @R
+       L /* =@Lfield */ int
+}
+
+var _ = Pair /* @Pair */ [int, string]{}
+
+type Addable /* =@Addable */ interface {
+       type int64, float64
+}
+
+func Add /* =@AddDecl */[T /* =@T */ Addable /* @Addable */](l /* =@l */, r /* =@r */ T /* @T */) T /* @T */ {
+       var t /* =@t */ T /* @T */
+       return l /* @l */ + r /* @r */ + t /* @t */
+}
+
+type Receiver /* =@Receiver */[P /* =@P */ any] struct {}
+
+// TODO(rFindley): make a decision on how/whether to resolve identifiers that
+// refer to receiver type parameters, as is the case for the 'P' result
+// parameter below.
+func (r /* =@recv */ Receiver /* @Receiver */ [P]) m() P {}
+
+func f /* =@f */[T1 /* =@T1 */ interface{type []T2 /* @T2 */}, T2 /* =@T2 */ any](
+  x /* =@x */ T1 /* @T1 */, T1 /* =@T1_duplicate */ y,  // Note that this is a bug:
+                                                        // the duplicate T1 should
+                                                       // not be allowed.
+  ){
+  // Note that duplicate short var declarations resolve to their alt declaration.
+  x /* @x */ := 0
+  y /* =@y */ := 0
+  T1 /* @T1 */ := 0
+  var t1var /* =@t1var */ T1 /* @T1 */
+}
diff --git a/libgo/go/go/parser/testdata/set.go2 b/libgo/go/go/parser/testdata/set.go2
new file mode 100644 (file)
index 0000000..0da6377
--- /dev/null
@@ -0,0 +1,31 @@
+// Package set implements sets of any type.
+package set
+
+type Set[Elem comparable] map[Elem]struct{}
+
+func Make[Elem comparable]() Set[Elem] {
+       return make(Set(Elem))
+}
+
+func (s Set[Elem]) Add(v Elem) {
+       s[v] = struct{}{}
+}
+
+func (s Set[Elem]) Delete(v Elem) {
+       delete(s, v)
+}
+
+func (s Set[Elem]) Contains(v Elem) bool {
+       _, ok := s[v]
+       return ok
+}
+
+func (s Set[Elem]) Len() int {
+       return len(s)
+}
+
+func (s Set[Elem]) Iterate(f func(Elem)) {
+       for v := range s {
+               f(v)
+       }
+}
diff --git a/libgo/go/go/parser/testdata/slices.go2 b/libgo/go/go/parser/testdata/slices.go2
new file mode 100644 (file)
index 0000000..e060212
--- /dev/null
@@ -0,0 +1,31 @@
+// Package slices implements various slice algorithms.
+package slices
+
+// Map turns a []T1 to a []T2 using a mapping function.
+func Map[T1, T2 any](s []T1, f func(T1) T2) []T2 {
+       r := make([]T2, len(s))
+       for i, v := range s {
+               r[i] = f(v)
+       }
+       return r
+}
+
+// Reduce reduces a []T1 to a single value using a reduction function.
+func Reduce[T1, T2 any](s []T1, initializer T2, f func(T2, T1) T2) T2 {
+       r := initializer
+       for _, v := range s {
+               r = f(r, v)
+       }
+       return r
+}
+
+// Filter filters values from a slice using a filter function.
+func Filter[T any](s []T, f func(T) bool) []T {
+       var r []T
+       for _, v := range s {
+               if f(v) {
+                       r = append(r, v)
+               }
+       }
+       return r
+}
diff --git a/libgo/go/go/parser/testdata/sort.go2 b/libgo/go/go/parser/testdata/sort.go2
new file mode 100644 (file)
index 0000000..88be79f
--- /dev/null
@@ -0,0 +1,27 @@
+package sort
+
+type orderedSlice[Elem comparable] []Elem
+
+func (s orderedSlice[Elem]) Len() int           { return len(s) }
+func (s orderedSlice[Elem]) Less(i, j int) bool { return s[i] < s[j] }
+func (s orderedSlice[Elem]) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
+
+// OrderedSlice sorts the slice s in ascending order.
+// The elements of s must be ordered using the < operator.
+func OrderedSlice[Elem comparable](s []Elem) {
+       sort.Sort(orderedSlice[Elem](s))
+}
+
+type sliceFn[Elem any] struct {
+       s []Elem
+       f func(Elem, Elem) bool
+}
+
+func (s sliceFn[Elem]) Len() int           { return len(s.s) }
+func (s sliceFn[Elem]) Less(i, j int) bool { return s.f(s.s[i], s.s[j]) }
+func (s sliceFn[Elem]) Swap(i, j int)      { s.s[i], s.s[j] = s.s[j], s.s[i] }
+
+// SliceFn sorts the slice s according to the function f.
+func SliceFn[Elem any](s []Elem, f func(Elem, Elem) bool) {
+       Sort(sliceFn[Elem]{s, f})
+}
diff --git a/libgo/go/go/parser/testdata/typeparams.src b/libgo/go/go/parser/testdata/typeparams.src
new file mode 100644 (file)
index 0000000..1fea23f
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test cases for error messages produced while parsing code that uses type
+// parameters, without ParseTypeParams being enabled.
+
+package p
+
+type List[E any /* ERROR "expected ']', found any" */ ] []E
+
+type Pair[L, /* ERROR "expected ']', found ','" */ R any] struct {
+       Left L
+       Right R
+}
+
+var _ = Pair[int, /* ERROR "expected ']' or ':', found ','" */ string]{}
diff --git a/libgo/go/go/printer/gobuild.go b/libgo/go/go/printer/gobuild.go
new file mode 100644 (file)
index 0000000..f00492d
--- /dev/null
@@ -0,0 +1,170 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package printer
+
+import (
+       "go/build/constraint"
+       "sort"
+       "text/tabwriter"
+)
+
+func (p *printer) fixGoBuildLines() {
+       if len(p.goBuild)+len(p.plusBuild) == 0 {
+               return
+       }
+
+       // Find latest possible placement of //go:build and // +build comments.
+       // That's just after the last blank line before we find a non-comment.
+       // (We'll add another blank line after our comment block.)
+       // When we start dropping // +build comments, we can skip over /* */ comments too.
+       // Note that we are processing tabwriter input, so every comment
+       // begins and ends with a tabwriter.Escape byte.
+       // And some newlines have turned into \f bytes.
+       insert := 0
+       for pos := 0; ; {
+               // Skip leading space at beginning of line.
+               blank := true
+               for pos < len(p.output) && (p.output[pos] == ' ' || p.output[pos] == '\t') {
+                       pos++
+               }
+               // Skip over // comment if any.
+               if pos+3 < len(p.output) && p.output[pos] == tabwriter.Escape && p.output[pos+1] == '/' && p.output[pos+2] == '/' {
+                       blank = false
+                       for pos < len(p.output) && !isNL(p.output[pos]) {
+                               pos++
+                       }
+               }
+               // Skip over \n at end of line.
+               if pos >= len(p.output) || !isNL(p.output[pos]) {
+                       break
+               }
+               pos++
+
+               if blank {
+                       insert = pos
+               }
+       }
+
+       // If there is a //go:build comment before the place we identified,
+       // use that point instead. (Earlier in the file is always fine.)
+       if len(p.goBuild) > 0 && p.goBuild[0] < insert {
+               insert = p.goBuild[0]
+       } else if len(p.plusBuild) > 0 && p.plusBuild[0] < insert {
+               insert = p.plusBuild[0]
+       }
+
+       var x constraint.Expr
+       switch len(p.goBuild) {
+       case 0:
+               // Synthesize //go:build expression from // +build lines.
+               for _, pos := range p.plusBuild {
+                       y, err := constraint.Parse(p.commentTextAt(pos))
+                       if err != nil {
+                               x = nil
+                               break
+                       }
+                       if x == nil {
+                               x = y
+                       } else {
+                               x = &constraint.AndExpr{X: x, Y: y}
+                       }
+               }
+       case 1:
+               // Parse //go:build expression.
+               x, _ = constraint.Parse(p.commentTextAt(p.goBuild[0]))
+       }
+
+       var block []byte
+       if x == nil {
+               // Don't have a valid //go:build expression to treat as truth.
+               // Bring all the lines together but leave them alone.
+               // Note that these are already tabwriter-escaped.
+               for _, pos := range p.goBuild {
+                       block = append(block, p.lineAt(pos)...)
+               }
+               for _, pos := range p.plusBuild {
+                       block = append(block, p.lineAt(pos)...)
+               }
+       } else {
+               block = append(block, tabwriter.Escape)
+               block = append(block, "//go:build "...)
+               block = append(block, x.String()...)
+               block = append(block, tabwriter.Escape, '\n')
+               if len(p.plusBuild) > 0 {
+                       lines, err := constraint.PlusBuildLines(x)
+                       if err != nil {
+                               lines = []string{"// +build error: " + err.Error()}
+                       }
+                       for _, line := range lines {
+                               block = append(block, tabwriter.Escape)
+                               block = append(block, line...)
+                               block = append(block, tabwriter.Escape, '\n')
+                       }
+               }
+       }
+       block = append(block, '\n')
+
+       // Build sorted list of lines to delete from remainder of output.
+       toDelete := append(p.goBuild, p.plusBuild...)
+       sort.Ints(toDelete)
+
+       // Collect output after insertion point, with lines deleted, into after.
+       var after []byte
+       start := insert
+       for _, end := range toDelete {
+               if end < start {
+                       continue
+               }
+               after = appendLines(after, p.output[start:end])
+               start = end + len(p.lineAt(end))
+       }
+       after = appendLines(after, p.output[start:])
+       if n := len(after); n >= 2 && isNL(after[n-1]) && isNL(after[n-2]) {
+               after = after[:n-1]
+       }
+
+       p.output = p.output[:insert]
+       p.output = append(p.output, block...)
+       p.output = append(p.output, after...)
+}
+
+// appendLines is like append(x, y...)
+// but it avoids creating doubled blank lines,
+// which would not be gofmt-standard output.
+// It assumes that only whole blocks of lines are being appended,
+// not line fragments.
+func appendLines(x, y []byte) []byte {
+       if len(y) > 0 && isNL(y[0]) && // y starts in blank line
+               (len(x) == 0 || len(x) >= 2 && isNL(x[len(x)-1]) && isNL(x[len(x)-2])) { // x is empty or ends in blank line
+               y = y[1:] // delete y's leading blank line
+       }
+       return append(x, y...)
+}
+
+func (p *printer) lineAt(start int) []byte {
+       pos := start
+       for pos < len(p.output) && !isNL(p.output[pos]) {
+               pos++
+       }
+       if pos < len(p.output) {
+               pos++
+       }
+       return p.output[start:pos]
+}
+
+func (p *printer) commentTextAt(start int) string {
+       if start < len(p.output) && p.output[start] == tabwriter.Escape {
+               start++
+       }
+       pos := start
+       for pos < len(p.output) && p.output[pos] != tabwriter.Escape && !isNL(p.output[pos]) {
+               pos++
+       }
+       return string(p.output[start:pos])
+}
+
+func isNL(b byte) bool {
+       return b == '\n' || b == '\f'
+}
index 95b9e918917cd50685cb27e3ac03dc9ca89e4877..913281ea6c14b7b13ef6e95f9233a1c808e518b1 100644 (file)
@@ -11,6 +11,7 @@ package printer
 import (
        "bytes"
        "go/ast"
+       "go/internal/typeparams"
        "go/token"
        "math"
        "strconv"
@@ -319,8 +320,12 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
        }
 }
 
-func (p *printer) parameters(fields *ast.FieldList) {
-       p.print(fields.Opening, token.LPAREN)
+func (p *printer) parameters(fields *ast.FieldList, isTypeParam bool) {
+       openTok, closeTok := token.LPAREN, token.RPAREN
+       if isTypeParam {
+               openTok, closeTok = token.LBRACK, token.RBRACK
+       }
+       p.print(fields.Opening, openTok)
        if len(fields.List) > 0 {
                prevLine := p.lineFor(fields.Opening)
                ws := indent
@@ -328,13 +333,8 @@ func (p *printer) parameters(fields *ast.FieldList) {
                        // determine par begin and end line (may be different
                        // if there are multiple parameter names for this par
                        // or the type is on a separate line)
-                       var parLineBeg int
-                       if len(par.Names) > 0 {
-                               parLineBeg = p.lineFor(par.Names[0].Pos())
-                       } else {
-                               parLineBeg = p.lineFor(par.Type.Pos())
-                       }
-                       var parLineEnd = p.lineFor(par.Type.End())
+                       parLineBeg := p.lineFor(par.Pos())
+                       parLineEnd := p.lineFor(par.End())
                        // separating "," if needed
                        needsLinebreak := 0 < prevLine && prevLine < parLineBeg
                        if i > 0 {
@@ -379,25 +379,29 @@ func (p *printer) parameters(fields *ast.FieldList) {
                        p.print(unindent)
                }
        }
-       p.print(fields.Closing, token.RPAREN)
+       p.print(fields.Closing, closeTok)
 }
 
-func (p *printer) signature(params, result *ast.FieldList) {
-       if params != nil {
-               p.parameters(params)
+func (p *printer) signature(sig *ast.FuncType) {
+       if tparams := typeparams.Get(sig); tparams != nil {
+               p.parameters(tparams, true)
+       }
+       if sig.Params != nil {
+               p.parameters(sig.Params, false)
        } else {
                p.print(token.LPAREN, token.RPAREN)
        }
-       n := result.NumFields()
+       res := sig.Results
+       n := res.NumFields()
        if n > 0 {
-               // result != nil
+               // res != nil
                p.print(blank)
-               if n == 1 && result.List[0].Names == nil {
-                       // single anonymous result; no ()'s
-                       p.expr(stripParensAlways(result.List[0].Type))
+               if n == 1 && res.List[0].Names == nil {
+                       // single anonymous res; no ()'s
+                       p.expr(stripParensAlways(res.List[0].Type))
                        return
                }
-               p.parameters(result)
+               p.parameters(res, false)
        }
 }
 
@@ -467,10 +471,18 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
                                }
                                p.expr(f.Type)
                        } else { // interface
-                               if ftyp, isFtyp := f.Type.(*ast.FuncType); isFtyp {
-                                       // method
-                                       p.expr(f.Names[0])
-                                       p.signature(ftyp.Params, ftyp.Results)
+                               if len(f.Names) > 0 {
+                                       // type list type or method
+                                       name := f.Names[0] // "type" or method name
+                                       p.expr(name)
+                                       if name.Name == "type" {
+                                               // type list type
+                                               p.print(blank)
+                                               p.expr(f.Type)
+                                       } else {
+                                               // method
+                                               p.signature(f.Type.(*ast.FuncType)) // don't print "func"
+                                       }
                                } else {
                                        // embedded interface
                                        p.expr(f.Type)
@@ -538,19 +550,47 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
        } else { // interface
 
                var line int
+               var prev *ast.Ident // previous "type" identifier
                for i, f := range list {
+                       var name *ast.Ident // first name, or nil
+                       if len(f.Names) > 0 {
+                               name = f.Names[0]
+                       }
                        if i > 0 {
-                               p.linebreak(p.lineFor(f.Pos()), 1, ignore, p.linesFrom(line) > 0)
+                               // don't do a line break (min == 0) if we are printing a list of types
+                               // TODO(gri) this doesn't work quite right if the list of types is
+                               //           spread across multiple lines
+                               min := 1
+                               if prev != nil && name == prev {
+                                       min = 0
+                               }
+                               p.linebreak(p.lineFor(f.Pos()), min, ignore, p.linesFrom(line) > 0)
                        }
                        p.setComment(f.Doc)
                        p.recordLine(&line)
-                       if ftyp, isFtyp := f.Type.(*ast.FuncType); isFtyp {
-                               // method
-                               p.expr(f.Names[0])
-                               p.signature(ftyp.Params, ftyp.Results)
+                       if name != nil {
+                               // type list type or method
+                               if name.Name == "type" {
+                                       // type list type
+                                       if name == prev {
+                                               // type is part of a list of types
+                                               p.print(token.COMMA, blank)
+                                       } else {
+                                               // type starts a new list of types
+                                               p.print(name, blank)
+                                       }
+                                       p.expr(f.Type)
+                                       prev = name
+                               } else {
+                                       // method
+                                       p.expr(name)
+                                       p.signature(f.Type.(*ast.FuncType)) // don't print "func"
+                                       prev = nil
+                               }
                        } else {
                                // embedded interface
                                p.expr(f.Type)
+                               prev = nil
                        }
                        p.setComment(f.Comment)
                }
@@ -800,7 +840,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
                p.print(x.Type.Pos(), token.FUNC)
                // See the comment in funcDecl about how the header size is computed.
                startCol := p.out.Column - len("func")
-               p.signature(x.Type.Params, x.Type.Results)
+               p.signature(x.Type)
                p.funcBody(p.distanceFrom(x.Type.Pos(), startCol), blank, x.Body)
 
        case *ast.ParenExpr:
@@ -831,7 +871,17 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
                // TODO(gri): should treat[] like parentheses and undo one level of depth
                p.expr1(x.X, token.HighestPrec, 1)
                p.print(x.Lbrack, token.LBRACK)
-               p.expr0(x.Index, depth+1)
+               // Note: we're a bit defensive here to handle the case of a ListExpr of
+               // length 1.
+               if list := typeparams.UnpackExpr(x.Index); len(list) > 0 {
+                       if len(list) > 1 {
+                               p.exprList(x.Lbrack, list, depth+1, commaTerm, x.Rbrack, false)
+                       } else {
+                               p.expr0(list[0], depth+1)
+                       }
+               } else {
+                       p.expr0(x.Index, depth+1)
+               }
                p.print(x.Rbrack, token.RBRACK)
 
        case *ast.SliceExpr:
@@ -945,7 +995,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
 
        case *ast.FuncType:
                p.print(token.FUNC)
-               p.signature(x.Params, x.Results)
+               p.signature(x)
 
        case *ast.InterfaceType:
                p.print(token.INTERFACE)
@@ -1585,6 +1635,9 @@ func (p *printer) spec(spec ast.Spec, n int, doIndent bool) {
        case *ast.TypeSpec:
                p.setComment(s.Doc)
                p.expr(s.Name)
+               if tparams := typeparams.Get(s); tparams != nil {
+                       p.parameters(tparams, true)
+               }
                if n == 1 {
                        p.print(blank)
                } else {
@@ -1773,11 +1826,11 @@ func (p *printer) funcDecl(d *ast.FuncDecl) {
        // FUNC is emitted).
        startCol := p.out.Column - len("func ")
        if d.Recv != nil {
-               p.parameters(d.Recv) // method: print receiver
+               p.parameters(d.Recv, false) // method: print receiver
                p.print(blank)
        }
        p.expr(d.Name)
-       p.signature(d.Type.Params, d.Type.Results)
+       p.signature(d.Type)
        p.funcBody(p.distanceFrom(d.Pos(), startCol), vtab, d.Body)
 }
 
index 0077afeaff7c92691485787f9762466bc73bf0df..ba61f782267ad8ed27ab5b2252f06bdf70cc5252 100644 (file)
@@ -8,6 +8,7 @@ package printer
 import (
        "fmt"
        "go/ast"
+       "go/build/constraint"
        "go/token"
        "io"
        "os"
@@ -64,6 +65,8 @@ type printer struct {
        lastTok      token.Token  // last token printed (token.ILLEGAL if it's whitespace)
        prevOpen     token.Token  // previous non-brace "open" token (, [, or token.ILLEGAL
        wsbuf        []whiteSpace // delayed white space
+       goBuild      []int        // start index of all //go:build comments in output
+       plusBuild    []int        // start index of all // +build comments in output
 
        // Positions
        // The out position differs from the pos position when the result
@@ -649,6 +652,11 @@ func (p *printer) writeComment(comment *ast.Comment) {
 
        // shortcut common case of //-style comments
        if text[1] == '/' {
+               if constraint.IsGoBuild(text) {
+                       p.goBuild = append(p.goBuild, len(p.output))
+               } else if constraint.IsPlusBuild(text) {
+                       p.plusBuild = append(p.plusBuild, len(p.output))
+               }
                p.writeString(pos, trimRight(text), true)
                return
        }
@@ -836,7 +844,7 @@ func (p *printer) writeWhitespace(n int) {
 // ----------------------------------------------------------------------------
 // Printing interface
 
-// nlines limits n to maxNewlines.
+// nlimit limits n to maxNewlines.
 func nlimit(n int) int {
        if n > maxNewlines {
                n = maxNewlines
@@ -1122,6 +1130,8 @@ func (p *printer) printNode(node interface{}) error {
        // get comments ready for use
        p.nextComment()
 
+       p.print(pmode(0))
+
        // format node
        switch n := node.(type) {
        case ast.Expr:
@@ -1313,6 +1323,10 @@ func (cfg *Config) fprint(output io.Writer, fset *token.FileSet, node interface{
        p.impliedSemi = false // EOF acts like a newline
        p.flush(token.Position{Offset: infinity, Line: infinity}, token.EOF)
 
+       // output is buffered in p.output now.
+       // fix //go:build and // +build comments if needed.
+       p.fixGoBuildLines()
+
        // redirect output through a trimmer to eliminate trailing whitespace
        // (Input to a tabwriter must be untrimmed since trailing tabs provide
        // formatting information. The tabwriter could provide trimming
index 45e501115ac6f98d95b1951fbbe97162760a7e8e..20c97b8c08173065e23a2be9795b90beb904201f 100644 (file)
@@ -10,6 +10,7 @@ import (
        "flag"
        "fmt"
        "go/ast"
+       "go/internal/typeparams"
        "go/parser"
        "go/token"
        "io"
@@ -35,6 +36,7 @@ const (
        rawFormat
        normNumber
        idempotent
+       allowTypeParams
 )
 
 // format parses src, prints the corresponding AST, verifies the resulting
@@ -70,7 +72,7 @@ func format(src []byte, mode checkMode) ([]byte, error) {
 
        // make sure formatted output is syntactically correct
        res := buf.Bytes()
-       if _, err := parser.ParseFile(fset, "", res, 0); err != nil {
+       if _, err := parser.ParseFile(fset, "", res, parser.ParseComments); err != nil {
                return nil, fmt.Errorf("re-parse: %s\n%s", err, buf.Bytes())
        }
 
@@ -88,8 +90,11 @@ func lineAt(text []byte, offs int) []byte {
 
 // diff compares a and b.
 func diff(aname, bname string, a, b []byte) error {
-       var buf bytes.Buffer // holding long error message
+       if bytes.Equal(a, b) {
+               return nil
+       }
 
+       var buf bytes.Buffer // holding long error message
        // compare lengths
        if len(a) != len(b) {
                fmt.Fprintf(&buf, "\nlength changed: len(%s) = %d, len(%s) = %d", aname, len(a), bname, len(b))
@@ -97,7 +102,7 @@ func diff(aname, bname string, a, b []byte) error {
 
        // compare contents
        line := 1
-       offs := 1
+       offs := 0
        for i := 0; i < len(a) && i < len(b); i++ {
                ch := a[i]
                if ch != b[i] {
@@ -112,10 +117,8 @@ func diff(aname, bname string, a, b []byte) error {
                }
        }
 
-       if buf.Len() > 0 {
-               return errors.New(buf.String())
-       }
-       return nil
+       fmt.Fprintf(&buf, "\n%s:\n%s\n%s:\n%s", aname, a, bname, b)
+       return errors.New(buf.String())
 }
 
 func runcheck(t *testing.T, source, golden string, mode checkMode) {
@@ -206,11 +209,22 @@ var data = []entry{
        {"complit.input", "complit.x", export},
        {"go2numbers.input", "go2numbers.golden", idempotent},
        {"go2numbers.input", "go2numbers.norm", normNumber | idempotent},
+       {"generics.input", "generics.golden", idempotent | allowTypeParams},
+       {"gobuild1.input", "gobuild1.golden", idempotent},
+       {"gobuild2.input", "gobuild2.golden", idempotent},
+       {"gobuild3.input", "gobuild3.golden", idempotent},
+       {"gobuild4.input", "gobuild4.golden", idempotent},
+       {"gobuild5.input", "gobuild5.golden", idempotent},
+       {"gobuild6.input", "gobuild6.golden", idempotent},
+       {"gobuild7.input", "gobuild7.golden", idempotent},
 }
 
 func TestFiles(t *testing.T) {
        t.Parallel()
        for _, e := range data {
+               if !typeparams.Enabled && e.mode&allowTypeParams != 0 {
+                       continue
+               }
                source := filepath.Join(dataDir, e.source)
                golden := filepath.Join(dataDir, e.golden)
                mode := e.mode
index a858051ef01a650d69a9d4a4039d53e601513cac..f34395b505dbd7be2b808acc9fd7ed817ba10b42 100644 (file)
@@ -1018,4 +1018,4 @@ type (
        c = foo
        d = interface{}
        ddd = p.Foo
-)
\ No newline at end of file
+)
diff --git a/libgo/go/go/printer/testdata/generics.golden b/libgo/go/go/printer/testdata/generics.golden
new file mode 100644 (file)
index 0000000..cc7fbbe
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package generics
+
+func _[A, B any](a A, b B) int {}
+func _[T any](x, y T) T
+
+type T[P any] struct{}
+type T[P1, P2, P3 any] struct{}
+
+type T[P C] struct{}
+type T[P1, P2, P3 C] struct{}
+
+type T[P C[P]] struct{}
+type T[P1, P2, P3 C[P1, P2, P3]] struct{}
+
+func f[P any](x P)
+func f[P1, P2, P3 any](x1 P1, x2 P2, x3 P3) struct{}
+
+func f[P interface{}](x P)
+func f[P1, P2, P3 interface {
+       m1(P1)
+       type P2, P3
+}](x1 P1, x2 P2, x3 P3) struct{}
+func f[P any](T1[P], T2[P]) T3[P]
+
+func (x T[P]) m()
+func (T[P]) m(x T[P]) P
+
+func _() {
+       type _ []T[P]
+       var _ []T[P]
+       _ = []T[P]{}
+}
+
+// properly format one-line type lists
+type _ interface{ type a }
+
+type _ interface {
+       type a, b, c
+}
diff --git a/libgo/go/go/printer/testdata/generics.input b/libgo/go/go/printer/testdata/generics.input
new file mode 100644 (file)
index 0000000..f4571ad
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package generics
+
+func _[A, B any](a A, b B) int {}
+func _[T any](x, y T) T
+
+type T[P any] struct{}
+type T[P1, P2, P3 any] struct{}
+
+type T[P C] struct{}
+type T[P1, P2, P3 C] struct{}
+
+type T[P C[P]] struct{}
+type T[P1, P2, P3 C[P1, P2, P3]] struct{}
+
+func f[P any](x P)
+func f[P1, P2, P3 any](x1 P1, x2 P2, x3 P3) struct{}
+
+func f[P interface{}](x P)
+func f[P1, P2, P3 interface{ m1(P1); type P2, P3 }](x1 P1, x2 P2, x3 P3) struct{}
+func f[P any](T1[P], T2[P]) T3[P]
+
+func (x T[P]) m()
+func ((T[P])) m(x T[P]) P
+
+func _() {
+       type _ []T[P]
+       var _ []T[P]
+       _ = []T[P]{}
+}
+
+// properly format one-line type lists
+type _ interface { type a }
+
+type _ interface { type a,b,c }
diff --git a/libgo/go/go/printer/testdata/gobuild1.golden b/libgo/go/go/printer/testdata/gobuild1.golden
new file mode 100644 (file)
index 0000000..649da40
--- /dev/null
@@ -0,0 +1,6 @@
+//go:build x
+// +build x
+
+package p
+
+func f()
diff --git a/libgo/go/go/printer/testdata/gobuild1.input b/libgo/go/go/printer/testdata/gobuild1.input
new file mode 100644 (file)
index 0000000..6538ee6
--- /dev/null
@@ -0,0 +1,7 @@
+package p
+
+//go:build x
+
+func f()
+
+// +build y
diff --git a/libgo/go/go/printer/testdata/gobuild2.golden b/libgo/go/go/printer/testdata/gobuild2.golden
new file mode 100644 (file)
index 0000000..c46fd34
--- /dev/null
@@ -0,0 +1,8 @@
+//go:build x
+// +build x
+
+// other comment
+
+package p
+
+func f()
diff --git a/libgo/go/go/printer/testdata/gobuild2.input b/libgo/go/go/printer/testdata/gobuild2.input
new file mode 100644 (file)
index 0000000..f0f772a
--- /dev/null
@@ -0,0 +1,9 @@
+// +build y
+
+// other comment
+
+package p
+
+func f()
+
+//go:build x
diff --git a/libgo/go/go/printer/testdata/gobuild3.golden b/libgo/go/go/printer/testdata/gobuild3.golden
new file mode 100644 (file)
index 0000000..db92c57
--- /dev/null
@@ -0,0 +1,10 @@
+// other comment
+
+//go:build x
+// +build x
+
+// yet another comment
+
+package p
+
+func f()
diff --git a/libgo/go/go/printer/testdata/gobuild3.input b/libgo/go/go/printer/testdata/gobuild3.input
new file mode 100644 (file)
index 0000000..d0c97b2
--- /dev/null
@@ -0,0 +1,11 @@
+// other comment
+
+// +build y
+
+// yet another comment
+
+package p
+
+//go:build x
+
+func f()
diff --git a/libgo/go/go/printer/testdata/gobuild4.golden b/libgo/go/go/printer/testdata/gobuild4.golden
new file mode 100644 (file)
index 0000000..b16477f
--- /dev/null
@@ -0,0 +1,6 @@
+//go:build (x || y) && z
+// +build x y
+// +build z
+
+// doc comment
+package p
diff --git a/libgo/go/go/printer/testdata/gobuild4.input b/libgo/go/go/printer/testdata/gobuild4.input
new file mode 100644 (file)
index 0000000..29d5a0a
--- /dev/null
@@ -0,0 +1,5 @@
+// doc comment
+package p
+
+// +build x y
+// +build z
diff --git a/libgo/go/go/printer/testdata/gobuild5.golden b/libgo/go/go/printer/testdata/gobuild5.golden
new file mode 100644 (file)
index 0000000..2808a53
--- /dev/null
@@ -0,0 +1,4 @@
+//go:build !(x || y) && z
+// +build !x,!y,z
+
+package p
diff --git a/libgo/go/go/printer/testdata/gobuild5.input b/libgo/go/go/printer/testdata/gobuild5.input
new file mode 100644 (file)
index 0000000..ec5815c
--- /dev/null
@@ -0,0 +1,4 @@
+//go:build !(x || y) && z
+// +build something else
+
+package p
diff --git a/libgo/go/go/printer/testdata/gobuild6.golden b/libgo/go/go/printer/testdata/gobuild6.golden
new file mode 100644 (file)
index 0000000..abb1e2a
--- /dev/null
@@ -0,0 +1,5 @@
+//go:build !(x || y) && z
+
+// no +build line
+
+package p
diff --git a/libgo/go/go/printer/testdata/gobuild6.input b/libgo/go/go/printer/testdata/gobuild6.input
new file mode 100644 (file)
index 0000000..1621897
--- /dev/null
@@ -0,0 +1,4 @@
+//go:build !(x || y) && z
+// no +build line
+
+package p
diff --git a/libgo/go/go/printer/testdata/gobuild7.golden b/libgo/go/go/printer/testdata/gobuild7.golden
new file mode 100644 (file)
index 0000000..bf41dd4
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// TODO(rsc): Delete this file once Go 1.17 comes out and we can retire Go 1.15 support.
+
+//go:build !go1.16
+// +build !go1.16
+
+// Package buildtag defines an Analyzer that checks build tags.
+package buildtag
diff --git a/libgo/go/go/printer/testdata/gobuild7.input b/libgo/go/go/printer/testdata/gobuild7.input
new file mode 100644 (file)
index 0000000..bf41dd4
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// TODO(rsc): Delete this file once Go 1.17 comes out and we can retire Go 1.15 support.
+
+//go:build !go1.16
+// +build !go1.16
+
+// Package buildtag defines an Analyzer that checks build tags.
+package buildtag
index 80b476cf2ee60fcb1fba429551aa1c42e548cb4d..fc2812adee0c3f6eaa2b363f3d2eeecb3248f50a 100644 (file)
@@ -231,7 +231,7 @@ func (p *parser) next0() {
        // Because of one-token look-ahead, print the previous token
        // when tracing as it provides a more readable output. The
        // very first token (!p.pos.IsValid()) is not initialized
-       // (it is token.ILLEGAL), so don't print it .
+       // (it is token.ILLEGAL), so don't print it.
        if p.trace && p.pos.IsValid() {
                s := p.tok.String()
                switch {
index bf7bfa30e4bcc261f1985bb02cf8193a6822c6cb..3114f4b645d91da154031f73caa147a8153aee51 100644 (file)
@@ -86,7 +86,7 @@ func (p *ErrorList) RemoveMultiples() {
                        i++
                }
        }
-       (*p) = (*p)[0:i]
+       *p = (*p)[0:i]
 }
 
 // An ErrorList implements the error interface.
index 00fe2dc0b19fd0b66bbe3fb48d27d1b0d27b972f..f08e28cdd6b72b35da5b669a0592b88c6e012c53 100644 (file)
@@ -48,11 +48,16 @@ type Scanner struct {
        ErrorCount int // number of errors encountered
 }
 
-const bom = 0xFEFF // byte order mark, only permitted as very first character
+const (
+       bom = 0xFEFF // byte order mark, only permitted as very first character
+       eof = -1     // end of file
+)
 
 // Read the next Unicode char into s.ch.
 // s.ch < 0 means end-of-file.
 //
+// For optimization, there is some overlap between this method and
+// s.scanIdentifier.
 func (s *Scanner) next() {
        if s.rdOffset < len(s.src) {
                s.offset = s.rdOffset
@@ -81,7 +86,7 @@ func (s *Scanner) next() {
                        s.lineOffset = s.offset
                        s.file.AddLine(s.offset)
                }
-               s.ch = -1 // eof
+               s.ch = eof
        }
 }
 
@@ -347,11 +352,53 @@ func isDigit(ch rune) bool {
        return isDecimal(ch) || ch >= utf8.RuneSelf && unicode.IsDigit(ch)
 }
 
+// scanIdentifier reads the string of valid identifier characters at s.offset.
+// It must only be called when s.ch is known to be a valid letter.
+//
+// Be careful when making changes to this function: it is optimized and affects
+// scanning performance significantly.
 func (s *Scanner) scanIdentifier() string {
        offs := s.offset
-       for isLetter(s.ch) || isDigit(s.ch) {
+
+       // Optimize for the common case of an ASCII identifier.
+       //
+       // Ranging over s.src[s.rdOffset:] lets us avoid some bounds checks, and
+       // avoids conversions to runes.
+       //
+       // In case we encounter a non-ASCII character, fall back on the slower path
+       // of calling into s.next().
+       for rdOffset, b := range s.src[s.rdOffset:] {
+               if 'a' <= b && b <= 'z' || 'A' <= b && b <= 'Z' || b == '_' || '0' <= b && b <= '9' {
+                       // Avoid assigning a rune for the common case of an ascii character.
+                       continue
+               }
+               s.rdOffset += rdOffset
+               if 0 < b && b < utf8.RuneSelf {
+                       // Optimization: we've encountered an ASCII character that's not a letter
+                       // or number. Avoid the call into s.next() and corresponding set up.
+                       //
+                       // Note that s.next() does some line accounting if s.ch is '\n', so this
+                       // shortcut is only possible because we know that the preceding character
+                       // is not '\n'.
+                       s.ch = rune(b)
+                       s.offset = s.rdOffset
+                       s.rdOffset++
+                       goto exit
+               }
+               // We know that the preceding character is valid for an identifier because
+               // scanIdentifier is only called when s.ch is a letter, so calling s.next()
+               // at s.rdOffset resets the scanner state.
                s.next()
+               for isLetter(s.ch) || isDigit(s.ch) {
+                       s.next()
+               }
+               goto exit
        }
+       s.offset = len(s.src)
+       s.rdOffset = len(s.src)
+       s.ch = eof
+
+exit:
        return string(s.src[offs:s.offset])
 }
 
@@ -383,7 +430,7 @@ func (s *Scanner) digits(base int, invalid *int) (digsep int) {
                        if s.ch == '_' {
                                ds = 2
                        } else if s.ch >= max && *invalid < 0 {
-                               *invalid = int(s.offset) // record invalid rune offset
+                               *invalid = s.offset // record invalid rune offset
                        }
                        digsep |= ds
                        s.next()
index ab4c2dd96233b965eda231ae56e190ea18f88b2a..db123c32e01d59e9d46fa6429efcefb9fc60bdff 100644 (file)
@@ -628,7 +628,7 @@ func TestInvalidLineDirectives(t *testing.T) {
        }
 
        if S.ErrorCount != len(invalidSegments) {
-               t.Errorf("go %d errors; want %d", S.ErrorCount, len(invalidSegments))
+               t.Errorf("got %d errors; want %d", S.ErrorCount, len(invalidSegments))
        }
 }
 
@@ -812,6 +812,8 @@ var errors = []struct {
        {"//\ufeff", token.COMMENT, 2, "//\ufeff", "illegal byte order mark"},                                // only first BOM is ignored
        {"'\ufeff" + `'`, token.CHAR, 1, "'\ufeff" + `'`, "illegal byte order mark"},                         // only first BOM is ignored
        {`"` + "abc\ufeffdef" + `"`, token.STRING, 4, `"` + "abc\ufeffdef" + `"`, "illegal byte order mark"}, // only first BOM is ignored
+       {"abc\x00def", token.IDENT, 3, "abc", "illegal character NUL"},
+       {"abc\x00", token.IDENT, 3, "abc", "illegal character NUL"},
 }
 
 func TestScanErrors(t *testing.T) {
@@ -889,26 +891,37 @@ func BenchmarkScan(b *testing.B) {
        }
 }
 
-func BenchmarkScanFile(b *testing.B) {
-       b.StopTimer()
-       const filename = "scanner.go"
-       src, err := os.ReadFile(filename)
-       if err != nil {
-               panic(err)
-       }
-       fset := token.NewFileSet()
-       file := fset.AddFile(filename, fset.Base(), len(src))
-       b.SetBytes(int64(len(src)))
-       var s Scanner
-       b.StartTimer()
-       for i := 0; i < b.N; i++ {
-               s.Init(file, src, nil, ScanComments)
-               for {
-                       _, tok, _ := s.Scan()
-                       if tok == token.EOF {
-                               break
+func BenchmarkScanFiles(b *testing.B) {
+       // Scan a few arbitrary large files, and one small one, to provide some
+       // variety in benchmarks.
+       for _, p := range []string{
+               "go/types/expr.go",
+               "go/parser/parser.go",
+               "net/http/server.go",
+               "go/scanner/errors.go",
+       } {
+               b.Run(p, func(b *testing.B) {
+                       b.StopTimer()
+                       filename := filepath.Join("..", "..", filepath.FromSlash(p))
+                       src, err := os.ReadFile(filename)
+                       if err != nil {
+                               b.Fatal(err)
                        }
-               }
+                       fset := token.NewFileSet()
+                       file := fset.AddFile(filename, fset.Base(), len(src))
+                       b.SetBytes(int64(len(src)))
+                       var s Scanner
+                       b.StartTimer()
+                       for i := 0; i < b.N; i++ {
+                               s.Init(file, src, nil, ScanComments)
+                               for {
+                                       _, tok, _ := s.Scan()
+                                       if tok == token.EOF {
+                                               break
+                                       }
+                               }
+                       }
+               })
        }
 }
 
index a21f5fd056027641a91a0c8cd8519beeab8057f1..0d7982c67059374be2c291fd3bd312b7a3e950d8 100644 (file)
@@ -278,7 +278,7 @@ func (f *File) Pos(offset int) Pos {
 //
 func (f *File) Offset(p Pos) int {
        if int(p) < f.base || int(p) > f.base+f.size {
-               panic(fmt.Sprintf("invalid Pos value %d (should be in [%d, %d[)", p, f.base, f.base+f.size))
+               panic(fmt.Sprintf("invalid Pos value %d (should be in [%d, %d])", p, f.base, f.base+f.size))
        }
        return int(p) - f.base
 }
@@ -346,7 +346,7 @@ func (f *File) position(p Pos, adjusted bool) (pos Position) {
 func (f *File) PositionFor(p Pos, adjusted bool) (pos Position) {
        if p != NoPos {
                if int(p) < f.base || int(p) > f.base+f.size {
-                       panic(fmt.Sprintf("invalid Pos value %d (should be in [%d, %d[)", p, f.base, f.base+f.size))
+                       panic(fmt.Sprintf("invalid Pos value %d (should be in [%d, %d])", p, f.base, f.base+f.size))
                }
                pos = f.position(p, adjusted)
        }
@@ -540,7 +540,7 @@ func searchInts(a []int, x int) int {
        // TODO(gri): Remove this when compilers have caught up.
        i, j := 0, len(a)
        for i < j {
-               h := i + (j-i)/2 // avoid overflow when computing h
+               h := i + (j-i)>>1 // avoid overflow when computing h
                // i ≤ h < j
                if a[h] <= x {
                        i = h + 1
diff --git a/libgo/go/go/token/position_bench_test.go b/libgo/go/go/token/position_bench_test.go
new file mode 100644 (file)
index 0000000..41be728
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package token
+
+import (
+       "testing"
+)
+
+func BenchmarkSearchInts(b *testing.B) {
+       data := make([]int, 10000)
+       for i := 0; i < 10000; i++ {
+               data[i] = i
+       }
+       const x = 8
+       if r := searchInts(data, x); r != x {
+               b.Errorf("got index = %d; want %d", r, x)
+       }
+       b.ResetTimer()
+       for i := 0; i < b.N; i++ {
+               searchInts(data, x)
+       }
+}
index acd1899c39d9e5ff07c6ada9e2fb8b449ab7ac76..d645b48c1d880936abddc4998e6b71f5b9e81a39 100644 (file)
@@ -102,6 +102,13 @@ type ImporterFrom interface {
 // A Config specifies the configuration for type checking.
 // The zero value for Config is a ready-to-use default configuration.
 type Config struct {
+       // goVersion describes the accepted Go language version. The string
+       // must follow the format "go%d.%d" (e.g. "go1.12") or it must be
+       // empty; an empty string indicates the latest language version.
+       // If the format is invalid, invoking the type checker will cause a
+       // panic.
+       goVersion string
+
        // If IgnoreFuncBodies is set, function bodies are not
        // type-checked.
        IgnoreFuncBodies bool
@@ -155,95 +162,7 @@ func srcimporter_setUsesCgo(conf *Config) {
        conf.go115UsesCgo = true
 }
 
-// Info holds result type information for a type-checked package.
-// Only the information for which a map is provided is collected.
-// If the package has type errors, the collected information may
-// be incomplete.
-type Info struct {
-       // Types maps expressions to their types, and for constant
-       // expressions, also their values. Invalid expressions are
-       // omitted.
-       //
-       // For (possibly parenthesized) identifiers denoting built-in
-       // functions, the recorded signatures are call-site specific:
-       // if the call result is not a constant, the recorded type is
-       // an argument-specific signature. Otherwise, the recorded type
-       // is invalid.
-       //
-       // The Types map does not record the type of every identifier,
-       // only those that appear where an arbitrary expression is
-       // permitted. For instance, the identifier f in a selector
-       // expression x.f is found only in the Selections map, the
-       // identifier z in a variable declaration 'var z int' is found
-       // only in the Defs map, and identifiers denoting packages in
-       // qualified identifiers are collected in the Uses map.
-       Types map[ast.Expr]TypeAndValue
-
-       // Defs maps identifiers to the objects they define (including
-       // package names, dots "." of dot-imports, and blank "_" identifiers).
-       // For identifiers that do not denote objects (e.g., the package name
-       // in package clauses, or symbolic variables t in t := x.(type) of
-       // type switch headers), the corresponding objects are nil.
-       //
-       // For an embedded field, Defs returns the field *Var it defines.
-       //
-       // Invariant: Defs[id] == nil || Defs[id].Pos() == id.Pos()
-       Defs map[*ast.Ident]Object
-
-       // Uses maps identifiers to the objects they denote.
-       //
-       // For an embedded field, Uses returns the *TypeName it denotes.
-       //
-       // Invariant: Uses[id].Pos() != id.Pos()
-       Uses map[*ast.Ident]Object
-
-       // Implicits maps nodes to their implicitly declared objects, if any.
-       // The following node and object types may appear:
-       //
-       //     node               declared object
-       //
-       //     *ast.ImportSpec    *PkgName for imports without renames
-       //     *ast.CaseClause    type-specific *Var for each type switch case clause (incl. default)
-       //     *ast.Field         anonymous parameter *Var (incl. unnamed results)
-       //
-       Implicits map[ast.Node]Object
-
-       // Selections maps selector expressions (excluding qualified identifiers)
-       // to their corresponding selections.
-       Selections map[*ast.SelectorExpr]*Selection
-
-       // Scopes maps ast.Nodes to the scopes they define. Package scopes are not
-       // associated with a specific node but with all files belonging to a package.
-       // Thus, the package scope can be found in the type-checked Package object.
-       // Scopes nest, with the Universe scope being the outermost scope, enclosing
-       // the package scope, which contains (one or more) files scopes, which enclose
-       // function scopes which in turn enclose statement and function literal scopes.
-       // Note that even though package-level functions are declared in the package
-       // scope, the function scopes are embedded in the file scope of the file
-       // containing the function declaration.
-       //
-       // The following node types may appear in Scopes:
-       //
-       //     *ast.File
-       //     *ast.FuncType
-       //     *ast.BlockStmt
-       //     *ast.IfStmt
-       //     *ast.SwitchStmt
-       //     *ast.TypeSwitchStmt
-       //     *ast.CaseClause
-       //     *ast.CommClause
-       //     *ast.ForStmt
-       //     *ast.RangeStmt
-       //
-       Scopes map[ast.Node]*Scope
-
-       // InitOrder is the list of package-level initializers in the order in which
-       // they must be executed. Initializers referring to variables related by an
-       // initialization dependency appear in topological order, the others appear
-       // in source order. Variables without an initialization expression do not
-       // appear in this list.
-       InitOrder []*Initializer
-}
+// The Info struct is found in api_notypeparams.go and api_typeparams.go.
 
 // TypeOf returns the type of expression e, or nil if not found.
 // Precondition: the Types, Uses and Defs maps are populated.
@@ -335,6 +254,13 @@ func (tv TypeAndValue) HasOk() bool {
        return tv.mode == commaok || tv.mode == mapindex
 }
 
+// _Inferred reports the _Inferred type arguments and signature
+// for a parameterized function call that uses type inference.
+type _Inferred struct {
+       Targs []Type
+       Sig   *Signature
+}
+
 // An Initializer describes a package-level variable, or a list of variables in case
 // of a multi-valued initialization expression, and the corresponding initialization
 // expression.
@@ -388,7 +314,7 @@ func AssignableTo(V, T Type) bool {
 // ConvertibleTo reports whether a value of type V is convertible to a value of type T.
 func ConvertibleTo(V, T Type) bool {
        x := operand{mode: value, typ: V}
-       return x.convertibleTo(nil, T) // check not needed for non-constant x
+       return x.convertibleTo(nil, T, nil) // check not needed for non-constant x
 }
 
 // Implements reports whether type V implements interface T.
diff --git a/libgo/go/go/types/api_notypeparams.go b/libgo/go/go/types/api_notypeparams.go
new file mode 100644 (file)
index 0000000..9f7cb7e
--- /dev/null
@@ -0,0 +1,104 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !typeparams
+// +build !typeparams
+
+package types
+
+import "go/ast"
+
+// Info holds result type information for a type-checked package.
+// Only the information for which a map is provided is collected.
+// If the package has type errors, the collected information may
+// be incomplete.
+type Info struct {
+       // Types maps expressions to their types, and for constant
+       // expressions, also their values. Invalid expressions are
+       // omitted.
+       //
+       // For (possibly parenthesized) identifiers denoting built-in
+       // functions, the recorded signatures are call-site specific:
+       // if the call result is not a constant, the recorded type is
+       // an argument-specific signature. Otherwise, the recorded type
+       // is invalid.
+       //
+       // The Types map does not record the type of every identifier,
+       // only those that appear where an arbitrary expression is
+       // permitted. For instance, the identifier f in a selector
+       // expression x.f is found only in the Selections map, the
+       // identifier z in a variable declaration 'var z int' is found
+       // only in the Defs map, and identifiers denoting packages in
+       // qualified identifiers are collected in the Uses map.
+       Types map[ast.Expr]TypeAndValue
+
+       // Defs maps identifiers to the objects they define (including
+       // package names, dots "." of dot-imports, and blank "_" identifiers).
+       // For identifiers that do not denote objects (e.g., the package name
+       // in package clauses, or symbolic variables t in t := x.(type) of
+       // type switch headers), the corresponding objects are nil.
+       //
+       // For an embedded field, Defs returns the field *Var it defines.
+       //
+       // Invariant: Defs[id] == nil || Defs[id].Pos() == id.Pos()
+       Defs map[*ast.Ident]Object
+
+       // Uses maps identifiers to the objects they denote.
+       //
+       // For an embedded field, Uses returns the *TypeName it denotes.
+       //
+       // Invariant: Uses[id].Pos() != id.Pos()
+       Uses map[*ast.Ident]Object
+
+       // Implicits maps nodes to their implicitly declared objects, if any.
+       // The following node and object types may appear:
+       //
+       //     node               declared object
+       //
+       //     *ast.ImportSpec    *PkgName for imports without renames
+       //     *ast.CaseClause    type-specific *Var for each type switch case clause (incl. default)
+       //     *ast.Field         anonymous parameter *Var (incl. unnamed results)
+       //
+       Implicits map[ast.Node]Object
+
+       // Selections maps selector expressions (excluding qualified identifiers)
+       // to their corresponding selections.
+       Selections map[*ast.SelectorExpr]*Selection
+
+       // Scopes maps ast.Nodes to the scopes they define. Package scopes are not
+       // associated with a specific node but with all files belonging to a package.
+       // Thus, the package scope can be found in the type-checked Package object.
+       // Scopes nest, with the Universe scope being the outermost scope, enclosing
+       // the package scope, which contains (one or more) files scopes, which enclose
+       // function scopes which in turn enclose statement and function literal scopes.
+       // Note that even though package-level functions are declared in the package
+       // scope, the function scopes are embedded in the file scope of the file
+       // containing the function declaration.
+       //
+       // The following node types may appear in Scopes:
+       //
+       //     *ast.File
+       //     *ast.FuncType
+       //     *ast.BlockStmt
+       //     *ast.IfStmt
+       //     *ast.SwitchStmt
+       //     *ast.TypeSwitchStmt
+       //     *ast.CaseClause
+       //     *ast.CommClause
+       //     *ast.ForStmt
+       //     *ast.RangeStmt
+       //
+       Scopes map[ast.Node]*Scope
+
+       // InitOrder is the list of package-level initializers in the order in which
+       // they must be executed. Initializers referring to variables related by an
+       // initialization dependency appear in topological order, the others appear
+       // in source order. Variables without an initialization expression do not
+       // appear in this list.
+       InitOrder []*Initializer
+}
+
+func getInferred(info *Info) map[ast.Expr]_Inferred {
+       return nil
+}
index ea1ae1ea54b8c0fae498e7c8076de1cb07f89928..0ff8da6c652d43cd7e397519b8ce3544f2bcf22d 100644 (file)
@@ -9,6 +9,7 @@ import (
        "fmt"
        "go/ast"
        "go/importer"
+       "go/internal/typeparams"
        "go/parser"
        "go/token"
        "internal/testenv"
@@ -20,9 +21,15 @@ import (
        . "go/types"
 )
 
+// pkgFor parses and type checks the package specified by path and source,
+// populating info if provided.
+//
+// If source begins with "package generic_" and type parameters are enabled,
+// generic code is permitted.
 func pkgFor(path, source string, info *Info) (*Package, error) {
        fset := token.NewFileSet()
-       f, err := parser.ParseFile(fset, path, source, 0)
+       mode := modeForSource(source)
+       f, err := parser.ParseFile(fset, path, source, mode)
        if err != nil {
                return nil, err
        }
@@ -43,9 +50,21 @@ func mustTypecheck(t *testing.T, path, source string, info *Info) string {
        return pkg.Name()
 }
 
-func mayTypecheck(t *testing.T, path, source string, info *Info) string {
+// genericPkg is a prefix for packages that should be type checked with
+// generics.
+const genericPkg = "package generic_"
+
+func modeForSource(src string) parser.Mode {
+       if !strings.HasPrefix(src, genericPkg) {
+               return typeparams.DisallowParsing
+       }
+       return 0
+}
+
+func mayTypecheck(t *testing.T, path, source string, info *Info) (string, error) {
        fset := token.NewFileSet()
-       f, err := parser.ParseFile(fset, path, source, 0)
+       mode := modeForSource(source)
+       f, err := parser.ParseFile(fset, path, source, mode)
        if f == nil { // ignore errors unless f is nil
                t.Fatalf("%s: unable to parse: %s", path, err)
        }
@@ -53,8 +72,8 @@ func mayTypecheck(t *testing.T, path, source string, info *Info) string {
                Error:    func(err error) {},
                Importer: importer.Default(),
        }
-       pkg, _ := conf.Check(f.Name.Name, fset, []*ast.File{f}, info)
-       return pkg.Name()
+       pkg, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, info)
+       return pkg.Name(), err
 }
 
 func TestValuesInfo(t *testing.T) {
@@ -176,6 +195,9 @@ func TestValuesInfo(t *testing.T) {
 }
 
 func TestTypesInfo(t *testing.T) {
+       // Test sources that are not expected to typecheck must start with the broken prefix.
+       const broken = "package broken_"
+
        var tests = []struct {
                src  string
                expr string // expression
@@ -188,6 +210,39 @@ func TestTypesInfo(t *testing.T) {
                {`package b3; var x interface{} = 0i`, `0i`, `complex128`},
                {`package b4; var x interface{} = "foo"`, `"foo"`, `string`},
 
+               // uses of nil
+               {`package n0; var _ *int = nil`, `nil`, `untyped nil`},
+               {`package n1; var _ func() = nil`, `nil`, `untyped nil`},
+               {`package n2; var _ []byte = nil`, `nil`, `untyped nil`},
+               {`package n3; var _ map[int]int = nil`, `nil`, `untyped nil`},
+               {`package n4; var _ chan int = nil`, `nil`, `untyped nil`},
+               {`package n5; var _ interface{} = nil`, `nil`, `untyped nil`},
+               {`package n6; import "unsafe"; var _ unsafe.Pointer = nil`, `nil`, `untyped nil`},
+
+               {`package n10; var (x *int; _ = x == nil)`, `nil`, `untyped nil`},
+               {`package n11; var (x func(); _ = x == nil)`, `nil`, `untyped nil`},
+               {`package n12; var (x []byte; _ = x == nil)`, `nil`, `untyped nil`},
+               {`package n13; var (x map[int]int; _ = x == nil)`, `nil`, `untyped nil`},
+               {`package n14; var (x chan int; _ = x == nil)`, `nil`, `untyped nil`},
+               {`package n15; var (x interface{}; _ = x == nil)`, `nil`, `untyped nil`},
+               {`package n15; import "unsafe"; var (x unsafe.Pointer; _ = x == nil)`, `nil`, `untyped nil`},
+
+               {`package n20; var _ = (*int)(nil)`, `nil`, `untyped nil`},
+               {`package n21; var _ = (func())(nil)`, `nil`, `untyped nil`},
+               {`package n22; var _ = ([]byte)(nil)`, `nil`, `untyped nil`},
+               {`package n23; var _ = (map[int]int)(nil)`, `nil`, `untyped nil`},
+               {`package n24; var _ = (chan int)(nil)`, `nil`, `untyped nil`},
+               {`package n25; var _ = (interface{})(nil)`, `nil`, `untyped nil`},
+               {`package n26; import "unsafe"; var _ = unsafe.Pointer(nil)`, `nil`, `untyped nil`},
+
+               {`package n30; func f(*int) { f(nil) }`, `nil`, `untyped nil`},
+               {`package n31; func f(func()) { f(nil) }`, `nil`, `untyped nil`},
+               {`package n32; func f([]byte) { f(nil) }`, `nil`, `untyped nil`},
+               {`package n33; func f(map[int]int) { f(nil) }`, `nil`, `untyped nil`},
+               {`package n34; func f(chan int) { f(nil) }`, `nil`, `untyped nil`},
+               {`package n35; func f(interface{}) { f(nil) }`, `nil`, `untyped nil`},
+               {`package n35; import "unsafe"; func f(unsafe.Pointer) { f(nil) }`, `nil`, `untyped nil`},
+
                // comma-ok expressions
                {`package p0; var x interface{}; var _, _ = x.(int)`,
                        `x.(int)`,
@@ -268,18 +323,65 @@ func TestTypesInfo(t *testing.T) {
                        `[][]struct{}`,
                },
 
+               // issue 47243
+               {`package issue47243_a; var x int32; var _ = x << 3`, `3`, `untyped int`},
+               {`package issue47243_b; var x int32; var _ = x << 3.`, `3.`, `uint`}, // issue 47410: should be untyped float
+               {`package issue47243_c; var x int32; var _ = 1 << x`, `1 << x`, `int`},
+               {`package issue47243_d; var x int32; var _ = 1 << x`, `1`, `int`},
+               {`package issue47243_e; var x int32; var _ = 1 << 2`, `1`, `untyped int`},
+               {`package issue47243_f; var x int32; var _ = 1 << 2`, `2`, `untyped int`},
+               {`package issue47243_g; var x int32; var _ = int(1) << 2`, `2`, `untyped int`},
+               {`package issue47243_h; var x int32; var _ = 1 << (2 << x)`, `1`, `int`},
+               {`package issue47243_i; var x int32; var _ = 1 << (2 << x)`, `(2 << x)`, `untyped int`},
+               {`package issue47243_j; var x int32; var _ = 1 << (2 << x)`, `2`, `untyped int`},
+
                // tests for broken code that doesn't parse or type-check
-               {`package x0; func _() { var x struct {f string}; x.f := 0 }`, `x.f`, `string`},
-               {`package x1; func _() { var z string; type x struct {f string}; y := &x{q: z}}`, `z`, `string`},
-               {`package x2; func _() { var a, b string; type x struct {f string}; z := &x{f: a; f: b;}}`, `b`, `string`},
-               {`package x3; var x = panic("");`, `panic`, `func(interface{})`},
+               {broken + `x0; func _() { var x struct {f string}; x.f := 0 }`, `x.f`, `string`},
+               {broken + `x1; func _() { var z string; type x struct {f string}; y := &x{q: z}}`, `z`, `string`},
+               {broken + `x2; func _() { var a, b string; type x struct {f string}; z := &x{f: a; f: b;}}`, `b`, `string`},
+               {broken + `x3; var x = panic("");`, `panic`, `func(interface{})`},
                {`package x4; func _() { panic("") }`, `panic`, `func(interface{})`},
-               {`package x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string][-1]int`},
+               {broken + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string][-1]int`},
+
+               // parameterized functions
+               {genericPkg + `p0; func f[T any](T); var _ = f[int]`, `f`, `func[T₁ interface{}](T₁)`},
+               {genericPkg + `p1; func f[T any](T); var _ = f[int]`, `f[int]`, `func(int)`},
+               {genericPkg + `p2; func f[T any](T); func _() { f(42) }`, `f`, `func[T₁ interface{}](T₁)`},
+               {genericPkg + `p3; func f[T any](T); func _() { f(42) }`, `f(42)`, `()`},
+
+               // type parameters
+               {genericPkg + `t0; type t[] int; var _ t`, `t`, `generic_t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t
+               {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[P₁ interface{}]`},
+               {genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[P₁ interface{}]`},
+               {genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[P₁, Q₂ interface{}]`},
+
+               // TODO (rFindley): compare with types2, which resolves the type broken_t4.t[P₁, Q₂ interface{m()}] here
+               {broken + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `broken_t4.t`},
+
+               // instantiated types must be sanitized
+               {genericPkg + `g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `generic_g0.t[int]`},
+
+               // issue 45096
+               {genericPkg + `issue45096; func _[T interface{ type int8, int16, int32  }](x T) { _ = x < 0 }`, `0`, `T₁`},
        }
 
        for _, test := range tests {
+               ResetId() // avoid renumbering of type parameter ids when adding tests
+               if strings.HasPrefix(test.src, genericPkg) && !typeparams.Enabled {
+                       continue
+               }
                info := Info{Types: make(map[ast.Expr]TypeAndValue)}
-               name := mayTypecheck(t, "TypesInfo", test.src, &info)
+               var name string
+               if strings.HasPrefix(test.src, broken) {
+                       var err error
+                       name, err = mayTypecheck(t, "TypesInfo", test.src, &info)
+                       if err == nil {
+                               t.Errorf("package %s: expected to fail but passed", name)
+                               continue
+                       }
+               } else {
+                       name = mustTypecheck(t, "TypesInfo", test.src, &info)
+               }
 
                // look for expression type
                var typ Type
@@ -301,6 +403,103 @@ func TestTypesInfo(t *testing.T) {
        }
 }
 
+func TestDefsInfo(t *testing.T) {
+       var tests = []struct {
+               src  string
+               obj  string
+               want string
+       }{
+               {`package p0; const x = 42`, `x`, `const p0.x untyped int`},
+               {`package p1; const x int = 42`, `x`, `const p1.x int`},
+               {`package p2; var x int`, `x`, `var p2.x int`},
+               {`package p3; type x int`, `x`, `type p3.x int`},
+               {`package p4; func f()`, `f`, `func p4.f()`},
+               {`package p5; func f() int { x, _ := 1, 2; return x }`, `_`, `var _ int`},
+
+               // generic types must be sanitized
+               // (need to use sufficiently nested types to provoke unexpanded types)
+               {genericPkg + `g0; type t[P any] P; const x = t[int](42)`, `x`, `const generic_g0.x generic_g0.t[int]`},
+               {genericPkg + `g1; type t[P any] P; var x = t[int](42)`, `x`, `var generic_g1.x generic_g1.t[int]`},
+               {genericPkg + `g2; type t[P any] P; type x struct{ f t[int] }`, `x`, `type generic_g2.x struct{f generic_g2.t[int]}`},
+               {genericPkg + `g3; type t[P any] P; func f(x struct{ f t[string] }); var g = f`, `g`, `var generic_g3.g func(x struct{f generic_g3.t[string]})`},
+       }
+
+       for _, test := range tests {
+               if strings.HasPrefix(test.src, genericPkg) && !typeparams.Enabled {
+                       continue
+               }
+               info := Info{
+                       Defs: make(map[*ast.Ident]Object),
+               }
+               name := mustTypecheck(t, "DefsInfo", test.src, &info)
+
+               // find object
+               var def Object
+               for id, obj := range info.Defs {
+                       if id.Name == test.obj {
+                               def = obj
+                               break
+                       }
+               }
+               if def == nil {
+                       t.Errorf("package %s: %s not found", name, test.obj)
+                       continue
+               }
+
+               if got := def.String(); got != test.want {
+                       t.Errorf("package %s: got %s; want %s", name, got, test.want)
+               }
+       }
+}
+
+func TestUsesInfo(t *testing.T) {
+       var tests = []struct {
+               src  string
+               obj  string
+               want string
+       }{
+               {`package p0; func _() { _ = x }; const x = 42`, `x`, `const p0.x untyped int`},
+               {`package p1; func _() { _ = x }; const x int = 42`, `x`, `const p1.x int`},
+               {`package p2; func _() { _ = x }; var x int`, `x`, `var p2.x int`},
+               {`package p3; func _() { type _ x }; type x int`, `x`, `type p3.x int`},
+               {`package p4; func _() { _ = f }; func f()`, `f`, `func p4.f()`},
+
+               // generic types must be sanitized
+               // (need to use sufficiently nested types to provoke unexpanded types)
+               {genericPkg + `g0; func _() { _ = x }; type t[P any] P; const x = t[int](42)`, `x`, `const generic_g0.x generic_g0.t[int]`},
+               {genericPkg + `g1; func _() { _ = x }; type t[P any] P; var x = t[int](42)`, `x`, `var generic_g1.x generic_g1.t[int]`},
+               {genericPkg + `g2; func _() { type _ x }; type t[P any] P; type x struct{ f t[int] }`, `x`, `type generic_g2.x struct{f generic_g2.t[int]}`},
+               {genericPkg + `g3; func _() { _ = f }; type t[P any] P; func f(x struct{ f t[string] })`, `f`, `func generic_g3.f(x struct{f generic_g3.t[string]})`},
+       }
+
+       for _, test := range tests {
+               if strings.HasPrefix(test.src, genericPkg) && !typeparams.Enabled {
+                       continue
+               }
+               info := Info{
+                       Uses: make(map[*ast.Ident]Object),
+               }
+               name := mustTypecheck(t, "UsesInfo", test.src, &info)
+
+               // find object
+               var use Object
+               for id, obj := range info.Uses {
+                       if id.Name == test.obj {
+                               use = obj
+                               break
+                       }
+               }
+               if use == nil {
+                       t.Errorf("package %s: %s not found", name, test.obj)
+                       continue
+               }
+
+               if got := use.String(); got != test.want {
+                       t.Errorf("package %s: got %s; want %s", name, got, test.want)
+               }
+       }
+}
+
 func TestImplicitsInfo(t *testing.T) {
        testenv.MustHaveGoBuild(t)
 
@@ -1035,6 +1234,8 @@ func TestLookupFieldOrMethod(t *testing.T) {
        // Test cases assume a lookup of the form a.f or x.f, where a stands for an
        // addressable value, and x for a non-addressable value (even though a variable
        // for ease of test case writing).
+       //
+       // Should be kept in sync with TestMethodSet.
        var tests = []struct {
                src      string
                found    bool
@@ -1245,6 +1446,9 @@ func TestConvertibleTo(t *testing.T) {
                {newDefined(new(Struct)), new(Struct), true},
                {newDefined(Typ[Int]), new(Struct), false},
                {Typ[UntypedInt], Typ[Int], true},
+               {NewSlice(Typ[Int]), NewPointer(NewArray(Typ[Int], 10)), true},
+               {NewSlice(Typ[Int]), NewArray(Typ[Int], 10), false},
+               {NewSlice(Typ[Int]), NewPointer(NewArray(Typ[Uint], 10)), false},
                // Untyped string values are not permitted by the spec, so the below
                // behavior is undefined.
                {Typ[UntypedString], Typ[String], true},
diff --git a/libgo/go/go/types/api_typeparams.go b/libgo/go/go/types/api_typeparams.go
new file mode 100644 (file)
index 0000000..ed744c4
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build typeparams
+// +build typeparams
+
+package types
+
+import (
+       "go/ast"
+)
+
+type (
+       Inferred  = _Inferred
+       Sum       = _Sum
+       TypeParam = _TypeParam
+)
+
+func NewSum(types []Type) Type { return _NewSum(types) }
+
+func (s *Signature) TParams() []*TypeName           { return s._TParams() }
+func (s *Signature) SetTParams(tparams []*TypeName) { s._SetTParams(tparams) }
+
+func (t *Interface) HasTypeList() bool  { return t._HasTypeList() }
+func (t *Interface) IsComparable() bool { return t._IsComparable() }
+func (t *Interface) IsConstraint() bool { return t._IsConstraint() }
+
+func (t *Named) TParams() []*TypeName { return t._TParams() }
+func (t *Named) TArgs() []Type        { return t._TArgs() }
+func (t *Named) SetTArgs(args []Type) { t._SetTArgs(args) }
+
+// Info is documented in api_notypeparams.go.
+type Info struct {
+       Types map[ast.Expr]TypeAndValue
+
+       // Inferred maps calls of parameterized functions that use type inference to
+       // the Inferred type arguments and signature of the function called. The
+       // recorded "call" expression may be an *ast.CallExpr (as in f(x)), or an
+       // *ast.IndexExpr (s in f[T]).
+       Inferred map[ast.Expr]_Inferred
+
+       Defs       map[*ast.Ident]Object
+       Uses       map[*ast.Ident]Object
+       Implicits  map[ast.Node]Object
+       Selections map[*ast.SelectorExpr]*Selection
+       Scopes     map[ast.Node]*Scope
+       InitOrder  []*Initializer
+}
+
+func getInferred(info *Info) map[ast.Expr]_Inferred {
+       return info.Inferred
+}
diff --git a/libgo/go/go/types/api_typeparams_test.go b/libgo/go/go/types/api_typeparams_test.go
new file mode 100644 (file)
index 0000000..15c9bf0
--- /dev/null
@@ -0,0 +1,139 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build typeparams
+// +build typeparams
+
+package types_test
+
+import (
+       "fmt"
+       "go/ast"
+       "testing"
+
+       . "go/types"
+)
+
+func TestInferredInfo(t *testing.T) {
+       var tests = []struct {
+               src   string
+               fun   string
+               targs []string
+               sig   string
+       }{
+               {genericPkg + `p0; func f[T any](T); func _() { f(42) }`,
+                       `f`,
+                       []string{`int`},
+                       `func(int)`,
+               },
+               {genericPkg + `p1; func f[T any](T) T; func _() { f('@') }`,
+                       `f`,
+                       []string{`rune`},
+                       `func(rune) rune`,
+               },
+               {genericPkg + `p2; func f[T any](...T) T; func _() { f(0i) }`,
+                       `f`,
+                       []string{`complex128`},
+                       `func(...complex128) complex128`,
+               },
+               {genericPkg + `p3; func f[A, B, C any](A, *B, []C); func _() { f(1.2, new(string), []byte{}) }`,
+                       `f`,
+                       []string{`float64`, `string`, `byte`},
+                       `func(float64, *string, []byte)`,
+               },
+               {genericPkg + `p4; func f[A, B any](A, *B, ...[]B); func _() { f(1.2, new(byte)) }`,
+                       `f`,
+                       []string{`float64`, `byte`},
+                       `func(float64, *byte, ...[]byte)`,
+               },
+
+               {genericPkg + `s1; func f[T any, P interface{type *T}](x T); func _(x string) { f(x) }`,
+                       `f`,
+                       []string{`string`, `*string`},
+                       `func(x string)`,
+               },
+               {genericPkg + `s2; func f[T any, P interface{type *T}](x []T); func _(x []int) { f(x) }`,
+                       `f`,
+                       []string{`int`, `*int`},
+                       `func(x []int)`,
+               },
+               {genericPkg + `s3; type C[T any] interface{type chan<- T}; func f[T any, P C[T]](x []T); func _(x []int) { f(x) }`,
+                       `f`,
+                       []string{`int`, `chan<- int`},
+                       `func(x []int)`,
+               },
+               {genericPkg + `s4; type C[T any] interface{type chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T); func _(x []int) { f(x) }`,
+                       `f`,
+                       []string{`int`, `chan<- int`, `chan<- []*chan<- int`},
+                       `func(x []int)`,
+               },
+
+               {genericPkg + `t1; func f[T any, P interface{type *T}]() T; func _() { _ = f[string] }`,
+                       `f`,
+                       []string{`string`, `*string`},
+                       `func() string`,
+               },
+               {genericPkg + `t2; type C[T any] interface{type chan<- T}; func f[T any, P C[T]]() []T; func _() { _ = f[int] }`,
+                       `f`,
+                       []string{`int`, `chan<- int`},
+                       `func() []int`,
+               },
+               {genericPkg + `t3; type C[T any] interface{type chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T; func _() { _ = f[int] }`,
+                       `f`,
+                       []string{`int`, `chan<- int`, `chan<- []*chan<- int`},
+                       `func() []int`,
+               },
+       }
+
+       for _, test := range tests {
+               info := Info{}
+               info.Inferred = make(map[ast.Expr]Inferred)
+               name, err := mayTypecheck(t, "InferredInfo", test.src, &info)
+               if err != nil {
+                       t.Errorf("package %s: %v", name, err)
+                       continue
+               }
+
+               // look for inferred type arguments and signature
+               var targs []Type
+               var sig *Signature
+               for call, inf := range info.Inferred {
+                       var fun ast.Expr
+                       switch x := call.(type) {
+                       case *ast.CallExpr:
+                               fun = x.Fun
+                       case *ast.IndexExpr:
+                               fun = x.X
+                       default:
+                               panic(fmt.Sprintf("unexpected call expression type %T", call))
+                       }
+                       if ExprString(fun) == test.fun {
+                               targs = inf.Targs
+                               sig = inf.Sig
+                               break
+                       }
+               }
+               if targs == nil {
+                       t.Errorf("package %s: no inferred information found for %s", name, test.fun)
+                       continue
+               }
+
+               // check that type arguments are correct
+               if len(targs) != len(test.targs) {
+                       t.Errorf("package %s: got %d type arguments; want %d", name, len(targs), len(test.targs))
+                       continue
+               }
+               for i, targ := range targs {
+                       if got := targ.String(); got != test.targs[i] {
+                               t.Errorf("package %s, %d. type argument: got %s; want %s", name, i, got, test.targs[i])
+                               continue
+                       }
+               }
+
+               // check that signature is correct
+               if got := sig.String(); got != test.sig {
+                       t.Errorf("package %s: got %s; want %s", name, got, test.sig)
+               }
+       }
+}
index 616564b567d7315d4723c5ed3f7ddb46b7a35a8f..18eae62184028ade83978e76483ebc20ba8c1102 100644 (file)
@@ -7,7 +7,6 @@
 package types
 
 import (
-       "errors"
        "go/ast"
        "go/token"
 )
@@ -26,7 +25,9 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
        case constant_, variable, mapindex, value, commaok, commaerr:
                // ok
        default:
-               unreachable()
+               // we may get here because of other problems (issue #39634, crash 12)
+               check.errorf(x, 0, "cannot assign %s to %s in %s", x, T, context)
+               return
        }
 
        if isUntyped(x.typ) {
@@ -44,27 +45,35 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
                        }
                        target = Default(x.typ)
                }
-               if err := check.canConvertUntyped(x, target); err != nil {
+               newType, val, code := check.implicitTypeAndValue(x, target)
+               if code != 0 {
                        msg := check.sprintf("cannot use %s as %s value in %s", x, target, context)
-                       code := _IncompatibleAssign
-                       var ierr Error
-                       if errors.As(err, &ierr) {
-                               // Preserve these inner errors, as they are informative.
-                               switch ierr.go116code {
-                               case _TruncatedFloat:
-                                       msg += " (truncated)"
-                                       code = ierr.go116code
-                               case _NumericOverflow:
-                                       msg += " (overflows)"
-                                       code = ierr.go116code
-                               }
+                       switch code {
+                       case _TruncatedFloat:
+                               msg += " (truncated)"
+                       case _NumericOverflow:
+                               msg += " (overflows)"
+                       default:
+                               code = _IncompatibleAssign
                        }
                        check.error(x, code, msg)
                        x.mode = invalid
                        return
                }
+               if val != nil {
+                       x.val = val
+                       check.updateExprVal(x.expr, val)
+               }
+               if newType != x.typ {
+                       x.typ = newType
+                       check.updateExprType(x.expr, newType, false)
+               }
+       }
+
+       // A generic (non-instantiated) function value cannot be assigned to a variable.
+       if sig := asSignature(x.typ); sig != nil && len(sig.tparams) > 0 {
+               check.errorf(x, _Todo, "cannot use generic function %s without instantiation in %s", x, context)
        }
-       // x.typ is typed
 
        // spec: "If a left-hand side is the blank identifier, any typed or
        // non-constant value except for the predeclared identifier nil may
@@ -148,6 +157,7 @@ func (check *Checker) initVar(lhs *Var, x *operand, context string) Type {
 
 func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type {
        if x.mode == invalid || x.typ == Typ[Invalid] {
+               check.useLHS(lhs)
                return nil
        }
 
@@ -221,25 +231,27 @@ func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type {
 
 // If returnPos is valid, initVars is called to type-check the assignment of
 // return expressions, and returnPos is the position of the return statement.
-func (check *Checker) initVars(lhs []*Var, rhs []ast.Expr, returnPos token.Pos) {
-       l := len(lhs)
-       get, r, commaOk := unpack(func(x *operand, i int) { check.multiExpr(x, rhs[i]) }, len(rhs), l == 2 && !returnPos.IsValid())
-       if get == nil || l != r {
-               // invalidate lhs and use rhs
+func (check *Checker) initVars(lhs []*Var, origRHS []ast.Expr, returnPos token.Pos) {
+       rhs, commaOk := check.exprList(origRHS, len(lhs) == 2 && !returnPos.IsValid())
+
+       if len(lhs) != len(rhs) {
+               // invalidate lhs
                for _, obj := range lhs {
                        if obj.typ == nil {
                                obj.typ = Typ[Invalid]
                        }
                }
-               if get == nil {
-                       return // error reported by unpack
+               // don't report an error if we already reported one
+               for _, x := range rhs {
+                       if x.mode == invalid {
+                               return
+                       }
                }
-               check.useGetter(get, r)
                if returnPos.IsValid() {
-                       check.errorf(atPos(returnPos), _WrongResultCount, "wrong number of return values (want %d, got %d)", l, r)
+                       check.errorf(atPos(returnPos), _WrongResultCount, "wrong number of return values (want %d, got %d)", len(lhs), len(rhs))
                        return
                }
-               check.errorf(rhs[0], _WrongAssignCount, "cannot initialize %d variables with %d values", l, r)
+               check.errorf(rhs[0], _WrongAssignCount, "cannot initialize %d variables with %d values", len(lhs), len(rhs))
                return
        }
 
@@ -248,50 +260,46 @@ func (check *Checker) initVars(lhs []*Var, rhs []ast.Expr, returnPos token.Pos)
                context = "return statement"
        }
 
-       var x operand
        if commaOk {
                var a [2]Type
                for i := range a {
-                       get(&x, i)
-                       a[i] = check.initVar(lhs[i], &x, context)
+                       a[i] = check.initVar(lhs[i], rhs[i], context)
                }
-               check.recordCommaOkTypes(rhs[0], a)
+               check.recordCommaOkTypes(origRHS[0], a)
                return
        }
 
        for i, lhs := range lhs {
-               get(&x, i)
-               check.initVar(lhs, &x, context)
+               check.initVar(lhs, rhs[i], context)
        }
 }
 
-func (check *Checker) assignVars(lhs, rhs []ast.Expr) {
-       l := len(lhs)
-       get, r, commaOk := unpack(func(x *operand, i int) { check.multiExpr(x, rhs[i]) }, len(rhs), l == 2)
-       if get == nil {
+func (check *Checker) assignVars(lhs, origRHS []ast.Expr) {
+       rhs, commaOk := check.exprList(origRHS, len(lhs) == 2)
+
+       if len(lhs) != len(rhs) {
                check.useLHS(lhs...)
-               return // error reported by unpack
-       }
-       if l != r {
-               check.useGetter(get, r)
-               check.errorf(rhs[0], _WrongAssignCount, "cannot assign %d values to %d variables", r, l)
+               // don't report an error if we already reported one
+               for _, x := range rhs {
+                       if x.mode == invalid {
+                               return
+                       }
+               }
+               check.errorf(rhs[0], _WrongAssignCount, "cannot assign %d values to %d variables", len(rhs), len(lhs))
                return
        }
 
-       var x operand
        if commaOk {
                var a [2]Type
                for i := range a {
-                       get(&x, i)
-                       a[i] = check.assignVar(lhs[i], &x)
+                       a[i] = check.assignVar(lhs[i], rhs[i])
                }
-               check.recordCommaOkTypes(rhs[0], a)
+               check.recordCommaOkTypes(origRHS[0], a)
                return
        }
 
        for i, lhs := range lhs {
-               get(&x, i)
-               check.assignVar(lhs, &x)
+               check.assignVar(lhs, rhs[i])
        }
 }
 
@@ -300,40 +308,60 @@ func (check *Checker) shortVarDecl(pos positioner, lhs, rhs []ast.Expr) {
        scope := check.scope
 
        // collect lhs variables
-       var newVars []*Var
-       var lhsVars = make([]*Var, len(lhs))
+       seen := make(map[string]bool, len(lhs))
+       lhsVars := make([]*Var, len(lhs))
+       newVars := make([]*Var, 0, len(lhs))
+       hasErr := false
        for i, lhs := range lhs {
-               var obj *Var
-               if ident, _ := lhs.(*ast.Ident); ident != nil {
-                       // Use the correct obj if the ident is redeclared. The
-                       // variable's scope starts after the declaration; so we
-                       // must use Scope.Lookup here and call Scope.Insert
-                       // (via check.declare) later.
-                       name := ident.Name
-                       if alt := scope.Lookup(name); alt != nil {
-                               // redeclared object must be a variable
-                               if alt, _ := alt.(*Var); alt != nil {
-                                       obj = alt
-                               } else {
-                                       check.errorf(lhs, _UnassignableOperand, "cannot assign to %s", lhs)
-                               }
-                               check.recordUse(ident, alt)
+               ident, _ := lhs.(*ast.Ident)
+               if ident == nil {
+                       check.useLHS(lhs)
+                       // TODO(rFindley) this is redundant with a parser error. Consider omitting?
+                       check.errorf(lhs, _BadDecl, "non-name %s on left side of :=", lhs)
+                       hasErr = true
+                       continue
+               }
+
+               name := ident.Name
+               if name != "_" {
+                       if seen[name] {
+                               check.errorf(lhs, _RepeatedDecl, "%s repeated on left side of :=", lhs)
+                               hasErr = true
+                               continue
+                       }
+                       seen[name] = true
+               }
+
+               // Use the correct obj if the ident is redeclared. The
+               // variable's scope starts after the declaration; so we
+               // must use Scope.Lookup here and call Scope.Insert
+               // (via check.declare) later.
+               if alt := scope.Lookup(name); alt != nil {
+                       check.recordUse(ident, alt)
+                       // redeclared object must be a variable
+                       if obj, _ := alt.(*Var); obj != nil {
+                               lhsVars[i] = obj
                        } else {
-                               // declare new variable, possibly a blank (_) variable
-                               obj = NewVar(ident.Pos(), check.pkg, name, nil)
-                               if name != "_" {
-                                       newVars = append(newVars, obj)
-                               }
-                               check.recordDef(ident, obj)
+                               check.errorf(lhs, _UnassignableOperand, "cannot assign to %s", lhs)
+                               hasErr = true
                        }
-               } else {
-                       check.useLHS(lhs)
-                       check.invalidAST(lhs, "cannot declare %s", lhs)
+                       continue
                }
+
+               // declare new variable
+               obj := NewVar(ident.Pos(), check.pkg, name, nil)
+               lhsVars[i] = obj
+               if name != "_" {
+                       newVars = append(newVars, obj)
+               }
+               check.recordDef(ident, obj)
+       }
+
+       // create dummy variables where the lhs is invalid
+       for i, obj := range lhsVars {
                if obj == nil {
-                       obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable
+                       lhsVars[i] = NewVar(lhs[i].Pos(), check.pkg, "_", nil)
                }
-               lhsVars[i] = obj
        }
 
        check.initVars(lhsVars, rhs, token.NoPos)
@@ -341,17 +369,18 @@ func (check *Checker) shortVarDecl(pos positioner, lhs, rhs []ast.Expr) {
        // process function literals in rhs expressions before scope changes
        check.processDelayed(top)
 
-       // declare new variables
-       if len(newVars) > 0 {
-               // spec: "The scope of a constant or variable identifier declared inside
-               // a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
-               // for short variable declarations) and ends at the end of the innermost
-               // containing block."
-               scopePos := rhs[len(rhs)-1].End()
-               for _, obj := range newVars {
-                       check.declare(scope, nil, obj, scopePos) // recordObject already called
-               }
-       } else {
+       if len(newVars) == 0 && !hasErr {
                check.softErrorf(pos, _NoNewVar, "no new variables on left side of :=")
+               return
+       }
+
+       // declare new variables
+       // spec: "The scope of a constant or variable identifier declared inside
+       // a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
+       // for short variable declarations) and ends at the end of the innermost
+       // containing block."
+       scopePos := rhs[len(rhs)-1].End()
+       for _, obj := range newVars {
+               check.declare(scope, nil, obj, scopePos) // id = nil: recordDef already called
        }
 }
index fd35f7867696d789b93999a04e285144d7d5b849..2a2d54da88227a60bcb6f5c3dfbf019db61faed4 100644 (file)
@@ -31,8 +31,8 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
        // For len(x) and cap(x) we need to know if x contains any function calls or
        // receive operations. Save/restore current setting and set hasCallOrRecv to
        // false for the evaluation of x so that we can check it afterwards.
-       // Note: We must do this _before_ calling unpack because unpack evaluates the
-       //       first argument before we even call arg(x, 0)!
+       // Note: We must do this _before_ calling exprList because exprList evaluates
+       //       all arguments.
        if id == _Len || id == _Cap {
                defer func(b bool) {
                        check.hasCallOrRecv = b
@@ -41,15 +41,14 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
        }
 
        // determine actual arguments
-       var arg getter
+       var arg func(*operand, int) // TODO(gri) remove use of arg getter in favor of using xlist directly
        nargs := len(call.Args)
        switch id {
        default:
                // make argument getter
-               arg, nargs, _ = unpack(func(x *operand, i int) { check.multiExpr(x, call.Args[i]) }, nargs, false)
-               if arg == nil {
-                       return
-               }
+               xlist, _ := check.exprList(call.Args, false)
+               arg = func(x *operand, i int) { *x = *xlist[i]; x.typ = expand(x.typ) }
+               nargs = len(xlist)
                // evaluate first argument, if present
                if nargs > 0 {
                        arg(x, 0)
@@ -84,7 +83,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                // of S and the respective parameter passing rules apply."
                S := x.typ
                var T Type
-               if s, _ := S.Underlying().(*Slice); s != nil {
+               if s := asSlice(S); s != nil {
                        T = s.elem
                } else {
                        check.invalidArg(x, _InvalidAppend, "%s is not a slice", x)
@@ -121,14 +120,17 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                // check general case by creating custom signature
                sig := makeSig(S, S, NewSlice(T)) // []T required for variadic signature
                sig.variadic = true
-               check.arguments(x, call, sig, func(x *operand, i int) {
-                       // only evaluate arguments that have not been evaluated before
-                       if i < len(alist) {
-                               *x = alist[i]
-                               return
-                       }
-                       arg(x, i)
-               }, nargs)
+               var xlist []*operand
+               // convert []operand to []*operand
+               for i := range alist {
+                       xlist = append(xlist, &alist[i])
+               }
+               for i := len(alist); i < nargs; i++ {
+                       var x operand
+                       arg(&x, i)
+                       xlist = append(xlist, &x)
+               }
+               check.arguments(call, sig, nil, xlist) // discard result (we know the result type)
                // ok to continue even if check.arguments reported errors
 
                x.mode = value
@@ -143,7 +145,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                mode := invalid
                var typ Type
                var val constant.Value
-               switch typ = implicitArrayDeref(x.typ.Underlying()); t := typ.(type) {
+               switch typ = implicitArrayDeref(optype(x.typ)); t := typ.(type) {
                case *Basic:
                        if isString(t) && id == _Len {
                                if x.mode == constant_ {
@@ -176,6 +178,25 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                        if id == _Len {
                                mode = value
                        }
+
+               case *_Sum:
+                       if t.is(func(t Type) bool {
+                               switch t := under(t).(type) {
+                               case *Basic:
+                                       if isString(t) && id == _Len {
+                                               return true
+                                       }
+                               case *Array, *Slice, *Chan:
+                                       return true
+                               case *Map:
+                                       if id == _Len {
+                                               return true
+                                       }
+                               }
+                               return false
+                       }) {
+                               mode = value
+                       }
                }
 
                if mode == invalid && typ != Typ[Invalid] {
@@ -196,7 +217,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 
        case _Close:
                // close(c)
-               c, _ := x.typ.Underlying().(*Chan)
+               c := asChan(x.typ)
                if c == nil {
                        check.invalidArg(x, _InvalidClose, "%s is not a channel", x)
                        return
@@ -271,7 +292,21 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                }
 
                // the argument types must be of floating-point type
-               if !isFloat(x.typ) {
+               f := func(x Type) Type {
+                       if t := asBasic(x); t != nil {
+                               switch t.kind {
+                               case Float32:
+                                       return Typ[Complex64]
+                               case Float64:
+                                       return Typ[Complex128]
+                               case UntypedFloat:
+                                       return Typ[UntypedComplex]
+                               }
+                       }
+                       return nil
+               }
+               resTyp := check.applyTypeFunc(f, x.typ)
+               if resTyp == nil {
                        check.invalidArg(x, _InvalidComplex, "arguments have type %s, expected floating-point", x.typ)
                        return
                }
@@ -283,20 +318,6 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                        x.mode = value
                }
 
-               // determine result type
-               var res BasicKind
-               switch x.typ.Underlying().(*Basic).kind {
-               case Float32:
-                       res = Complex64
-               case Float64:
-                       res = Complex128
-               case UntypedFloat:
-                       res = UntypedComplex
-               default:
-                       unreachable()
-               }
-               resTyp := Typ[res]
-
                if check.Types != nil && x.mode != constant_ {
                        check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ, x.typ))
                }
@@ -306,7 +327,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
        case _Copy:
                // copy(x, y []T) int
                var dst Type
-               if t, _ := x.typ.Underlying().(*Slice); t != nil {
+               if t := asSlice(x.typ); t != nil {
                        dst = t.elem
                }
 
@@ -316,7 +337,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                        return
                }
                var src Type
-               switch t := y.typ.Underlying().(type) {
+               switch t := optype(y.typ).(type) {
                case *Basic:
                        if isString(y.typ) {
                                src = universeByte
@@ -343,7 +364,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 
        case _Delete:
                // delete(m, k)
-               m, _ := x.typ.Underlying().(*Map)
+               m := asMap(x.typ)
                if m == nil {
                        check.invalidArg(x, _InvalidDelete, "%s is not a map", x)
                        return
@@ -353,8 +374,8 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                        return
                }
 
-               if ok, code := x.assignableTo(check, m.key, nil); !ok {
-                       check.invalidArg(x, code, "%s is not assignable to %s", x, m.key)
+               check.assignment(x, m.key, "argument to delete")
+               if x.mode == invalid {
                        return
                }
 
@@ -389,7 +410,21 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                }
 
                // the argument must be of complex type
-               if !isComplex(x.typ) {
+               f := func(x Type) Type {
+                       if t := asBasic(x); t != nil {
+                               switch t.kind {
+                               case Complex64:
+                                       return Typ[Float32]
+                               case Complex128:
+                                       return Typ[Float64]
+                               case UntypedComplex:
+                                       return Typ[UntypedFloat]
+                               }
+                       }
+                       return nil
+               }
+               resTyp := check.applyTypeFunc(f, x.typ)
+               if resTyp == nil {
                        code := _InvalidImag
                        if id == _Real {
                                code = _InvalidReal
@@ -409,20 +444,6 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                        x.mode = value
                }
 
-               // determine result type
-               var res BasicKind
-               switch x.typ.Underlying().(*Basic).kind {
-               case Complex64:
-                       res = Float32
-               case Complex128:
-                       res = Float64
-               case UntypedComplex:
-                       res = UntypedFloat
-               default:
-                       unreachable()
-               }
-               resTyp := Typ[res]
-
                if check.Types != nil && x.mode != constant_ {
                        check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ))
                }
@@ -434,25 +455,47 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                // make(T, n, m)
                // (no argument evaluated yet)
                arg0 := call.Args[0]
-               T := check.typ(arg0)
+               T := check.varType(arg0)
                if T == Typ[Invalid] {
                        return
                }
 
-               var min int // minimum number of arguments
-               switch T.Underlying().(type) {
-               case *Slice:
-                       min = 2
-               case *Map, *Chan:
-                       min = 1
-               default:
+               min, max := -1, 10
+               var valid func(t Type) bool
+               valid = func(t Type) bool {
+                       var m int
+                       switch t := optype(t).(type) {
+                       case *Slice:
+                               m = 2
+                       case *Map, *Chan:
+                               m = 1
+                       case *_Sum:
+                               return t.is(valid)
+                       default:
+                               return false
+                       }
+                       if m > min {
+                               min = m
+                       }
+                       if m+1 < max {
+                               max = m + 1
+                       }
+                       return true
+               }
+
+               if !valid(T) {
                        check.invalidArg(arg0, _InvalidMake, "cannot make %s; type must be slice, map, or channel", arg0)
                        return
                }
-               if nargs < min || min+1 < nargs {
-                       check.errorf(call, _WrongArgCount, "%v expects %d or %d arguments; found %d", call, min, min+1, nargs)
+               if nargs < min || max < nargs {
+                       if min == max {
+                               check.errorf(call, _WrongArgCount, "%v expects %d arguments; found %d", call, min, nargs)
+                       } else {
+                               check.errorf(call, _WrongArgCount, "%v expects %d or %d arguments; found %d", call, min, max, nargs)
+                       }
                        return
                }
+
                types := []Type{T}
                var sizes []int64 // constant integer arguments, if any
                for _, arg := range call.Args[1:] {
@@ -475,7 +518,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
        case _New:
                // new(T)
                // (no argument evaluated yet)
-               T := check.typ(call.Args[0])
+               T := check.varType(call.Args[0])
                if T == Typ[Invalid] {
                        return
                }
@@ -543,8 +586,36 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                        check.recordBuiltinType(call.Fun, makeSig(x.typ))
                }
 
+       case _Add:
+               // unsafe.Add(ptr unsafe.Pointer, len IntegerType) unsafe.Pointer
+               if !check.allowVersion(check.pkg, 1, 17) {
+                       check.errorf(call.Fun, _InvalidUnsafeAdd, "unsafe.Add requires go1.17 or later")
+                       return
+               }
+
+               check.assignment(x, Typ[UnsafePointer], "argument to unsafe.Add")
+               if x.mode == invalid {
+                       return
+               }
+
+               var y operand
+               arg(&y, 1)
+               if !check.isValidIndex(&y, _InvalidUnsafeAdd, "length", true) {
+                       return
+               }
+
+               x.mode = value
+               x.typ = Typ[UnsafePointer]
+               if check.Types != nil {
+                       check.recordBuiltinType(call.Fun, makeSig(x.typ, x.typ, y.typ))
+               }
+
        case _Alignof:
                // unsafe.Alignof(x T) uintptr
+               if asTypeParam(x.typ) != nil {
+                       check.invalidOp(call, _Todo, "unsafe.Alignof undefined for %s", x)
+                       return
+               }
                check.assignment(x, nil, "argument to unsafe.Alignof")
                if x.mode == invalid {
                        return
@@ -602,6 +673,10 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 
        case _Sizeof:
                // unsafe.Sizeof(x T) uintptr
+               if asTypeParam(x.typ) != nil {
+                       check.invalidOp(call, _Todo, "unsafe.Sizeof undefined for %s", x)
+                       return
+               }
                check.assignment(x, nil, "argument to unsafe.Sizeof")
                if x.mode == invalid {
                        return
@@ -612,6 +687,31 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                x.typ = Typ[Uintptr]
                // result is constant - no need to record signature
 
+       case _Slice:
+               // unsafe.Slice(ptr *T, len IntegerType) []T
+               if !check.allowVersion(check.pkg, 1, 17) {
+                       check.errorf(call.Fun, _InvalidUnsafeSlice, "unsafe.Slice requires go1.17 or later")
+                       return
+               }
+
+               typ := asPointer(x.typ)
+               if typ == nil {
+                       check.invalidArg(x, _InvalidUnsafeSlice, "%s is not a pointer", x)
+                       return
+               }
+
+               var y operand
+               arg(&y, 1)
+               if !check.isValidIndex(&y, _InvalidUnsafeSlice, "length", false) {
+                       return
+               }
+
+               x.mode = value
+               x.typ = NewSlice(typ.base)
+               if check.Types != nil {
+                       check.recordBuiltinType(call.Fun, makeSig(x.typ, typ, y.typ))
+               }
+
        case _Assert:
                // assert(pred) causes a typechecker error if pred is false.
                // The result of assert is the value of pred if there is no error.
@@ -657,6 +757,40 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
        return true
 }
 
+// applyTypeFunc applies f to x. If x is a type parameter,
+// the result is a type parameter constrained by an new
+// interface bound. The type bounds for that interface
+// are computed by applying f to each of the type bounds
+// of x. If any of these applications of f return nil,
+// applyTypeFunc returns nil.
+// If x is not a type parameter, the result is f(x).
+func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type {
+       if tp := asTypeParam(x); tp != nil {
+               // Test if t satisfies the requirements for the argument
+               // type and collect possible result types at the same time.
+               var rtypes []Type
+               if !tp.Bound().is(func(x Type) bool {
+                       if r := f(x); r != nil {
+                               rtypes = append(rtypes, r)
+                               return true
+                       }
+                       return false
+               }) {
+                       return nil
+               }
+
+               // construct a suitable new type parameter
+               tpar := NewTypeName(token.NoPos, nil /* = Universe pkg */, "<type parameter>", nil)
+               ptyp := check.newTypeParam(tpar, 0, &emptyInterface) // assigns type to tpar as a side-effect
+               tsum := _NewSum(rtypes)
+               ptyp.bound = &Interface{types: tsum, allMethods: markComplete, allTypes: tsum}
+
+               return ptyp
+       }
+
+       return f(x)
+}
+
 // makeSig makes a signature for the given argument and result types.
 // Default types are used for untyped arguments, and res may be nil.
 func makeSig(res Type, args ...Type) *Signature {
@@ -678,7 +812,7 @@ func makeSig(res Type, args ...Type) *Signature {
 //
 func implicitArrayDeref(typ Type) Type {
        if p, ok := typ.(*Pointer); ok {
-               if a, ok := p.base.Underlying().(*Array); ok {
+               if a := asArray(p.base); a != nil {
                        return a
                }
        }
index 092e524b87cbf73ec2359e884a031722fca17769..c4830d9eccc1b147578e83be56e870cda187c564 100644 (file)
@@ -87,6 +87,9 @@ var builtinCalls = []struct {
        {"make", `var    c int32; _ = make([]float64   , 0, c)`, `func([]float64, int, int32) []float64`},
        {"make", `var l, c uint ; _ = make([]complex128, l, c)`, `func([]complex128, uint, uint) []complex128`},
 
+       // issue #45667
+       {"make", `const l uint = 1; _ = make([]int, l)`, `func([]int, uint) []int`},
+
        {"new", `_ = new(int)`, `func(int) *int`},
        {"new", `type T struct{}; _ = new(T)`, `func(p.T) *p.T`},
 
@@ -104,6 +107,10 @@ var builtinCalls = []struct {
        {"recover", `recover()`, `func() interface{}`},
        {"recover", `_ = recover()`, `func() interface{}`},
 
+       {"Add", `var p unsafe.Pointer; _ = unsafe.Add(p, -1.0)`, `func(unsafe.Pointer, int) unsafe.Pointer`},
+       {"Add", `var p unsafe.Pointer; var n uintptr; _ = unsafe.Add(p, n)`, `func(unsafe.Pointer, uintptr) unsafe.Pointer`},
+       {"Add", `_ = unsafe.Add(nil, 0)`, `func(unsafe.Pointer, int) unsafe.Pointer`},
+
        {"Alignof", `_ = unsafe.Alignof(0)`, `invalid type`},                 // constant
        {"Alignof", `var x struct{}; _ = unsafe.Alignof(x)`, `invalid type`}, // constant
 
@@ -113,6 +120,9 @@ var builtinCalls = []struct {
        {"Sizeof", `_ = unsafe.Sizeof(0)`, `invalid type`},                 // constant
        {"Sizeof", `var x struct{}; _ = unsafe.Sizeof(x)`, `invalid type`}, // constant
 
+       {"Slice", `var p *int; _ = unsafe.Slice(p, 1)`, `func(*int, int) []int`},
+       {"Slice", `var p *byte; var n uintptr; _ = unsafe.Slice(p, n)`, `func(*byte, uintptr) []byte`},
+
        {"assert", `assert(true)`, `invalid type`},                                    // constant
        {"assert", `type B bool; const pred B = 1 < 2; assert(pred)`, `invalid type`}, // constant
 
index 6765b17bf340535f91f017a64fdf02caebebea84..631ea426c6bbf42e5fe613e4936942a2e253d055 100644 (file)
@@ -8,313 +8,352 @@ package types
 
 import (
        "go/ast"
+       "go/internal/typeparams"
        "go/token"
        "strings"
        "unicode"
 )
 
-func (check *Checker) call(x *operand, e *ast.CallExpr) exprKind {
-       check.exprOrType(x, e.Fun)
+// funcInst type-checks a function instantiation inst and returns the result in x.
+// The operand x must be the evaluation of inst.X and its type must be a signature.
+func (check *Checker) funcInst(x *operand, inst *ast.IndexExpr) {
+       xlist := typeparams.UnpackExpr(inst.Index)
+       targs := check.typeList(xlist)
+       if targs == nil {
+               x.mode = invalid
+               x.expr = inst
+               return
+       }
+       assert(len(targs) == len(xlist))
+
+       // check number of type arguments (got) vs number of type parameters (want)
+       sig := x.typ.(*Signature)
+       got, want := len(targs), len(sig.tparams)
+       if got > want {
+               check.errorf(xlist[got-1], _Todo, "got %d type arguments but want %d", got, want)
+               x.mode = invalid
+               x.expr = inst
+               return
+       }
+
+       // if we don't have enough type arguments, try type inference
+       inferred := false
+
+       if got < want {
+               targs = check.infer(inst, sig.tparams, targs, nil, nil, true)
+               if targs == nil {
+                       // error was already reported
+                       x.mode = invalid
+                       x.expr = inst
+                       return
+               }
+               got = len(targs)
+               inferred = true
+       }
+       assert(got == want)
+
+       // determine argument positions (for error reporting)
+       // TODO(rFindley) use a positioner here? instantiate would need to be
+       //                updated accordingly.
+       poslist := make([]token.Pos, len(xlist))
+       for i, x := range xlist {
+               poslist[i] = x.Pos()
+       }
+
+       // instantiate function signature
+       res := check.instantiate(x.Pos(), sig, targs, poslist).(*Signature)
+       assert(res.tparams == nil) // signature is not generic anymore
+       if inferred {
+               check.recordInferred(inst, targs, res)
+       }
+       x.typ = res
+       x.mode = value
+       x.expr = inst
+}
+
+func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind {
+       var inst *ast.IndexExpr
+       if iexpr, _ := call.Fun.(*ast.IndexExpr); iexpr != nil {
+               if check.indexExpr(x, iexpr) {
+                       // Delay function instantiation to argument checking,
+                       // where we combine type and value arguments for type
+                       // inference.
+                       assert(x.mode == value)
+                       inst = iexpr
+               }
+               x.expr = iexpr
+               check.record(x)
+       } else {
+               check.exprOrType(x, call.Fun)
+       }
 
        switch x.mode {
        case invalid:
-               check.use(e.Args...)
-               x.mode = invalid
-               x.expr = e
+               check.use(call.Args...)
+               x.expr = call
                return statement
 
        case typexpr:
                // conversion
                T := x.typ
                x.mode = invalid
-               switch n := len(e.Args); n {
+               switch n := len(call.Args); n {
                case 0:
-                       check.errorf(inNode(e, e.Rparen), _WrongArgCount, "missing argument in conversion to %s", T)
+                       check.errorf(inNode(call, call.Rparen), _WrongArgCount, "missing argument in conversion to %s", T)
                case 1:
-                       check.expr(x, e.Args[0])
+                       check.expr(x, call.Args[0])
                        if x.mode != invalid {
-                               if e.Ellipsis.IsValid() {
-                                       check.errorf(e.Args[0], _BadDotDotDotSyntax, "invalid use of ... in conversion to %s", T)
+                               if call.Ellipsis.IsValid() {
+                                       check.errorf(call.Args[0], _BadDotDotDotSyntax, "invalid use of ... in conversion to %s", T)
                                        break
                                }
+                               if t := asInterface(T); t != nil {
+                                       check.completeInterface(token.NoPos, t)
+                                       if t._IsConstraint() {
+                                               check.errorf(call, _Todo, "cannot use interface %s in conversion (contains type list or is comparable)", T)
+                                               break
+                                       }
+                               }
                                check.conversion(x, T)
                        }
                default:
-                       check.use(e.Args...)
-                       check.errorf(e.Args[n-1], _WrongArgCount, "too many arguments in conversion to %s", T)
+                       check.use(call.Args...)
+                       check.errorf(call.Args[n-1], _WrongArgCount, "too many arguments in conversion to %s", T)
                }
-               x.expr = e
+               x.expr = call
                return conversion
 
        case builtin:
                id := x.id
-               if !check.builtin(x, e, id) {
+               if !check.builtin(x, call, id) {
                        x.mode = invalid
                }
-               x.expr = e
+               x.expr = call
                // a non-constant result implies a function call
                if x.mode != invalid && x.mode != constant_ {
                        check.hasCallOrRecv = true
                }
                return predeclaredFuncs[id].kind
+       }
 
-       default:
-               // function/method call
-               cgocall := x.mode == cgofunc
+       // ordinary function/method call
+       cgocall := x.mode == cgofunc
 
-               sig, _ := x.typ.Underlying().(*Signature)
-               if sig == nil {
-                       check.invalidOp(x, _InvalidCall, "cannot call non-function %s", x)
+       sig := asSignature(x.typ)
+       if sig == nil {
+               check.invalidOp(x, _InvalidCall, "cannot call non-function %s", x)
+               x.mode = invalid
+               x.expr = call
+               return statement
+       }
+
+       // evaluate type arguments, if any
+       var targs []Type
+       if inst != nil {
+               xlist := typeparams.UnpackExpr(inst.Index)
+               targs = check.typeList(xlist)
+               if targs == nil {
+                       check.use(call.Args...)
                        x.mode = invalid
-                       x.expr = e
+                       x.expr = call
                        return statement
                }
+               assert(len(targs) == len(xlist))
 
-               arg, n, _ := unpack(func(x *operand, i int) { check.multiExpr(x, e.Args[i]) }, len(e.Args), false)
-               if arg != nil {
-                       check.arguments(x, e, sig, arg, n)
-               } else {
+               // check number of type arguments (got) vs number of type parameters (want)
+               got, want := len(targs), len(sig.tparams)
+               if got > want {
+                       check.errorf(xlist[want], _Todo, "got %d type arguments but want %d", got, want)
+                       check.use(call.Args...)
                        x.mode = invalid
+                       x.expr = call
+                       return statement
                }
+       }
 
-               // determine result
-               switch sig.results.Len() {
-               case 0:
-                       x.mode = novalue
-               case 1:
-                       if cgocall {
-                               x.mode = commaerr
-                       } else {
-                               x.mode = value
-                       }
-                       x.typ = sig.results.vars[0].typ // unpack tuple
-               default:
+       // evaluate arguments
+       args, _ := check.exprList(call.Args, false)
+       sig = check.arguments(call, sig, targs, args)
+
+       // determine result
+       switch sig.results.Len() {
+       case 0:
+               x.mode = novalue
+       case 1:
+               if cgocall {
+                       x.mode = commaerr
+               } else {
                        x.mode = value
-                       x.typ = sig.results
                }
-
-               x.expr = e
-               check.hasCallOrRecv = true
-
-               return statement
+               x.typ = sig.results.vars[0].typ // unpack tuple
+       default:
+               x.mode = value
+               x.typ = sig.results
        }
-}
+       x.expr = call
+       check.hasCallOrRecv = true
 
-// use type-checks each argument.
-// Useful to make sure expressions are evaluated
-// (and variables are "used") in the presence of other errors.
-// The arguments may be nil.
-func (check *Checker) use(arg ...ast.Expr) {
-       var x operand
-       for _, e := range arg {
-               // The nil check below is necessary since certain AST fields
-               // may legally be nil (e.g., the ast.SliceExpr.High field).
-               if e != nil {
-                       check.rawExpr(&x, e, nil)
-               }
+       // if type inference failed, a parametrized result must be invalidated
+       // (operands cannot have a parametrized type)
+       if x.mode == value && len(sig.tparams) > 0 && isParameterized(sig.tparams, x.typ) {
+               x.mode = invalid
        }
+
+       return statement
 }
 
-// useLHS is like use, but doesn't "use" top-level identifiers.
-// It should be called instead of use if the arguments are
-// expressions on the lhs of an assignment.
-// The arguments must not be nil.
-func (check *Checker) useLHS(arg ...ast.Expr) {
-       var x operand
-       for _, e := range arg {
-               // If the lhs is an identifier denoting a variable v, this assignment
-               // is not a 'use' of v. Remember current value of v.used and restore
-               // after evaluating the lhs via check.rawExpr.
-               var v *Var
-               var v_used bool
-               if ident, _ := unparen(e).(*ast.Ident); ident != nil {
-                       // never type-check the blank name on the lhs
-                       if ident.Name == "_" {
-                               continue
+func (check *Checker) exprList(elist []ast.Expr, allowCommaOk bool) (xlist []*operand, commaOk bool) {
+       switch len(elist) {
+       case 0:
+               // nothing to do
+
+       case 1:
+               // single (possibly comma-ok) value, or function returning multiple values
+               e := elist[0]
+               var x operand
+               check.multiExpr(&x, e)
+               if t, ok := x.typ.(*Tuple); ok && x.mode != invalid {
+                       // multiple values
+                       xlist = make([]*operand, t.Len())
+                       for i, v := range t.vars {
+                               xlist[i] = &operand{mode: value, expr: e, typ: v.typ}
                        }
-                       if _, obj := check.scope.LookupParent(ident.Name, token.NoPos); obj != nil {
-                               // It's ok to mark non-local variables, but ignore variables
-                               // from other packages to avoid potential race conditions with
-                               // dot-imported variables.
-                               if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {
-                                       v = w
-                                       v_used = v.used
-                               }
-                       }
-               }
-               check.rawExpr(&x, e, nil)
-               if v != nil {
-                       v.used = v_used // restore v.used
+                       break
                }
-       }
-}
-
-// useGetter is like use, but takes a getter instead of a list of expressions.
-// It should be called instead of use if a getter is present to avoid repeated
-// evaluation of the first argument (since the getter was likely obtained via
-// unpack, which may have evaluated the first argument already).
-func (check *Checker) useGetter(get getter, n int) {
-       var x operand
-       for i := 0; i < n; i++ {
-               get(&x, i)
-       }
-}
 
-// A getter sets x as the i'th operand, where 0 <= i < n and n is the total
-// number of operands (context-specific, and maintained elsewhere). A getter
-// type-checks the i'th operand; the details of the actual check are getter-
-// specific.
-type getter func(x *operand, i int)
-
-// unpack takes a getter get and a number of operands n. If n == 1, unpack
-// calls the incoming getter for the first operand. If that operand is
-// invalid, unpack returns (nil, 0, false). Otherwise, if that operand is a
-// function call, or a comma-ok expression and allowCommaOk is set, the result
-// is a new getter and operand count providing access to the function results,
-// or comma-ok values, respectively. The third result value reports if it
-// is indeed the comma-ok case. In all other cases, the incoming getter and
-// operand count are returned unchanged, and the third result value is false.
-//
-// In other words, if there's exactly one operand that - after type-checking
-// by calling get - stands for multiple operands, the resulting getter provides
-// access to those operands instead.
-//
-// If the returned getter is called at most once for a given operand index i
-// (including i == 0), that operand is guaranteed to cause only one call of
-// the incoming getter with that i.
-//
-func unpack(get getter, n int, allowCommaOk bool) (getter, int, bool) {
-       if n != 1 {
-               // zero or multiple values
-               return get, n, false
-       }
-       // possibly result of an n-valued function call or comma,ok value
-       var x0 operand
-       get(&x0, 0)
-       if x0.mode == invalid {
-               return nil, 0, false
-       }
-
-       if t, ok := x0.typ.(*Tuple); ok {
-               // result of an n-valued function call
-               return func(x *operand, i int) {
+               // exactly one (possibly invalid or comma-ok) value
+               xlist = []*operand{&x}
+               if allowCommaOk && (x.mode == mapindex || x.mode == commaok || x.mode == commaerr) {
                        x.mode = value
-                       x.expr = x0.expr
-                       x.typ = t.At(i).typ
-               }, t.Len(), false
-       }
-
-       if x0.mode == mapindex || x0.mode == commaok || x0.mode == commaerr {
-               // comma-ok value
-               if allowCommaOk {
-                       a := [2]Type{x0.typ, Typ[UntypedBool]}
-                       if x0.mode == commaerr {
-                               a[1] = universeError
+                       x2 := &operand{mode: value, expr: e, typ: Typ[UntypedBool]}
+                       if x.mode == commaerr {
+                               x2.typ = universeError
                        }
-                       return func(x *operand, i int) {
-                               x.mode = value
-                               x.expr = x0.expr
-                               x.typ = a[i]
-                       }, 2, true
+                       xlist = append(xlist, x2)
+                       commaOk = true
                }
-               x0.mode = value
-       }
 
-       // single value
-       return func(x *operand, i int) {
-               if i != 0 {
-                       unreachable()
+       default:
+               // multiple (possibly invalid) values
+               xlist = make([]*operand, len(elist))
+               for i, e := range elist {
+                       var x operand
+                       check.expr(&x, e)
+                       xlist[i] = &x
                }
-               *x = x0
-       }, 1, false
+       }
+
+       return
 }
 
-// arguments checks argument passing for the call with the given signature.
-// The arg function provides the operand for the i'th argument.
-func (check *Checker) arguments(x *operand, call *ast.CallExpr, sig *Signature, arg getter, n int) {
-       if call.Ellipsis.IsValid() {
-               // last argument is of the form x...
-               if !sig.variadic {
-                       check.errorf(atPos(call.Ellipsis), _NonVariadicDotDotDot, "cannot use ... in call to non-variadic %s", call.Fun)
-                       check.useGetter(arg, n)
+func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type, args []*operand) (rsig *Signature) {
+       rsig = sig
+
+       // TODO(gri) try to eliminate this extra verification loop
+       for _, a := range args {
+               switch a.mode {
+               case typexpr:
+                       check.errorf(a, 0, "%s used as value", a)
                        return
-               }
-               if len(call.Args) == 1 && n > 1 {
-                       // f()... is not permitted if f() is multi-valued
-                       check.errorf(atPos(call.Ellipsis), _InvalidDotDotDotOperand, "cannot use ... with %d-valued %s", n, call.Args[0])
-                       check.useGetter(arg, n)
+               case invalid:
                        return
                }
        }
 
-       // evaluate arguments
-       context := check.sprintf("argument to %s", call.Fun)
-       for i := 0; i < n; i++ {
-               arg(x, i)
-               if x.mode != invalid {
-                       var ellipsis token.Pos
-                       if i == n-1 && call.Ellipsis.IsValid() {
-                               ellipsis = call.Ellipsis
+       // Function call argument/parameter count requirements
+       //
+       //               | standard call    | dotdotdot call |
+       // --------------+------------------+----------------+
+       // standard func | nargs == npars   | invalid        |
+       // --------------+------------------+----------------+
+       // variadic func | nargs >= npars-1 | nargs == npars |
+       // --------------+------------------+----------------+
+
+       nargs := len(args)
+       npars := sig.params.Len()
+       ddd := call.Ellipsis.IsValid()
+
+       // set up parameters
+       sigParams := sig.params // adjusted for variadic functions (may be nil for empty parameter lists!)
+       adjusted := false       // indicates if sigParams is different from t.params
+       if sig.variadic {
+               if ddd {
+                       // variadic_func(a, b, c...)
+                       if len(call.Args) == 1 && nargs > 1 {
+                               // f()... is not permitted if f() is multi-valued
+                               check.errorf(inNode(call, call.Ellipsis), _InvalidDotDotDot, "cannot use ... with %d-valued %s", nargs, call.Args[0])
+                               return
+                       }
+               } else {
+                       // variadic_func(a, b, c)
+                       if nargs >= npars-1 {
+                               // Create custom parameters for arguments: keep
+                               // the first npars-1 parameters and add one for
+                               // each argument mapping to the ... parameter.
+                               vars := make([]*Var, npars-1) // npars > 0 for variadic functions
+                               copy(vars, sig.params.vars)
+                               last := sig.params.vars[npars-1]
+                               typ := last.typ.(*Slice).elem
+                               for len(vars) < nargs {
+                                       vars = append(vars, NewParam(last.pos, last.pkg, last.name, typ))
+                               }
+                               sigParams = NewTuple(vars...) // possibly nil!
+                               adjusted = true
+                               npars = nargs
+                       } else {
+                               // nargs < npars-1
+                               npars-- // for correct error message below
                        }
-                       check.argument(sig, i, x, ellipsis, context)
                }
+       } else {
+               if ddd {
+                       // standard_func(a, b, c...)
+                       check.errorf(inNode(call, call.Ellipsis), _NonVariadicDotDotDot, "cannot use ... in call to non-variadic %s", call.Fun)
+                       return
+               }
+               // standard_func(a, b, c)
        }
 
        // check argument count
-       if sig.variadic {
-               // a variadic function accepts an "empty"
-               // last argument: count one extra
-               n++
-       }
-       if n < sig.params.Len() {
-               check.errorf(inNode(call, call.Rparen), _WrongArgCount, "too few arguments in call to %s", call.Fun)
-               // ok to continue
-       }
-}
-
-// argument checks passing of argument x to the i'th parameter of the given signature.
-// If ellipsis is valid, the argument is followed by ... at that position in the call.
-func (check *Checker) argument(sig *Signature, i int, x *operand, ellipsis token.Pos, context string) {
-       check.singleValue(x)
-       if x.mode == invalid {
+       switch {
+       case nargs < npars:
+               check.errorf(inNode(call, call.Rparen), _WrongArgCount, "not enough arguments in call to %s", call.Fun)
+               return
+       case nargs > npars:
+               check.errorf(args[npars], _WrongArgCount, "too many arguments in call to %s", call.Fun) // report at first extra argument
                return
        }
 
-       n := sig.params.Len()
+       // infer type arguments and instantiate signature if necessary
+       if len(sig.tparams) > 0 {
+               // TODO(gri) provide position information for targs so we can feed
+               //           it to the instantiate call for better error reporting
+               targs := check.infer(call, sig.tparams, targs, sigParams, args, true)
+               if targs == nil {
+                       return // error already reported
+               }
+
+               // compute result signature
+               rsig = check.instantiate(call.Pos(), sig, targs, nil).(*Signature)
+               assert(rsig.tparams == nil) // signature is not generic anymore
+               check.recordInferred(call, targs, rsig)
 
-       // determine parameter type
-       var typ Type
-       switch {
-       case i < n:
-               typ = sig.params.vars[i].typ
-       case sig.variadic:
-               typ = sig.params.vars[n-1].typ
-               if debug {
-                       if _, ok := typ.(*Slice); !ok {
-                               check.dump("%v: expected unnamed slice type, got %s", sig.params.vars[n-1].Pos(), typ)
-                       }
+               // Optimization: Only if the parameter list was adjusted do we
+               // need to compute it from the adjusted list; otherwise we can
+               // simply use the result signature's parameter list.
+               if adjusted {
+                       sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(sig.tparams, targs)).(*Tuple)
+               } else {
+                       sigParams = rsig.params
                }
-       default:
-               check.errorf(x, _WrongArgCount, "too many arguments")
-               return
        }
 
-       if ellipsis.IsValid() {
-               if i != n-1 {
-                       check.errorf(atPos(ellipsis), _MisplacedDotDotDot, "can only use ... with matching parameter")
-                       return
-               }
-               // argument is of the form x... and x is single-valued
-               if _, ok := x.typ.Underlying().(*Slice); !ok && x.typ != Typ[UntypedNil] { // see issue #18268
-                       check.errorf(x, _InvalidDotDotDotOperand, "cannot use %s as parameter of type %s", x, typ)
-                       return
-               }
-       } else if sig.variadic && i >= n-1 {
-               // use the variadic parameter slice's element type
-               typ = typ.(*Slice).elem
+       // check arguments
+       for i, a := range args {
+               check.assignment(a, sigParams.vars[i].typ, check.sprintf("argument to %s", call.Fun))
        }
 
-       check.assignment(x, typ, context)
+       return
 }
 
 var cgoPrefixes = [...]string{
@@ -417,7 +456,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
                                x.typ = exp.typ
                                x.id = exp.id
                        default:
-                               check.dump("unexpected object %v", exp)
+                               check.dump("%v: unexpected object %v", e.Sel.Pos(), exp)
                                unreachable()
                        }
                        x.expr = e
@@ -430,6 +469,8 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
                goto Error
        }
 
+       check.instantiatedOperand(x)
+
        obj, index, indirect = check.lookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
        if obj == nil {
                switch {
@@ -439,8 +480,20 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
                case indirect:
                        check.errorf(e.Sel, _InvalidMethodExpr, "cannot call pointer method %s on %s", sel, x.typ)
                default:
-                       // Check if capitalization of sel matters and provide better error
-                       // message in that case.
+                       var why string
+                       if tpar := asTypeParam(x.typ); tpar != nil {
+                               // Type parameter bounds don't specify fields, so don't mention "field".
+                               switch obj := tpar.Bound().obj.(type) {
+                               case nil:
+                                       why = check.sprintf("type bound for %s has no method %s", x.typ, sel)
+                               case *TypeName:
+                                       why = check.sprintf("interface %s has no method %s", obj.name, sel)
+                               }
+                       } else {
+                               why = check.sprintf("type %s has no field or method %s", x.typ, sel)
+                       }
+
+                       // Check if capitalization of sel matters and provide better error message in that case.
                        if len(sel) > 0 {
                                var changeCase string
                                if r := rune(sel[0]); unicode.IsUpper(r) {
@@ -449,11 +502,11 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
                                        changeCase = string(unicode.ToUpper(r)) + sel[1:]
                                }
                                if obj, _, _ = check.lookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, changeCase); obj != nil {
-                                       check.errorf(e.Sel, _MissingFieldOrMethod, "%s.%s undefined (type %s has no field or method %s, but does have %s)", x.expr, sel, x.typ, sel, changeCase)
-                                       break
+                                       why += ", but does have " + changeCase
                                }
                        }
-                       check.errorf(e.Sel, _MissingFieldOrMethod, "%s.%s undefined (type %s has no field or method %s)", x.expr, sel, x.typ, sel)
+
+                       check.errorf(e.Sel, _MissingFieldOrMethod, "%s.%s undefined (%s)", x.expr, sel, why)
                }
                goto Error
        }
@@ -461,6 +514,54 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
        // methods may not have a fully set up signature yet
        if m, _ := obj.(*Func); m != nil {
                check.objDecl(m, nil)
+               // If m has a parameterized receiver type, infer the type arguments from
+               // the actual receiver provided and then substitute the type parameters in
+               // the signature accordingly.
+               // TODO(gri) factor this code out
+               sig := m.typ.(*Signature)
+               if len(sig.rparams) > 0 {
+                       // For inference to work, we must use the receiver type
+                       // matching the receiver in the actual method declaration.
+                       // If the method is embedded, the matching receiver is the
+                       // embedded struct or interface that declared the method.
+                       // Traverse the embedding to find that type (issue #44688).
+                       recv := x.typ
+                       for i := 0; i < len(index)-1; i++ {
+                               // The embedded type is either a struct or a pointer to
+                               // a struct except for the last one (which we don't need).
+                               recv = asStruct(derefStructPtr(recv)).Field(index[i]).typ
+                       }
+
+                       // The method may have a pointer receiver, but the actually provided receiver
+                       // may be a (hopefully addressable) non-pointer value, or vice versa. Here we
+                       // only care about inferring receiver type parameters; to make the inference
+                       // work, match up pointer-ness of receiver and argument.
+                       if ptrRecv := isPointer(sig.recv.typ); ptrRecv != isPointer(recv) {
+                               if ptrRecv {
+                                       recv = NewPointer(recv)
+                               } else {
+                                       recv = recv.(*Pointer).base
+                               }
+                       }
+                       // Disable reporting of errors during inference below. If we're unable to infer
+                       // the receiver type arguments here, the receiver must be be otherwise invalid
+                       // and an error has been reported elsewhere.
+                       arg := operand{mode: variable, expr: x.expr, typ: recv}
+                       targs := check.infer(m, sig.rparams, nil, NewTuple(sig.recv), []*operand{&arg}, false /* no error reporting */)
+                       if targs == nil {
+                               // We may reach here if there were other errors (see issue #40056).
+                               goto Error
+                       }
+                       // Don't modify m. Instead - for now - make a copy of m and use that instead.
+                       // (If we modify m, some tests will fail; possibly because the m is in use.)
+                       // TODO(gri) investigate and provide a correct explanation here
+                       copy := *m
+                       copy.typ = check.subst(e.Pos(), m.typ, makeSubstMap(sig.rparams, targs))
+                       obj = &copy
+               }
+               // TODO(gri) we also need to do substitution for parameterized interface methods
+               //           (this breaks code in testdata/linalg.go2 at the moment)
+               //           12/20/2019: Is this TODO still correct?
        }
 
        if x.mode == typexpr {
@@ -483,7 +584,8 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
                }
                x.mode = value
                x.typ = &Signature{
-                       params:   NewTuple(append([]*Var{NewVar(token.NoPos, check.pkg, "", x.typ)}, params...)...),
+                       tparams:  sig.tparams,
+                       params:   NewTuple(append([]*Var{NewVar(token.NoPos, check.pkg, "_", x.typ)}, params...)...),
                        results:  sig.results,
                        variadic: sig.variadic,
                }
@@ -507,7 +609,14 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
                        // addressability, should we report the type &(x.typ) instead?
                        check.recordSelection(e, MethodVal, x.typ, obj, index, indirect)
 
-                       if debug {
+                       // TODO(gri) The verification pass below is disabled for now because
+                       //           method sets don't match method lookup in some cases.
+                       //           For instance, if we made a copy above when creating a
+                       //           custom method for a parameterized received type, the
+                       //           method set method doesn't match (no copy there). There
+                       ///          may be other situations.
+                       disabled := true
+                       if !disabled && debug {
                                // Verify that LookupFieldOrMethod and MethodSet.Lookup agree.
                                // TODO(gri) This only works because we call LookupFieldOrMethod
                                // _before_ calling NewMethodSet: LookupFieldOrMethod completes
@@ -567,3 +676,60 @@ Error:
        x.mode = invalid
        x.expr = e
 }
+
+// use type-checks each argument.
+// Useful to make sure expressions are evaluated
+// (and variables are "used") in the presence of other errors.
+// The arguments may be nil.
+func (check *Checker) use(arg ...ast.Expr) {
+       var x operand
+       for _, e := range arg {
+               // The nil check below is necessary since certain AST fields
+               // may legally be nil (e.g., the ast.SliceExpr.High field).
+               if e != nil {
+                       check.rawExpr(&x, e, nil)
+               }
+       }
+}
+
+// useLHS is like use, but doesn't "use" top-level identifiers.
+// It should be called instead of use if the arguments are
+// expressions on the lhs of an assignment.
+// The arguments must not be nil.
+func (check *Checker) useLHS(arg ...ast.Expr) {
+       var x operand
+       for _, e := range arg {
+               // If the lhs is an identifier denoting a variable v, this assignment
+               // is not a 'use' of v. Remember current value of v.used and restore
+               // after evaluating the lhs via check.rawExpr.
+               var v *Var
+               var v_used bool
+               if ident, _ := unparen(e).(*ast.Ident); ident != nil {
+                       // never type-check the blank name on the lhs
+                       if ident.Name == "_" {
+                               continue
+                       }
+                       if _, obj := check.scope.LookupParent(ident.Name, token.NoPos); obj != nil {
+                               // It's ok to mark non-local variables, but ignore variables
+                               // from other packages to avoid potential race conditions with
+                               // dot-imported variables.
+                               if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {
+                                       v = w
+                                       v_used = v.used
+                               }
+                       }
+               }
+               check.rawExpr(&x, e, nil)
+               if v != nil {
+                       v.used = v_used // restore v.used
+               }
+       }
+}
+
+// instantiatedOperand reports an error of x is an uninstantiated (generic) type and sets x.typ to Typ[Invalid].
+func (check *Checker) instantiatedOperand(x *operand) {
+       if x.mode == typexpr && isGeneric(x.typ) {
+               check.errorf(x, _Todo, "cannot use generic type %s without instantiation", x.typ)
+               x.typ = Typ[Invalid]
+       }
+}
index 280792e838ef24bb62849c1b93904dc436770aba..a923c3c612124f21f6baa59cec4967ee5084a271 100644 (file)
@@ -8,6 +8,7 @@ package types
 
 import (
        "errors"
+       "fmt"
        "go/ast"
        "go/constant"
        "go/token"
@@ -19,18 +20,18 @@ const (
        trace = false // turn on for detailed type resolution traces
 )
 
-// If Strict is set, the type-checker enforces additional
+// If forceStrict is set, the type-checker enforces additional
 // rules not specified by the Go 1 spec, but which will
 // catch guaranteed run-time errors if the respective
 // code is executed. In other words, programs passing in
-// Strict mode are Go 1 compliant, but not all Go 1 programs
-// will pass in Strict mode. The additional rules are:
+// strict mode are Go 1 compliant, but not all Go 1 programs
+// will pass in strict mode. The additional rules are:
 //
 // - A type assertion x.(T) where T is an interface type
 //   is invalid if any (statically known) method that exists
 //   for both x and T have different signatures.
 //
-const strict = false
+const forceStrict = false
 
 // exprInfo stores information about an untyped expression.
 type exprInfo struct {
@@ -69,6 +70,12 @@ type importKey struct {
        path, dir string
 }
 
+// A dotImportKey describes a dot-imported object in the given scope.
+type dotImportKey struct {
+       scope *Scope
+       obj   Object
+}
+
 // A Checker maintains the state of the type checker.
 // It must be created with NewChecker.
 type Checker struct {
@@ -78,22 +85,33 @@ type Checker struct {
        fset *token.FileSet
        pkg  *Package
        *Info
-       objMap map[Object]*declInfo       // maps package-level objects and (non-interface) methods to declaration info
-       impMap map[importKey]*Package     // maps (import path, source directory) to (complete or fake) package
-       posMap map[*Interface][]token.Pos // maps interface types to lists of embedded interface positions
-       pkgCnt map[string]int             // counts number of imported packages with a given name (for better error messages)
+       version version                    // accepted language version
+       objMap  map[Object]*declInfo       // maps package-level objects and (non-interface) methods to declaration info
+       impMap  map[importKey]*Package     // maps (import path, source directory) to (complete or fake) package
+       posMap  map[*Interface][]token.Pos // maps interface types to lists of embedded interface positions
+       typMap  map[string]*Named          // maps an instantiated named type hash to a *Named type
+
+       // pkgPathMap maps package names to the set of distinct import paths we've
+       // seen for that name, anywhere in the import graph. It is used for
+       // disambiguating package names in error messages.
+       //
+       // pkgPathMap is allocated lazily, so that we don't pay the price of building
+       // it on the happy path. seenPkgMap tracks the packages that we've already
+       // walked.
+       pkgPathMap map[string]map[string]bool
+       seenPkgMap map[*Package]bool
 
        // information collected during type-checking of a set of package files
        // (initialized by Files, valid only for the duration of check.Files;
        // maps and lists are allocated on demand)
-       files            []*ast.File                             // package files
-       unusedDotImports map[*Scope]map[*Package]*ast.ImportSpec // unused dot-imported packages
+       files        []*ast.File               // package files
+       imports      []*PkgName                // list of imported packages
+       dotImportMap map[dotImportKey]*PkgName // maps dot-imported objects to the package they were dot-imported through
 
        firstErr error                 // first error encountered
        methods  map[*TypeName][]*Func // maps package scope type names to associated non-blank (non-interface) methods
        untyped  map[ast.Expr]exprInfo // map of expressions without final type
        delayed  []func()              // stack of delayed action segments; segments are processed in FIFO order
-       finals   []func()              // list of final actions; processed at the end of type-checking the current set of files
        objPath  []Object              // path of object dependencies during type inference (for cycle reporting)
 
        // context within which the current object is type-checked
@@ -104,22 +122,6 @@ type Checker struct {
        indent int // indentation for tracing
 }
 
-// addUnusedImport adds the position of a dot-imported package
-// pkg to the map of dot imports for the given file scope.
-func (check *Checker) addUnusedDotImport(scope *Scope, pkg *Package, spec *ast.ImportSpec) {
-       mm := check.unusedDotImports
-       if mm == nil {
-               mm = make(map[*Scope]map[*Package]*ast.ImportSpec)
-               check.unusedDotImports = mm
-       }
-       m := mm[scope]
-       if m == nil {
-               m = make(map[*Package]*ast.ImportSpec)
-               mm[scope] = m
-       }
-       m[pkg] = spec
-}
-
 // addDeclDep adds the dependency edge (check.decl -> to) if check.decl exists
 func (check *Checker) addDeclDep(to Object) {
        from := check.decl
@@ -149,14 +151,6 @@ func (check *Checker) later(f func()) {
        check.delayed = append(check.delayed, f)
 }
 
-// atEnd adds f to the list of actions processed at the end
-// of type-checking, before initialization order computation.
-// Actions added by atEnd are processed after any actions
-// added by later.
-func (check *Checker) atEnd(f func()) {
-       check.finals = append(check.finals, f)
-}
-
 // push pushes obj onto the object path and returns its index in the path.
 func (check *Checker) push(obj Object) int {
        check.objPath = append(check.objPath, obj)
@@ -185,15 +179,21 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch
                info = new(Info)
        }
 
+       version, err := parseGoVersion(conf.goVersion)
+       if err != nil {
+               panic(fmt.Sprintf("invalid Go version %q (%v)", conf.goVersion, err))
+       }
+
        return &Checker{
-               conf:   conf,
-               fset:   fset,
-               pkg:    pkg,
-               Info:   info,
-               objMap: make(map[Object]*declInfo),
-               impMap: make(map[importKey]*Package),
-               posMap: make(map[*Interface][]token.Pos),
-               pkgCnt: make(map[string]int),
+               conf:    conf,
+               fset:    fset,
+               pkg:     pkg,
+               Info:    info,
+               version: version,
+               objMap:  make(map[Object]*declInfo),
+               impMap:  make(map[importKey]*Package),
+               posMap:  make(map[*Interface][]token.Pos),
+               typMap:  make(map[string]*Named),
        }
 }
 
@@ -202,13 +202,13 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch
 func (check *Checker) initFiles(files []*ast.File) {
        // start with a clean slate (check.Files may be called multiple times)
        check.files = nil
-       check.unusedDotImports = nil
+       check.imports = nil
+       check.dotImportMap = nil
 
        check.firstErr = nil
        check.methods = nil
        check.untyped = nil
        check.delayed = nil
-       check.finals = nil
 
        // determine package name and collect valid files
        pkg := check.pkg
@@ -265,7 +265,6 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) {
        check.packageObjects()
 
        check.processDelayed(0) // incl. all functions
-       check.processFinals()
 
        check.initOrder()
 
@@ -275,7 +274,20 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) {
 
        check.recordUntyped()
 
+       if check.Info != nil {
+               sanitizeInfo(check.Info)
+       }
+
        check.pkg.complete = true
+
+       // no longer needed - release memory
+       check.imports = nil
+       check.dotImportMap = nil
+       check.pkgPathMap = nil
+       check.seenPkgMap = nil
+
+       // TODO(rFindley) There's more memory we should release at this point.
+
        return
 }
 
@@ -294,13 +306,30 @@ func (check *Checker) processDelayed(top int) {
        check.delayed = check.delayed[:top]
 }
 
-func (check *Checker) processFinals() {
-       n := len(check.finals)
-       for _, f := range check.finals {
-               f() // must not append to check.finals
+func (check *Checker) record(x *operand) {
+       // convert x into a user-friendly set of values
+       // TODO(gri) this code can be simplified
+       var typ Type
+       var val constant.Value
+       switch x.mode {
+       case invalid:
+               typ = Typ[Invalid]
+       case novalue:
+               typ = (*Tuple)(nil)
+       case constant_:
+               typ = x.typ
+               val = x.val
+       default:
+               typ = x.typ
        }
-       if len(check.finals) != n {
-               panic("internal error: final action list grew")
+       assert(x.expr != nil && typ != nil)
+
+       if isUntyped(typ) {
+               // delay type and value recording until we know the type
+               // or until the end of type checking
+               check.rememberUntyped(x.expr, false, x.mode, typ.(*Basic), val)
+       } else {
+               check.recordTypeAndValue(x.expr, x.mode, typ, val)
        }
 }
 
@@ -326,7 +355,9 @@ func (check *Checker) recordTypeAndValue(x ast.Expr, mode operandMode, typ Type,
        }
        if mode == constant_ {
                assert(val != nil)
-               assert(typ == Typ[Invalid] || isConstType(typ))
+               // We check is(typ, IsConstType) here as constant expressions may be
+               // recorded as type parameters.
+               assert(typ == Typ[Invalid] || is(typ, IsConstType))
        }
        if m := check.Types; m != nil {
                m[x] = TypeAndValue{mode, typ, val}
@@ -334,14 +365,14 @@ func (check *Checker) recordTypeAndValue(x ast.Expr, mode operandMode, typ Type,
 }
 
 func (check *Checker) recordBuiltinType(f ast.Expr, sig *Signature) {
-       // f must be a (possibly parenthesized) identifier denoting a built-in
-       // (built-ins in package unsafe always produce a constant result and
-       // we don't record their signatures, so we don't see qualified idents
-       // here): record the signature for f and possible children.
+       // f must be a (possibly parenthesized, possibly qualified)
+       // identifier denoting a built-in (including unsafe's non-constant
+       // functions Add and Slice): record the signature for f and possible
+       // children.
        for {
                check.recordTypeAndValue(f, builtin, sig, nil)
                switch p := f.(type) {
-               case *ast.Ident:
+               case *ast.Ident, *ast.SelectorExpr:
                        return // we're done
                case *ast.ParenExpr:
                        f = p.X
@@ -377,6 +408,14 @@ func (check *Checker) recordCommaOkTypes(x ast.Expr, a [2]Type) {
        }
 }
 
+func (check *Checker) recordInferred(call ast.Expr, targs []Type, sig *Signature) {
+       assert(call != nil)
+       assert(sig != nil)
+       if m := getInferred(check.Info); m != nil {
+               m[call] = _Inferred{targs, sig}
+       }
+}
+
 func (check *Checker) recordDef(id *ast.Ident, obj Object) {
        assert(id != nil)
        if m := check.Defs; m != nil {
index ce31dab68bb18067c453d555e26f99654761696f..f83abf11ce2e22623cb1ff266ec0b2c4a2f6557f 100644 (file)
@@ -27,8 +27,10 @@ package types_test
 
 import (
        "flag"
+       "fmt"
        "go/ast"
        "go/importer"
+       "go/internal/typeparams"
        "go/parser"
        "go/scanner"
        "go/token"
@@ -43,59 +45,11 @@ import (
 )
 
 var (
-       haltOnError = flag.Bool("halt", false, "halt on error")
-       listErrors  = flag.Bool("errlist", false, "list errors")
-       testFiles   = flag.String("files", "", "space-separated list of test files")
+       haltOnError  = flag.Bool("halt", false, "halt on error")
+       verifyErrors = flag.Bool("verify", false, "verify errors (rather than list them) in TestManual")
+       goVersion    = flag.String("lang", "", "Go language version (e.g. \"go1.12\") for TestManual")
 )
 
-// The test filenames do not end in .go so that they are invisible
-// to gofmt since they contain comments that must not change their
-// positions relative to surrounding tokens.
-
-// Each tests entry is list of files belonging to the same package.
-var tests = [][]string{
-       {"testdata/errors.src"},
-       {"testdata/importdecl0a.src", "testdata/importdecl0b.src"},
-       {"testdata/importdecl1a.src", "testdata/importdecl1b.src"},
-       {"testdata/importC.src"}, // special handling in checkFiles
-       {"testdata/cycles.src"},
-       {"testdata/cycles1.src"},
-       {"testdata/cycles2.src"},
-       {"testdata/cycles3.src"},
-       {"testdata/cycles4.src"},
-       {"testdata/cycles5.src"},
-       {"testdata/init0.src"},
-       {"testdata/init1.src"},
-       {"testdata/init2.src"},
-       {"testdata/decls0.src"},
-       {"testdata/decls1.src"},
-       {"testdata/decls2a.src", "testdata/decls2b.src"},
-       {"testdata/decls3.src"},
-       {"testdata/decls4.src"},
-       {"testdata/decls5.src"},
-       {"testdata/const0.src"},
-       {"testdata/const1.src"},
-       {"testdata/constdecl.src"},
-       {"testdata/vardecl.src"},
-       {"testdata/expr0.src"},
-       {"testdata/expr1.src"},
-       {"testdata/expr2.src"},
-       {"testdata/expr3.src"},
-       {"testdata/methodsets.src"},
-       {"testdata/shifts.src"},
-       {"testdata/builtins.src"},
-       {"testdata/conversions.src"},
-       {"testdata/conversions2.src"},
-       {"testdata/stmt0.src"},
-       {"testdata/stmt1.src"},
-       {"testdata/gotos.src"},
-       {"testdata/labels.src"},
-       {"testdata/literals.src"},
-       {"testdata/issues.src"},
-       {"testdata/blank.src"},
-       {"testdata/issue25008b.src", "testdata/issue25008a.src"}, // order (b before a) is crucial!
-}
-
 var fset = token.NewFileSet()
 
 // Positioned errors are of the form filename:line:column: message .
@@ -114,11 +68,11 @@ func splitError(err error) (pos, msg string) {
        return
 }
 
-func parseFiles(t *testing.T, filenames []string) ([]*ast.File, []error) {
+func parseFiles(t *testing.T, filenames []string, srcs [][]byte, mode parser.Mode) ([]*ast.File, []error) {
        var files []*ast.File
        var errlist []error
-       for _, filename := range filenames {
-               file, err := parser.ParseFile(fset, filename, nil, parser.AllErrors)
+       for i, filename := range filenames {
+               file, err := parser.ParseFile(fset, filename, srcs[i], mode)
                if file == nil {
                        t.Fatalf("%s: %s", filename, err)
                }
@@ -147,19 +101,17 @@ var errRx = regexp.MustCompile(`^ *ERROR *(HERE)? *"?([^"]*)"?`)
 // errMap collects the regular expressions of ERROR comments found
 // in files and returns them as a map of error positions to error messages.
 //
-func errMap(t *testing.T, testname string, files []*ast.File) map[string][]string {
+// srcs must be a slice of the same length as files, containing the original
+// source for the parsed AST.
+func errMap(t *testing.T, files []*ast.File, srcs [][]byte) map[string][]string {
        // map of position strings to lists of error message patterns
        errmap := make(map[string][]string)
 
-       for _, file := range files {
-               filename := fset.Position(file.Package).Filename
-               src, err := os.ReadFile(filename)
-               if err != nil {
-                       t.Fatalf("%s: could not read %s", testname, filename)
-               }
-
+       for i, file := range files {
+               tok := fset.File(file.Package)
+               src := srcs[i]
                var s scanner.Scanner
-               s.Init(fset.AddFile(filename, -1, len(src)), src, nil, scanner.ScanComments)
+               s.Init(tok, src, nil, scanner.ScanComments)
                var prev token.Pos // position of last non-comment, non-semicolon token
                var here token.Pos // position immediately after the token at position prev
 
@@ -236,16 +188,52 @@ func eliminate(t *testing.T, errmap map[string][]string, errlist []error) {
        }
 }
 
-func checkFiles(t *testing.T, testfiles []string) {
+// goVersionRx matches a Go version string using '_', e.g. "go1_12".
+var goVersionRx = regexp.MustCompile(`^go[1-9][0-9]*_(0|[1-9][0-9]*)$`)
+
+// asGoVersion returns a regular Go language version string
+// if s is a Go version string using '_' rather than '.' to
+// separate the major and minor version numbers (e.g. "go1_12").
+// Otherwise it returns the empty string.
+func asGoVersion(s string) string {
+       if goVersionRx.MatchString(s) {
+               return strings.Replace(s, "_", ".", 1)
+       }
+       return ""
+}
+
+func checkFiles(t *testing.T, sizes Sizes, goVersion string, filenames []string, srcs [][]byte, manual bool, imp Importer) {
+       if len(filenames) == 0 {
+               t.Fatal("no source files")
+       }
+
+       if strings.HasSuffix(filenames[0], ".go2") && !typeparams.Enabled {
+               t.Skip("type params are not enabled")
+       }
+       if strings.HasSuffix(filenames[0], ".go1") && typeparams.Enabled {
+               t.Skip("type params are enabled")
+       }
+
+       mode := parser.AllErrors
+       if !strings.HasSuffix(filenames[0], ".go2") {
+               mode |= typeparams.DisallowParsing
+       }
+
        // parse files and collect parser errors
-       files, errlist := parseFiles(t, testfiles)
+       files, errlist := parseFiles(t, filenames, srcs, mode)
 
        pkgName := "<no package>"
        if len(files) > 0 {
                pkgName = files[0].Name.Name
        }
 
-       if *listErrors && len(errlist) > 0 {
+       // if no Go version is given, consider the package name
+       if goVersion == "" {
+               goVersion = asGoVersion(pkgName)
+       }
+
+       listErrors := manual && !*verifyErrors
+       if listErrors && len(errlist) > 0 {
                t.Errorf("--- %s:", pkgName)
                for _, err := range errlist {
                        t.Error(err)
@@ -254,16 +242,25 @@ func checkFiles(t *testing.T, testfiles []string) {
 
        // typecheck and collect typechecker errors
        var conf Config
+       conf.Sizes = sizes
+       SetGoVersion(&conf, goVersion)
+
        // special case for importC.src
-       if len(testfiles) == 1 && strings.HasSuffix(testfiles[0], "importC.src") {
-               conf.FakeImportC = true
+       if len(filenames) == 1 {
+               if strings.HasSuffix(filenames[0], "importC.src") {
+                       conf.FakeImportC = true
+               }
+       }
+
+       conf.Importer = imp
+       if imp == nil {
+               conf.Importer = importer.Default()
        }
-       conf.Importer = importer.Default()
        conf.Error = func(err error) {
                if *haltOnError {
                        defer panic(err)
                }
-               if *listErrors {
+               if listErrors {
                        t.Error(err)
                        return
                }
@@ -275,7 +272,7 @@ func checkFiles(t *testing.T, testfiles []string) {
        }
        conf.Check(pkgName, fset, files, nil)
 
-       if *listErrors {
+       if listErrors {
                return
        }
 
@@ -292,7 +289,7 @@ func checkFiles(t *testing.T, testfiles []string) {
 
        // match and eliminate errors;
        // we are expecting the following errors
-       errmap := errMap(t, pkgName, files)
+       errmap := errMap(t, files, srcs)
        eliminate(t, errmap, errlist)
 
        // there should be no expected errors left
@@ -306,44 +303,100 @@ func checkFiles(t *testing.T, testfiles []string) {
        }
 }
 
-func TestCheck(t *testing.T) {
+// TestManual is for manual testing of input files, provided as a list
+// of arguments after the test arguments (and a separating "--"). For
+// instance, to check the files foo.go and bar.go, use:
+//
+//     go test -run Manual -- foo.go bar.go
+//
+// Provide the -verify flag to verify errors against ERROR comments in
+// the input files rather than having a list of errors reported.
+// The accepted Go language version can be controlled with the -lang flag.
+func TestManual(t *testing.T) {
+       filenames := flag.Args()
+       if len(filenames) == 0 {
+               return
+       }
        testenv.MustHaveGoBuild(t)
-
-       // Declare builtins for testing.
        DefPredeclaredTestFuncs()
+       testPkg(t, filenames, *goVersion, true)
+}
 
-       // If explicit test files are specified, only check those.
-       if files := *testFiles; files != "" {
-               checkFiles(t, strings.Split(files, " "))
-               return
-       }
+func TestLongConstants(t *testing.T) {
+       format := "package longconst\n\nconst _ = %s\nconst _ = %s // ERROR excessively long constant"
+       src := fmt.Sprintf(format, strings.Repeat("1", 9999), strings.Repeat("1", 10001))
+       checkFiles(t, nil, "", []string{"longconst.go"}, [][]byte{[]byte(src)}, false, nil)
+}
+
+// TestIndexRepresentability tests that constant index operands must
+// be representable as int even if they already have a type that can
+// represent larger values.
+func TestIndexRepresentability(t *testing.T) {
+       const src = "package index\n\nvar s []byte\nvar _ = s[int64 /* ERROR \"int64\\(1\\) << 40 \\(.*\\) overflows int\" */ (1) << 40]"
+       checkFiles(t, &StdSizes{4, 4}, "", []string{"index.go"}, [][]byte{[]byte(src)}, false, nil)
+}
 
-       // Otherwise, run all the tests.
-       for _, files := range tests {
-               checkFiles(t, files)
+func TestIssue46453(t *testing.T) {
+       if typeparams.Enabled {
+               t.Skip("type params are enabled")
        }
+       const src = "package p\ntype _ comparable // ERROR \"undeclared name: comparable\""
+       checkFiles(t, nil, "", []string{"issue46453.go"}, [][]byte{[]byte(src)}, false, nil)
 }
 
-func TestFixedBugs(t *testing.T) { testDir(t, "fixedbugs") }
+func TestIssue47243_TypedRHS(t *testing.T) {
+       // The RHS of the shift expression below overflows uint on 32bit platforms,
+       // but this is OK as it is explicitly typed.
+       const src = "package issue47243\n\nvar a uint64; var _ = a << uint64(4294967296)" // uint64(1<<32)
+       checkFiles(t, &StdSizes{4, 4}, "", []string{"p.go"}, [][]byte{[]byte(src)}, false, nil)
+}
+
+func TestCheck(t *testing.T)     { DefPredeclaredTestFuncs(); testDir(t, "check") }
+func TestExamples(t *testing.T)  { testDir(t, "examples") }
+func TestFixedbugs(t *testing.T) { testDir(t, "fixedbugs") }
 
 func testDir(t *testing.T, dir string) {
        testenv.MustHaveGoBuild(t)
 
-       dirs, err := os.ReadDir(dir)
+       dir = filepath.Join("testdata", dir)
+       fis, err := os.ReadDir(dir)
        if err != nil {
-               t.Fatal(err)
+               t.Error(err)
+               return
        }
 
-       for _, d := range dirs {
-               testname := filepath.Base(d.Name())
-               testname = strings.TrimSuffix(testname, filepath.Ext(testname))
-               t.Run(testname, func(t *testing.T) {
-                       filename := filepath.Join(dir, d.Name())
-                       if d.IsDir() {
-                               t.Errorf("skipped directory %q", filename)
-                               return
+       for _, fi := range fis {
+               path := filepath.Join(dir, fi.Name())
+
+               // if fi is a directory, its files make up a single package
+               var filenames []string
+               if fi.IsDir() {
+                       fis, err := os.ReadDir(path)
+                       if err != nil {
+                               t.Error(err)
+                               continue
                        }
-                       checkFiles(t, []string{filename})
+                       for _, fi := range fis {
+                               filenames = append(filenames, filepath.Join(path, fi.Name()))
+                       }
+               } else {
+                       filenames = []string{path}
+               }
+               t.Run(filepath.Base(path), func(t *testing.T) {
+                       testPkg(t, filenames, "", false)
                })
        }
 }
+
+// TODO(rFindley) reconcile the different test setup in go/types with types2.
+func testPkg(t *testing.T, filenames []string, goVersion string, manual bool) {
+       srcs := make([][]byte, len(filenames))
+       for i, filename := range filenames {
+               src, err := os.ReadFile(filename)
+               if err != nil {
+                       t.Fatalf("could not read %s: %v", filename, err)
+               }
+               srcs[i] = src
+       }
+       checkFiles(t, nil, goVersion, filenames, srcs, manual, nil)
+}
index 1cab1cc70f0e8bfc4206422136b1f5cb65b9f66a..ad6d3eef1027a839d0c0dea3e87172cde7ef8c02 100644 (file)
@@ -17,10 +17,11 @@ func (check *Checker) conversion(x *operand, T Type) {
        constArg := x.mode == constant_
 
        var ok bool
+       var reason string
        switch {
        case constArg && isConstType(T):
                // constant conversion
-               switch t := T.Underlying().(*Basic); {
+               switch t := asBasic(T); {
                case representableConst(x.val, check, t, &x.val):
                        ok = true
                case isInteger(x.typ) && isString(t):
@@ -31,14 +32,18 @@ func (check *Checker) conversion(x *operand, T Type) {
                        x.val = constant.MakeString(string(codepoint))
                        ok = true
                }
-       case x.convertibleTo(check, T):
+       case x.convertibleTo(check, T, &reason):
                // non-constant conversion
                x.mode = value
                ok = true
        }
 
        if !ok {
-               check.errorf(x, _InvalidConversion, "cannot convert %s to %s", x, T)
+               if reason != "" {
+                       check.errorf(x, _InvalidConversion, "cannot convert %s to %s (%s)", x, T, reason)
+               } else {
+                       check.errorf(x, _InvalidConversion, "cannot convert %s to %s", x, T)
+               }
                x.mode = invalid
                return
        }
@@ -55,8 +60,8 @@ func (check *Checker) conversion(x *operand, T Type) {
                // - Keep untyped nil for untyped nil arguments.
                // - For integer to string conversions, keep the argument type.
                //   (See also the TODO below.)
-               if IsInterface(T) || constArg && !isConstType(T) {
-                       final = Default(x.typ)
+               if IsInterface(T) || constArg && !isConstType(T) || x.isNil() {
+                       final = Default(x.typ) // default type of untyped nil is untyped nil
                } else if isInteger(x.typ) && isString(T) {
                        final = x.typ
                }
@@ -79,7 +84,7 @@ func (check *Checker) conversion(x *operand, T Type) {
 // convertibleTo reports whether T(x) is valid.
 // The check parameter may be nil if convertibleTo is invoked through an
 // exported API call, i.e., when all methods have been type-checked.
-func (x *operand) convertibleTo(check *Checker, T Type) bool {
+func (x *operand) convertibleTo(check *Checker, T Type, reason *string) bool {
        // "x is assignable to T"
        if ok, _ := x.assignableTo(check, T, nil); ok {
                return true
@@ -87,8 +92,8 @@ func (x *operand) convertibleTo(check *Checker, T Type) bool {
 
        // "x's type and T have identical underlying types if tags are ignored"
        V := x.typ
-       Vu := V.Underlying()
-       Tu := T.Underlying()
+       Vu := under(V)
+       Tu := under(T)
        if check.identicalIgnoreTags(Vu, Tu) {
                return true
        }
@@ -97,14 +102,14 @@ func (x *operand) convertibleTo(check *Checker, T Type) bool {
        // have identical underlying types if tags are ignored"
        if V, ok := V.(*Pointer); ok {
                if T, ok := T.(*Pointer); ok {
-                       if check.identicalIgnoreTags(V.base.Underlying(), T.base.Underlying()) {
+                       if check.identicalIgnoreTags(under(V.base), under(T.base)) {
                                return true
                        }
                }
        }
 
        // "x's type and T are both integer or floating point types"
-       if (isInteger(V) || isFloat(V)) && (isInteger(T) || isFloat(T)) {
+       if isIntegerOrFloat(V) && isIntegerOrFloat(T) {
                return true
        }
 
@@ -133,31 +138,48 @@ func (x *operand) convertibleTo(check *Checker, T Type) bool {
                return true
        }
 
+       // "x is a slice, T is a pointer-to-array type,
+       // and the slice and array types have identical element types."
+       if s := asSlice(V); s != nil {
+               if p := asPointer(T); p != nil {
+                       if a := asArray(p.Elem()); a != nil {
+                               if check.identical(s.Elem(), a.Elem()) {
+                                       if check == nil || check.allowVersion(check.pkg, 1, 17) {
+                                               return true
+                                       }
+                                       if reason != nil {
+                                               *reason = "conversion of slices to array pointers requires go1.17 or later"
+                                       }
+                               }
+                       }
+               }
+       }
+
        return false
 }
 
 func isUintptr(typ Type) bool {
-       t, ok := typ.Underlying().(*Basic)
-       return ok && t.kind == Uintptr
+       t := asBasic(typ)
+       return t != nil && t.kind == Uintptr
 }
 
 func isUnsafePointer(typ Type) bool {
-       // TODO(gri): Is this (typ.Underlying() instead of just typ) correct?
+       // TODO(gri): Is this asBasic(typ) instead of typ.(*Basic) correct?
+       //            (The former calls under(), while the latter doesn't.)
        //            The spec does not say so, but gc claims it is. See also
        //            issue 6326.
-       t, ok := typ.Underlying().(*Basic)
-       return ok && t.kind == UnsafePointer
+       t := asBasic(typ)
+       return t != nil && t.kind == UnsafePointer
 }
 
 func isPointer(typ Type) bool {
-       _, ok := typ.Underlying().(*Pointer)
-       return ok
+       return asPointer(typ) != nil
 }
 
 func isBytesOrRunes(typ Type) bool {
-       if s, ok := typ.(*Slice); ok {
-               t, ok := s.elem.Underlying().(*Basic)
-               return ok && (t.kind == Byte || t.kind == Rune)
+       if s := asSlice(typ); s != nil {
+               t := asBasic(s.elem)
+               return t != nil && (t.kind == Byte || t.kind == Rune)
        }
        return false
 }
index 1f0bc358a26e9ace5e0c3dcf396eaaf6079e2646..9211febc6da1620a43e9867af2f37c149a6f0753 100644 (file)
@@ -5,8 +5,10 @@
 package types
 
 import (
+       "fmt"
        "go/ast"
        "go/constant"
+       "go/internal/typeparams"
        "go/token"
 )
 
@@ -52,7 +54,10 @@ func pathString(path []Object) string {
 // objDecl type-checks the declaration of obj in its respective (file) context.
 // For the meaning of def, see Checker.definedType, in typexpr.go.
 func (check *Checker) objDecl(obj Object, def *Named) {
-       if trace {
+       if trace && obj.Type() == nil {
+               if check.indent == 0 {
+                       fmt.Println() // empty line between top-level objects for readability
+               }
                check.trace(obj.Pos(), "-- checking %s (%s, objPath = %s)", obj, obj.color(), pathString(check.objPath))
                check.indent++
                defer func() {
@@ -183,13 +188,14 @@ func (check *Checker) objDecl(obj Object, def *Named) {
        switch obj := obj.(type) {
        case *Const:
                check.decl = d // new package-level const decl
-               check.constDecl(obj, d.typ, d.init, d.inherited)
+               check.constDecl(obj, d.vtyp, d.init, d.inherited)
        case *Var:
                check.decl = d // new package-level var decl
-               check.varDecl(obj, d.lhs, d.typ, d.init)
+               check.varDecl(obj, d.lhs, d.vtyp, d.init)
        case *TypeName:
                // invalid recursive types are detected via path
-               check.typeDecl(obj, d.typ, def, d.alias)
+               check.typeDecl(obj, d.tdecl, def)
+               check.collectMethods(obj) // methods can only be added to top-level types
        case *Func:
                // functions may be recursive - no need to track dependencies
                check.funcDecl(obj, d)
@@ -234,7 +240,7 @@ func (check *Checker) cycle(obj Object) (isCycle bool) {
                        // this information explicitly in the object.
                        var alias bool
                        if d := check.objMap[obj]; d != nil {
-                               alias = d.alias // package-level object
+                               alias = d.tdecl.Assign.IsValid() // package-level object
                        } else {
                                alias = obj.IsAlias() // function local object
                        }
@@ -318,7 +324,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo {
                }
 
                // don't report a 2nd error if we already know the type is invalid
-               // (e.g., if a cycle was detected earlier, via Checker.underlying).
+               // (e.g., if a cycle was detected earlier, via under).
                if t.underlying == Typ[Invalid] {
                        t.info = invalid
                        return invalid
@@ -337,13 +343,15 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo {
                                if tn == t.obj {
                                        check.cycleError(path[i:])
                                        t.info = invalid
-                                       t.underlying = Typ[Invalid]
                                        return t.info
                                }
                        }
                        panic("internal error: cycle start not found")
                }
                return t.info
+
+       case *instance:
+               return check.validType(t.expand(), path)
        }
 
        return valid
@@ -475,7 +483,7 @@ func (check *Checker) constDecl(obj *Const, typ, init ast.Expr, inherited bool)
                if !isConstType(t) {
                        // don't report an error if the type is an invalid C (defined) type
                        // (issue #22090)
-                       if t.Underlying() != Typ[Invalid] {
+                       if under(t) != Typ[Invalid] {
                                check.errorf(typ, _InvalidConstType, "invalid constant type %s", t)
                        }
                        obj.typ = Typ[Invalid]
@@ -506,7 +514,7 @@ func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init ast.Expr) {
 
        // determine type, if any
        if typ != nil {
-               obj.typ = check.typ(typ)
+               obj.typ = check.varType(typ)
                // We cannot spread the type to all lhs variables if there
                // are more than one since that would mark them as checked
                // (see Checker.objDecl) and the assignment of init exprs,
@@ -561,36 +569,66 @@ func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init ast.Expr) {
        check.initVars(lhs, []ast.Expr{init}, token.NoPos)
 }
 
-// underlying returns the underlying type of typ; possibly by following
-// forward chains of named types. Such chains only exist while named types
-// are incomplete. If an underlying type is found, resolve the chain by
-// setting the underlying type for each defined type in the chain before
-// returning it.
-//
-// If no underlying type is found, a cycle error is reported and Typ[Invalid]
-// is used as underlying type for each defined type in the chain and returned
-// as result.
-func (check *Checker) underlying(typ Type) Type {
-       // If typ is not a defined type, its underlying type is itself.
-       n0, _ := typ.(*Named)
-       if n0 == nil {
-               return typ // nothing to do
+// under returns the expanded underlying type of n0; possibly by following
+// forward chains of named types. If an underlying type is found, resolve
+// the chain by setting the underlying type for each defined type in the
+// chain before returning it. If no underlying type is found or a cycle
+// is detected, the result is Typ[Invalid]. If a cycle is detected and
+// n0.check != nil, the cycle is reported.
+func (n0 *Named) under() Type {
+       u := n0.underlying
+
+       if u == Typ[Invalid] {
+               return u
        }
 
        // If the underlying type of a defined type is not a defined
-       // type, then that is the desired underlying type.
-       typ = n0.underlying
-       n, _ := typ.(*Named)
+       // (incl. instance) type, then that is the desired underlying
+       // type.
+       switch u.(type) {
+       case nil:
+               return Typ[Invalid]
+       default:
+               // common case
+               return u
+       case *Named, *instance:
+               // handled below
+       }
+
+       if n0.check == nil {
+               panic("internal error: Named.check == nil but type is incomplete")
+       }
+
+       // Invariant: after this point n0 as well as any named types in its
+       // underlying chain should be set up when this function exits.
+       check := n0.check
+
+       // If we can't expand u at this point, it is invalid.
+       n := asNamed(u)
        if n == nil {
-               return typ // common case
+               n0.underlying = Typ[Invalid]
+               return n0.underlying
        }
 
        // Otherwise, follow the forward chain.
        seen := map[*Named]int{n0: 0}
        path := []Object{n0.obj}
        for {
-               typ = n.underlying
-               n1, _ := typ.(*Named)
+               u = n.underlying
+               if u == nil {
+                       u = Typ[Invalid]
+                       break
+               }
+               var n1 *Named
+               switch u1 := u.(type) {
+               case *Named:
+                       n1 = u1
+               case *instance:
+                       n1, _ = u1.expand().(*Named)
+                       if n1 == nil {
+                               u = Typ[Invalid]
+                       }
+               }
                if n1 == nil {
                        break // end of chain
                }
@@ -602,7 +640,7 @@ func (check *Checker) underlying(typ Type) Type {
                if i, ok := seen[n]; ok {
                        // cycle
                        check.cycleError(path[i:])
-                       typ = Typ[Invalid]
+                       u = Typ[Invalid]
                        break
                }
        }
@@ -611,13 +649,14 @@ func (check *Checker) underlying(typ Type) Type {
                // We should never have to update the underlying type of an imported type;
                // those underlying types should have been resolved during the import.
                // Also, doing so would lead to a race condition (was issue #31749).
+               // Do this check always, not just in debug mode (it's cheap).
                if n.obj.pkg != check.pkg {
                        panic("internal error: imported type with unresolved underlying type")
                }
-               n.underlying = typ
+               n.underlying = u
        }
 
-       return typ
+       return u
 }
 
 func (n *Named) setUnderlying(typ Type) {
@@ -626,26 +665,45 @@ func (n *Named) setUnderlying(typ Type) {
        }
 }
 
-func (check *Checker) typeDecl(obj *TypeName, typ ast.Expr, def *Named, alias bool) {
+func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) {
        assert(obj.typ == nil)
 
        check.later(func() {
                check.validType(obj.typ, nil)
        })
 
+       alias := tdecl.Assign.IsValid()
+       if alias && typeparams.Get(tdecl) != nil {
+               // The parser will ensure this but we may still get an invalid AST.
+               // Complain and continue as regular type definition.
+               check.error(atPos(tdecl.Assign), 0, "generic type cannot be alias")
+               alias = false
+       }
+
        if alias {
+               // type alias declaration
+               if !check.allowVersion(check.pkg, 1, 9) {
+                       check.errorf(atPos(tdecl.Assign), _BadDecl, "type aliases requires go1.9 or later")
+               }
 
                obj.typ = Typ[Invalid]
-               obj.typ = check.typ(typ)
+               obj.typ = check.anyType(tdecl.Type)
 
        } else {
+               // defined type declaration
 
-               named := &Named{obj: obj}
+               named := check.newNamed(obj, nil, nil)
                def.setUnderlying(named)
                obj.typ = named // make sure recursive type declarations terminate
 
+               if tparams := typeparams.Get(tdecl); tparams != nil {
+                       check.openScope(tdecl, "type parameters")
+                       defer check.closeScope()
+                       named.tparams = check.collectTypeParams(tparams)
+               }
+
                // determine underlying type of named
-               named.orig = check.definedType(typ, named)
+               named.orig = check.definedType(tdecl.Type, named)
 
                // The underlying type of named may be itself a named type that is
                // incomplete:
@@ -660,14 +718,85 @@ func (check *Checker) typeDecl(obj *TypeName, typ ast.Expr, def *Named, alias bo
                // and which has as its underlying type the named type B.
                // Determine the (final, unnamed) underlying type by resolving
                // any forward chain.
-               named.underlying = check.underlying(named)
+               // TODO(gri) Investigate if we can just use named.origin here
+               //           and rely on lazy computation of the underlying type.
+               named.underlying = under(named)
+       }
+
+}
 
+func (check *Checker) collectTypeParams(list *ast.FieldList) (tparams []*TypeName) {
+       // Type parameter lists should not be empty. The parser will
+       // complain but we still may get an incorrect AST: ignore it.
+       if list.NumFields() == 0 {
+               return
+       }
+
+       // Declare type parameters up-front, with empty interface as type bound.
+       // The scope of type parameters starts at the beginning of the type parameter
+       // list (so we can have mutually recursive parameterized interfaces).
+       for _, f := range list.List {
+               tparams = check.declareTypeParams(tparams, f.Names)
+       }
+
+       setBoundAt := func(at int, bound Type) {
+               assert(IsInterface(bound))
+               tparams[at].typ.(*_TypeParam).bound = bound
+       }
+
+       index := 0
+       var bound Type
+       for _, f := range list.List {
+               if f.Type == nil {
+                       goto next
+               }
+
+               // The predeclared identifier "any" is visible only as a constraint
+               // in a type parameter list. Look for it before general constraint
+               // resolution.
+               if tident, _ := unparen(f.Type).(*ast.Ident); tident != nil && tident.Name == "any" && check.lookup("any") == nil {
+                       bound = universeAny
+               } else {
+                       bound = check.typ(f.Type)
+               }
+
+               // type bound must be an interface
+               // TODO(gri) We should delay the interface check because
+               //           we may not have a complete interface yet:
+               //           type C(type T C) interface {}
+               //           (issue #39724).
+               if _, ok := under(bound).(*Interface); ok {
+                       // Otherwise, set the bound for each type parameter.
+                       for i := range f.Names {
+                               setBoundAt(index+i, bound)
+                       }
+               } else if bound != Typ[Invalid] {
+                       check.errorf(f.Type, _Todo, "%s is not an interface", bound)
+               }
+
+       next:
+               index += len(f.Names)
        }
 
-       check.addMethodDecls(obj)
+       return
 }
 
-func (check *Checker) addMethodDecls(obj *TypeName) {
+func (check *Checker) declareTypeParams(tparams []*TypeName, names []*ast.Ident) []*TypeName {
+       for _, name := range names {
+               tpar := NewTypeName(name.Pos(), check.pkg, name.Name, nil)
+               check.newTypeParam(tpar, len(tparams), &emptyInterface) // assigns type to tpar as a side-effect
+               check.declare(check.scope, name, tpar, check.scope.pos) // TODO(gri) check scope position
+               tparams = append(tparams, tpar)
+       }
+
+       if trace && len(names) > 0 {
+               check.trace(names[0].Pos(), "type params = %v", tparams[len(tparams)-len(names):])
+       }
+
+       return tparams
+}
+
+func (check *Checker) collectMethods(obj *TypeName) {
        // get associated methods
        // (Checker.collectObjects only collects methods with non-blank names;
        // Checker.resolveBaseTypeName ensures that obj is not an alias name
@@ -677,14 +806,14 @@ func (check *Checker) addMethodDecls(obj *TypeName) {
                return
        }
        delete(check.methods, obj)
-       assert(!check.objMap[obj].alias) // don't use TypeName.IsAlias (requires fully set up object)
+       assert(!check.objMap[obj].tdecl.Assign.IsValid()) // don't use TypeName.IsAlias (requires fully set up object)
 
        // use an objset to check for name conflicts
        var mset objset
 
        // spec: "If the base type is a struct type, the non-blank method
        // and field names must be distinct."
-       base, _ := obj.typ.(*Named) // shouldn't fail but be conservative
+       base := asNamed(obj.typ) // shouldn't fail but be conservative
        if base != nil {
                if t, _ := base.underlying.(*Struct); t != nil {
                        for _, fld := range t.fields {
@@ -735,12 +864,18 @@ func (check *Checker) funcDecl(obj *Func, decl *declInfo) {
 
        sig := new(Signature)
        obj.typ = sig // guard against cycles
+
+       // Avoid cycle error when referring to method while type-checking the signature.
+       // This avoids a nuisance in the best case (non-parameterized receiver type) and
+       // since the method is not a type, we get an error. If we have a parameterized
+       // receiver type, instantiating the receiver type leads to the instantiation of
+       // its methods, and we don't want a cycle error in that case.
+       // TODO(gri) review if this is correct and/or whether we still need this?
+       saved := obj.color_
+       obj.color_ = black
        fdecl := decl.fdecl
        check.funcType(sig, fdecl.Recv, fdecl.Type)
-       if sig.recv == nil && obj.name == "init" && (sig.params.Len() > 0 || sig.results.Len() > 0) {
-               check.errorf(fdecl, _InvalidInitSig, "func init must have no arguments and no return values")
-               // ok to continue
-       }
+       obj.color_ = saved
 
        // function body must be type-checked after global declarations
        // (functions implemented elsewhere have no body)
@@ -846,7 +981,7 @@ func (check *Checker) declStmt(d ast.Decl) {
                        check.declare(check.scope, d.spec.Name, obj, scopePos)
                        // mark and unmark type before calling typeDecl; its type is still nil (see Checker.objDecl)
                        obj.setColor(grey + color(check.push(obj)))
-                       check.typeDecl(obj, d.spec.Type, nil, d.spec.Assign.IsValid())
+                       check.typeDecl(obj, d.spec, nil)
                        check.pop().setColor(black)
                default:
                        check.invalidAST(d.node(), "unknown ast.Decl node %T", d.node())
index c01a12c346d3e50c301e589e3fd2a762664a6593..3d24da7b533cf89d5851a204dd8c373b2567d3dc 100644 (file)
@@ -10,6 +10,8 @@ type errorCode int
 // Collectively, these codes provide an identifier that may be used to
 // implement special handling for certain types of errors.
 //
+// Error code values should not be changed: add new codes at the end.
+//
 // Error codes should be fine-grained enough that the exact nature of the error
 // can be easily determined, but coarse enough that they are not an
 // implementation detail of the type checking algorithm. As a rule-of-thumb,
@@ -34,8 +36,6 @@ const (
        // _Test is reserved for errors that only apply while in self-test mode.
        _Test
 
-       /* package names */
-
        // _BlankPkgName occurs when a package name is the blank identifier "_".
        //
        // Per the spec:
@@ -55,8 +55,6 @@ const (
        //  var _ = fmt
        _InvalidPkgUse
 
-       /* imports */
-
        // _BadImportPath occurs when an import path is not valid.
        _BadImportPath
 
@@ -81,8 +79,6 @@ const (
        //  func main() {}
        _UnusedImport
 
-       /* initialization */
-
        // _InvalidInitCycle occurs when an invalid cycle is detected within the
        // initialization graph.
        //
@@ -92,8 +88,6 @@ const (
        //  func f() int { return x }
        _InvalidInitCycle
 
-       /* decls */
-
        // _DuplicateDecl occurs when an identifier is declared multiple times.
        //
        // Example:
@@ -122,8 +116,6 @@ const (
        //  type T [unsafe.Sizeof(T{})]int
        _InvalidTypeCycle
 
-       /* decls > const */
-
        // _InvalidConstInit occurs when a const declaration has a non-constant
        // initializer.
        //
@@ -149,8 +141,6 @@ const (
        //  const c *int = 4
        _InvalidConstType
 
-       /* decls > var (+ other variable assignment codes) */
-
        // _UntypedNil occurs when the predeclared (untyped) value nil is used to
        // initialize a variable declared without an explicit type.
        //
@@ -159,7 +149,7 @@ const (
        _UntypedNil
 
        // _WrongAssignCount occurs when the number of values on the right-hand side
-       // of an assignment or or initialization expression does not match the number
+       // of an assignment or initialization expression does not match the number
        // of variables on the left-hand side.
        //
        // Example:
@@ -249,8 +239,6 @@ const (
        //  }
        _UnaddressableFieldAssign
 
-       /* decls > type (+ other type expression codes) */
-
        // _NotAType occurs when the identifier used as the underlying type in a type
        // declaration or the right-hand side of a type alias does not denote a type.
        //
@@ -320,8 +308,6 @@ const (
        //  }
        _InvalidPtrEmbed
 
-       /* decls > func and method */
-
        // _BadRecv occurs when a method declaration does not have exactly one
        // receiver parameter.
        //
@@ -358,8 +344,6 @@ const (
        //  func (T) m(i int) int { return i }
        _DuplicateMethod
 
-       /* decls > special */
-
        // _InvalidBlank occurs when a blank identifier is used as a value or type.
        //
        // Per the spec:
@@ -386,8 +370,8 @@ const (
        // _InvalidInitSig occurs when an init function declares parameters or
        // results.
        //
-       // Example:
-       //  func init() int { return 1 }
+       // Deprecated: no longer emitted by the type checker. _InvalidInitDecl is
+       // used instead.
        _InvalidInitSig
 
        // _InvalidInitDecl occurs when init is declared as anything other than a
@@ -395,14 +379,15 @@ const (
        //
        // Example:
        //  var init = 1
+       //
+       // Example:
+       //  func init() int { return 1 }
        _InvalidInitDecl
 
        // _InvalidMainDecl occurs when main is declared as anything other than a
        // function, in a main package.
        _InvalidMainDecl
 
-       /* exprs */
-
        // _TooManyValues occurs when a function returns too many values for the
        // expression context in which it is used.
        //
@@ -425,8 +410,6 @@ const (
        //  }
        _NotAnExpr
 
-       /* exprs > const */
-
        // _TruncatedFloat occurs when a float constant is truncated to an integer
        // value.
        //
@@ -440,8 +423,6 @@ const (
        //  var x int8 = 1000
        _NumericOverflow
 
-       /* exprs > operation */
-
        // _UndefinedOp occurs when an operator is not defined for the type(s) used
        // in an operation.
        //
@@ -476,8 +457,6 @@ const (
        //  }
        _NonNumericIncDec
 
-       /* exprs > ptr */
-
        // _UnaddressableOperand occurs when the & operator is applied to an
        // unaddressable expression.
        //
@@ -493,8 +472,6 @@ const (
        //  var y = *x
        _InvalidIndirection
 
-       /* exprs > [] */
-
        // _NonIndexableOperand occurs when an index operation is applied to a value
        // that cannot be indexed.
        //
@@ -527,8 +504,6 @@ const (
        //  var _ = []int{1,2,3}[2:1]
        _SwappedSliceIndices
 
-       /* operators > slice */
-
        // _NonSliceableOperand occurs when a slice operation is applied to a value
        // whose type is not sliceable, or is unaddressable.
        //
@@ -548,8 +523,6 @@ const (
        //  var x = s[1:2:3]
        _InvalidSliceExpr
 
-       /* exprs > shift */
-
        // _InvalidShiftCount occurs when the right-hand side of a shift operation is
        // either non-integer, negative, or too large.
        //
@@ -567,8 +540,6 @@ const (
        //  var x = s << 2
        _InvalidShiftOperand
 
-       /* exprs > chan */
-
        // _InvalidReceive occurs when there is a channel receive from a value that
        // is either not a channel, or is a send-only channel.
        //
@@ -589,8 +560,6 @@ const (
        //  }
        _InvalidSend
 
-       /* exprs > literal */
-
        // _DuplicateLitKey occurs when an index is duplicated in a slice, array, or
        // map literal.
        //
@@ -680,8 +649,6 @@ const (
        //  var _ = P {}
        _InvalidLit
 
-       /* exprs > selector */
-
        // _AmbiguousSelector occurs when a selector is ambiguous.
        //
        // Example:
@@ -727,8 +694,6 @@ const (
        //  var x = T{}.f
        _MissingFieldOrMethod
 
-       /* exprs > ... */
-
        // _BadDotDotDotSyntax occurs when a "..." occurs in a context where it is
        // not valid.
        //
@@ -753,51 +718,13 @@ const (
        _NonVariadicDotDotDot
 
        // _MisplacedDotDotDot occurs when a "..." is used somewhere other than the
-       // final argument to a function call.
+       // final argument in a function declaration.
        //
        // Example:
-       //  func printArgs(args ...int) {
-       //      for _, a := range args {
-       //              println(a)
-       //      }
-       //  }
-       //
-       //  func f() {
-       //      a := []int{1,2,3}
-       //      printArgs(0, a...)
-       //  }
+       //      func f(...int, int)
        _MisplacedDotDotDot
 
-       // _InvalidDotDotDotOperand occurs when a "..." operator is applied to a
-       // single-valued operand.
-       //
-       // Example:
-       //  func printArgs(args ...int) {
-       //      for _, a := range args {
-       //              println(a)
-       //      }
-       //  }
-       //
-       //  func f() {
-       //      a := 1
-       //      printArgs(a...)
-       //  }
-       //
-       // Example:
-       //  func args() (int, int) {
-       //      return 1, 2
-       //  }
-       //
-       //  func printArgs(args ...int) {
-       //      for _, a := range args {
-       //              println(a)
-       //      }
-       //  }
-       //
-       //  func g() {
-       //      printArgs(args()...)
-       //  }
-       _InvalidDotDotDotOperand
+       _ // _InvalidDotDotDotOperand was removed.
 
        // _InvalidDotDotDot occurs when a "..." is used in a non-variadic built-in
        // function.
@@ -807,8 +734,6 @@ const (
        //  var l = len(s...)
        _InvalidDotDotDot
 
-       /* exprs > built-in */
-
        // _UncalledBuiltin occurs when a built-in function is used as a
        // function-valued expression, instead of being called.
        //
@@ -920,8 +845,6 @@ const (
        //  var _ = real(int(1))
        _InvalidReal
 
-       /* exprs > assertion */
-
        // _InvalidAssert occurs when a type assertion is applied to a
        // value that is not of interface type.
        //
@@ -945,8 +868,6 @@ const (
        //  var _ = x.(T)
        _ImpossibleAssert
 
-       /* exprs > conversion */
-
        // _InvalidConversion occurs when the argument type cannot be converted to the
        // target.
        //
@@ -966,8 +887,6 @@ const (
        //  var _ = 1 + ""
        _InvalidUntypedConversion
 
-       /* offsetof */
-
        // _BadOffsetofSyntax occurs when unsafe.Offsetof is called with an argument
        // that is not a selector expression.
        //
@@ -1006,8 +925,6 @@ const (
        //  var _ = unsafe.Offsetof(s.m)
        _InvalidOffsetof
 
-       /* control flow > scope */
-
        // _UnusedExpr occurs when a side-effect free expression is used as a
        // statement. Such a statement has no effect.
        //
@@ -1055,8 +972,6 @@ const (
        //  }
        _OutOfScopeResult
 
-       /* control flow > if */
-
        // _InvalidCond occurs when an if condition is not a boolean expression.
        //
        // Example:
@@ -1067,8 +982,6 @@ const (
        //  }
        _InvalidCond
 
-       /* control flow > for */
-
        // _InvalidPostDecl occurs when there is a declaration in a for-loop post
        // statement.
        //
@@ -1078,17 +991,7 @@ const (
        //  }
        _InvalidPostDecl
 
-       // _InvalidChanRange occurs when a send-only channel used in a range
-       // expression.
-       //
-       // Example:
-       //  func sum(c chan<- int) {
-       //      s := 0
-       //      for i := range c {
-       //              s += i
-       //      }
-       //  }
-       _InvalidChanRange
+       _ // _InvalidChanRange was removed.
 
        // _InvalidIterVar occurs when two iteration variables are used while ranging
        // over a channel.
@@ -1112,8 +1015,6 @@ const (
        //  }
        _InvalidRangeExpr
 
-       /* control flow > switch */
-
        // _MisplacedBreak occurs when a break statement is not within a for, switch,
        // or select statement of the innermost function definition.
        //
@@ -1217,8 +1118,6 @@ const (
        //  }
        _InvalidExprSwitch
 
-       /* control flow > select */
-
        // _InvalidSelectCase occurs when a select case is not a channel send or
        // receive.
        //
@@ -1233,8 +1132,6 @@ const (
        //  }
        _InvalidSelectCase
 
-       /* control flow > labels and jumps */
-
        // _UndeclaredLabel occurs when an undeclared label is jumped to.
        //
        // Example:
@@ -1302,8 +1199,6 @@ const (
        // }
        _JumpIntoBlock
 
-       /* control flow > calls */
-
        // _InvalidMethodExpr occurs when a pointer method is called but the argument
        // is not addressable.
        //
@@ -1331,8 +1226,6 @@ const (
        //  var y = x()
        _InvalidCall
 
-       /* control flow > suspended */
-
        // _UnusedResults occurs when a restricted expression-only built-in function
        // is suspended via go or defer. Such a suspension discards the results of
        // these side-effect free built-in functions, and therefore is ineffectual.
@@ -1363,4 +1256,61 @@ const (
        //      return i
        //  }
        _InvalidGo
+
+       // All codes below were added in Go 1.17.
+
+       // _BadDecl occurs when a declaration has invalid syntax.
+       _BadDecl
+
+       // _RepeatedDecl occurs when an identifier occurs more than once on the left
+       // hand side of a short variable declaration.
+       //
+       // Example:
+       //  func _() {
+       //      x, y, y := 1, 2, 3
+       //  }
+       _RepeatedDecl
+
+       // _InvalidUnsafeAdd occurs when unsafe.Add is called with a
+       // length argument that is not of integer type.
+       //
+       // Example:
+       //  import "unsafe"
+       //
+       //  var p unsafe.Pointer
+       //  var _ = unsafe.Add(p, float64(1))
+       _InvalidUnsafeAdd
+
+       // _InvalidUnsafeSlice occurs when unsafe.Slice is called with a
+       // pointer argument that is not of pointer type or a length argument
+       // that is not of integer type, negative, or out of bounds.
+       //
+       // Example:
+       //  import "unsafe"
+       //
+       //  var x int
+       //  var _ = unsafe.Slice(x, 1)
+       //
+       // Example:
+       //  import "unsafe"
+       //
+       //  var x int
+       //  var _ = unsafe.Slice(&x, float64(1))
+       //
+       // Example:
+       //  import "unsafe"
+       //
+       //  var x int
+       //  var _ = unsafe.Slice(&x, -1)
+       //
+       // Example:
+       //  import "unsafe"
+       //
+       //  var x int
+       //  var _ = unsafe.Slice(&x, uint64(1) << 63)
+       _InvalidUnsafeSlice
+
+       // _Todo is a placeholder for error codes that have not been decided.
+       // TODO(rFindley) remove this error code after deciding on errors for generics code.
+       _Todo
 )
index a2195011f0ee63a2f8c8459ce1617ff6cae212f0..226310641733ae833e91e63064ec6a8db71ea469 100644 (file)
@@ -28,8 +28,13 @@ func unreachable() {
 func (check *Checker) qualifier(pkg *Package) string {
        // Qualify the package unless it's the package being type-checked.
        if pkg != check.pkg {
+               if check.pkgPathMap == nil {
+                       check.pkgPathMap = make(map[string]map[string]bool)
+                       check.seenPkgMap = make(map[*Package]bool)
+                       check.markImports(check.pkg)
+               }
                // If the same package name was used by multiple packages, display the full path.
-               if check.pkgCnt[pkg.name] > 1 {
+               if len(check.pkgPathMap[pkg.name]) > 1 {
                        return strconv.Quote(pkg.path)
                }
                return pkg.name
@@ -37,6 +42,26 @@ func (check *Checker) qualifier(pkg *Package) string {
        return ""
 }
 
+// markImports recursively walks pkg and its imports, to record unique import
+// paths in pkgPathMap.
+func (check *Checker) markImports(pkg *Package) {
+       if check.seenPkgMap[pkg] {
+               return
+       }
+       check.seenPkgMap[pkg] = true
+
+       forName, ok := check.pkgPathMap[pkg.name]
+       if !ok {
+               forName = make(map[string]bool)
+               check.pkgPathMap[pkg.name] = forName
+       }
+       forName[pkg.path] = true
+
+       for _, imp := range pkg.imports {
+               check.markImports(imp)
+       }
+}
+
 func (check *Checker) sprintf(format string, args ...interface{}) string {
        for i, arg := range args {
                switch a := arg.(type) {
@@ -89,15 +114,18 @@ func (check *Checker) err(err error) {
                return
        }
 
-       if check.errpos != nil && isInternal {
-               // If we have an internal error and the errpos override is set, use it to
-               // augment our error positioning.
-               // TODO(rFindley) we may also want to augment the error message and refer
-               // to the position (pos) in the original expression.
-               span := spanOf(check.errpos)
-               e.Pos = span.pos
-               e.go116start = span.start
-               e.go116end = span.end
+       if isInternal {
+               e.Msg = stripAnnotations(e.Msg)
+               if check.errpos != nil {
+                       // If we have an internal error and the errpos override is set, use it to
+                       // augment our error positioning.
+                       // TODO(rFindley) we may also want to augment the error message and refer
+                       // to the position (pos) in the original expression.
+                       span := spanOf(check.errpos)
+                       e.Pos = span.pos
+                       e.go116start = span.start
+                       e.go116end = span.end
+               }
                err = e
        }
 
@@ -225,3 +253,18 @@ func spanOf(at positioner) posSpan {
                return posSpan{pos, pos, pos}
        }
 }
+
+// stripAnnotations removes internal (type) annotations from s.
+func stripAnnotations(s string) string {
+       var b strings.Builder
+       for _, r := range s {
+               // strip #'s and subscript digits
+               if r != instanceMarker && !('₀' <= r && r < '₀'+10) { // '₀' == U+2080
+                       b.WriteRune(r)
+               }
+       }
+       if b.Len() < len(s) {
+               return b.String()
+       }
+       return s
+}
diff --git a/libgo/go/go/types/errors_test.go b/libgo/go/go/types/errors_test.go
new file mode 100644 (file)
index 0000000..fdbe07c
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types
+
+import "testing"
+
+func TestStripAnnotations(t *testing.T) {
+       for _, test := range []struct {
+               in, want string
+       }{
+               {"", ""},
+               {"   ", "   "},
+               {"foo", "foo"},
+               {"foo₀", "foo"},
+               {"foo(T₀)", "foo(T)"},
+               {"#foo(T₀)", "foo(T)"},
+       } {
+               got := stripAnnotations(test.in)
+               if got != test.want {
+                       t.Errorf("%q: got %q; want %q", test.in, got, test.want)
+               }
+       }
+}
index d940bf0e80a9cb89956badca19249e2798dd88ae..41d3a61b89528ed7e8c4445585982f8efc593bd0 100644 (file)
@@ -76,7 +76,7 @@ func TestEvalArith(t *testing.T) {
                `false == false`,
                `12345678 + 87654321 == 99999999`,
                `10 * 20 == 200`,
-               `(1<<1000)*2 >> 100 == 2<<900`,
+               `(1<<500)*2 >> 100 == 2<<400`,
                `"foo" + "bar" == "foobar"`,
                `"abc" <= "bcd"`,
                `len([10]struct{}{}) == 2*5`,
@@ -155,9 +155,9 @@ func TestEvalPos(t *testing.T) {
                import "io"
                type R = io.Reader
                func _() {
-                       /* interface{R}.Read => , func(interface{io.Reader}, p []byte) (n int, err error) */
+                       /* interface{R}.Read => , func(interface{io.Reader}, p []byte) (n int, err error) */
                        _ = func() {
-                               /* interface{io.Writer}.Write => , func(interface{io.Writer}, p []byte) (n int, err error) */
+                               /* interface{io.Writer}.Write => , func(interface{io.Writer}, p []byte) (n int, err error) */
                                type io interface {} // must not shadow io in line above
                        }
                        type R interface {} // must not shadow R in first line of this function body
index 95bb2702ef3e84db54b61edf272973ee766f8a9c..ffbb5c08d35d8c2a08f9294c987eeb0366f9edf2 100644 (file)
@@ -5,6 +5,7 @@
 // Only run where builders (build.golang.org) have
 // access to compiled packages for import.
 //
+//go:build !arm && !arm64
 // +build !arm,!arm64
 
 package types_test
index eb2056125a7b71aecf3efb362cd98ec5146a09a1..58962e777bc9541ec549a0c0de0035187f0331ac 100644 (file)
@@ -10,6 +10,7 @@ import (
        "fmt"
        "go/ast"
        "go/constant"
+       "go/internal/typeparams"
        "go/token"
        "math"
 )
@@ -58,11 +59,16 @@ the type (and constant value, if any) is recorded via Info.Types, if present.
 
 type opPredicates map[token.Token]func(Type) bool
 
-var unaryOpPredicates = opPredicates{
-       token.ADD: isNumeric,
-       token.SUB: isNumeric,
-       token.XOR: isInteger,
-       token.NOT: isBoolean,
+var unaryOpPredicates opPredicates
+
+func init() {
+       // Setting unaryOpPredicates in init avoids declaration cycles.
+       unaryOpPredicates = opPredicates{
+               token.ADD: isNumeric,
+               token.SUB: isNumeric,
+               token.XOR: isInteger,
+               token.NOT: isBoolean,
+       }
 }
 
 func (check *Checker) op(m opPredicates, x *operand, op token.Token) bool {
@@ -78,13 +84,77 @@ func (check *Checker) op(m opPredicates, x *operand, op token.Token) bool {
        return true
 }
 
+// overflow checks that the constant x is representable by its type.
+// For untyped constants, it checks that the value doesn't become
+// arbitrarily large.
+func (check *Checker) overflow(x *operand, op token.Token, opPos token.Pos) {
+       assert(x.mode == constant_)
+
+       if x.val.Kind() == constant.Unknown {
+               // TODO(gri) We should report exactly what went wrong. At the
+               //           moment we don't have the (go/constant) API for that.
+               //           See also TODO in go/constant/value.go.
+               check.errorf(atPos(opPos), _InvalidConstVal, "constant result is not representable")
+               return
+       }
+
+       // Typed constants must be representable in
+       // their type after each constant operation.
+       if isTyped(x.typ) {
+               check.representable(x, asBasic(x.typ))
+               return
+       }
+
+       // Untyped integer values must not grow arbitrarily.
+       const prec = 512 // 512 is the constant precision
+       if x.val.Kind() == constant.Int && constant.BitLen(x.val) > prec {
+               check.errorf(atPos(opPos), _InvalidConstVal, "constant %s overflow", opName(x.expr))
+               x.val = constant.MakeUnknown()
+       }
+}
+
+// opName returns the name of an operation, or the empty string.
+// For now, only operations that might overflow are handled.
+// TODO(gri) Expand this to a general mechanism giving names to
+//           nodes?
+func opName(e ast.Expr) string {
+       switch e := e.(type) {
+       case *ast.BinaryExpr:
+               if int(e.Op) < len(op2str2) {
+                       return op2str2[e.Op]
+               }
+       case *ast.UnaryExpr:
+               if int(e.Op) < len(op2str1) {
+                       return op2str1[e.Op]
+               }
+       }
+       return ""
+}
+
+var op2str1 = [...]string{
+       token.XOR: "bitwise complement",
+}
+
+// This is only used for operations that may cause overflow.
+var op2str2 = [...]string{
+       token.ADD: "addition",
+       token.SUB: "subtraction",
+       token.XOR: "bitwise XOR",
+       token.MUL: "multiplication",
+       token.SHL: "shift",
+}
+
 // The unary expression e may be nil. It's passed in for better error messages only.
-func (check *Checker) unary(x *operand, e *ast.UnaryExpr, op token.Token) {
-       switch op {
+func (check *Checker) unary(x *operand, e *ast.UnaryExpr) {
+       check.expr(x, e.X)
+       if x.mode == invalid {
+               return
+       }
+       switch e.Op {
        case token.AND:
                // spec: "As an exception to the addressability
                // requirement x may also be a composite literal."
-               if _, ok := unparen(x.expr).(*ast.CompositeLit); !ok && x.mode != variable {
+               if _, ok := unparen(e.X).(*ast.CompositeLit); !ok && x.mode != variable {
                        check.invalidOp(x, _UnaddressableOperand, "cannot take address of %s", x)
                        x.mode = invalid
                        return
@@ -94,8 +164,8 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr, op token.Token) {
                return
 
        case token.ARROW:
-               typ, ok := x.typ.Underlying().(*Chan)
-               if !ok {
+               typ := asChan(x.typ)
+               if typ == nil {
                        check.invalidOp(x, _InvalidReceive, "cannot receive from non-channel %s", x)
                        x.mode = invalid
                        return
@@ -111,26 +181,23 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr, op token.Token) {
                return
        }
 
-       if !check.op(unaryOpPredicates, x, op) {
+       if !check.op(unaryOpPredicates, x, e.Op) {
                x.mode = invalid
                return
        }
 
        if x.mode == constant_ {
-               typ := x.typ.Underlying().(*Basic)
-               var prec uint
-               if isUnsigned(typ) {
-                       prec = uint(check.conf.sizeof(typ) * 8)
+               if x.val.Kind() == constant.Unknown {
+                       // nothing to do (and don't cause an error below in the overflow check)
+                       return
                }
-               x.val = constant.UnaryOp(op, x.val, prec)
-               // Typed constants must be representable in
-               // their type after each constant operation.
-               if isTyped(typ) {
-                       if e != nil {
-                               x.expr = e // for better error message
-                       }
-                       check.representable(x, typ)
+               var prec uint
+               if isUnsigned(x.typ) {
+                       prec = uint(check.conf.sizeof(x.typ) * 8)
                }
+               x.val = constant.UnaryOp(e.Op, x.val, prec)
+               x.expr = e
+               check.overflow(x, e.Op, x.Pos())
                return
        }
 
@@ -332,17 +399,24 @@ func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *c
 // representable checks that a constant operand is representable in the given
 // basic type.
 func (check *Checker) representable(x *operand, typ *Basic) {
-       if err := check.isRepresentable(x, typ); err != nil {
+       v, code := check.representation(x, typ)
+       if code != 0 {
+               check.invalidConversion(code, x, typ)
                x.mode = invalid
-               check.err(err)
+               return
        }
+       assert(v != nil)
+       x.val = v
 }
 
-func (check *Checker) isRepresentable(x *operand, typ *Basic) error {
+// representation returns the representation of the constant operand x as the
+// basic type typ.
+//
+// If no such representation is possible, it returns a non-zero error code.
+func (check *Checker) representation(x *operand, typ *Basic) (constant.Value, errorCode) {
        assert(x.mode == constant_)
-       if !representableConst(x.val, check, typ, &x.val) {
-               var msg string
-               var code errorCode
+       v := x.val
+       if !representableConst(x.val, check, typ, &v) {
                if isNumeric(x.typ) && isNumeric(typ) {
                        // numeric conversion : error msg
                        //
@@ -352,19 +426,25 @@ func (check *Checker) isRepresentable(x *operand, typ *Basic) error {
                        // float   -> float   : overflows
                        //
                        if !isInteger(x.typ) && isInteger(typ) {
-                               msg = "%s truncated to %s"
-                               code = _TruncatedFloat
+                               return nil, _TruncatedFloat
                        } else {
-                               msg = "%s overflows %s"
-                               code = _NumericOverflow
+                               return nil, _NumericOverflow
                        }
-               } else {
-                       msg = "cannot convert %s to %s"
-                       code = _InvalidConstVal
                }
-               return check.newErrorf(x, code, false, msg, x, typ)
+               return nil, _InvalidConstVal
        }
-       return nil
+       return v, 0
+}
+
+func (check *Checker) invalidConversion(code errorCode, x *operand, target Type) {
+       msg := "cannot convert %s to %s"
+       switch code {
+       case _TruncatedFloat:
+               msg = "%s truncated to %s"
+       case _NumericOverflow:
+               msg = "%s overflows %s"
+       }
+       check.errorf(x, code, msg, x, target)
 }
 
 // updateExprType updates the type of x to typ and invokes itself
@@ -456,7 +536,7 @@ func (check *Checker) updateExprType(x ast.Expr, typ Type, final bool) {
        // If the new type is not final and still untyped, just
        // update the recorded type.
        if !final && isUntyped(typ) {
-               old.typ = typ.Underlying().(*Basic)
+               old.typ = asBasic(typ)
                check.untyped[x] = old
                return
        }
@@ -500,15 +580,32 @@ func (check *Checker) updateExprVal(x ast.Expr, val constant.Value) {
 
 // convertUntyped attempts to set the type of an untyped value to the target type.
 func (check *Checker) convertUntyped(x *operand, target Type) {
-       if err := check.canConvertUntyped(x, target); err != nil {
+       newType, val, code := check.implicitTypeAndValue(x, target)
+       if code != 0 {
+               check.invalidConversion(code, x, target.Underlying())
                x.mode = invalid
-               check.err(err)
+               return
+       }
+       if val != nil {
+               x.val = val
+               check.updateExprVal(x.expr, val)
+       }
+       if newType != x.typ {
+               x.typ = newType
+               check.updateExprType(x.expr, newType, false)
        }
 }
 
-func (check *Checker) canConvertUntyped(x *operand, target Type) error {
+// implicitTypeAndValue returns the implicit type of x when used in a context
+// where the target type is expected. If no such implicit conversion is
+// possible, it returns a nil Type and non-zero error code.
+//
+// If x is a constant operand, the returned constant.Value will be the
+// representation of x in this context.
+func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, constant.Value, errorCode) {
+       target = expand(target)
        if x.mode == invalid || isTyped(x.typ) || target == Typ[Invalid] {
-               return nil
+               return x.typ, nil, 0
        }
 
        if isUntyped(target) {
@@ -517,43 +614,23 @@ func (check *Checker) canConvertUntyped(x *operand, target Type) error {
                tkind := target.(*Basic).kind
                if isNumeric(x.typ) && isNumeric(target) {
                        if xkind < tkind {
-                               x.typ = target
-                               check.updateExprType(x.expr, target, false)
+                               return target, nil, 0
                        }
                } else if xkind != tkind {
-                       return check.newErrorf(x, _InvalidUntypedConversion, false, "cannot convert %s to %s", x, target)
-               }
-               return nil
-       }
-
-       if t, ok := target.Underlying().(*Basic); ok && x.mode == constant_ {
-               if err := check.isRepresentable(x, t); err != nil {
-                       return err
+                       return nil, nil, _InvalidUntypedConversion
                }
-               // Expression value may have been rounded - update if needed.
-               check.updateExprVal(x.expr, x.val)
-       } else {
-               newTarget := check.implicitType(x, target)
-               if newTarget == nil {
-                       return check.newErrorf(x, _InvalidUntypedConversion, false, "cannot convert %s to %s", x, target)
-               }
-               target = newTarget
+               return x.typ, nil, 0
        }
-       x.typ = target
-       // Even though implicitType can return UntypedNil, this value is final: the
-       // predeclared identifier nil has no type.
-       check.updateExprType(x.expr, target, true)
-       return nil
-}
 
-// implicitType returns the implicit type of x when used in a context where the
-// target type is expected. If no such implicit conversion is possible, it
-// returns nil.
-func (check *Checker) implicitType(x *operand, target Type) Type {
-       assert(isUntyped(x.typ))
-       switch t := target.Underlying().(type) {
+       switch t := optype(target).(type) {
        case *Basic:
-               assert(x.mode != constant_)
+               if x.mode == constant_ {
+                       v, code := check.representation(x, t)
+                       if code != 0 {
+                               return nil, nil, code
+                       }
+                       return target, v, code
+               }
                // Non-constant untyped values may appear as the
                // result of comparisons (untyped bool), intermediate
                // (delayed-checked) rhs operands of shifts, and as
@@ -561,26 +638,40 @@ func (check *Checker) implicitType(x *operand, target Type) Type {
                switch x.typ.(*Basic).kind {
                case UntypedBool:
                        if !isBoolean(target) {
-                               return nil
+                               return nil, nil, _InvalidUntypedConversion
                        }
                case UntypedInt, UntypedRune, UntypedFloat, UntypedComplex:
                        if !isNumeric(target) {
-                               return nil
+                               return nil, nil, _InvalidUntypedConversion
                        }
                case UntypedString:
                        // Non-constant untyped string values are not permitted by the spec and
                        // should not occur during normal typechecking passes, but this path is
                        // reachable via the AssignableTo API.
                        if !isString(target) {
-                               return nil
+                               return nil, nil, _InvalidUntypedConversion
                        }
                case UntypedNil:
                        // Unsafe.Pointer is a basic type that includes nil.
                        if !hasNil(target) {
-                               return nil
+                               return nil, nil, _InvalidUntypedConversion
                        }
+                       // Preserve the type of nil as UntypedNil: see #13061.
+                       return Typ[UntypedNil], nil, 0
                default:
-                       return nil
+                       return nil, nil, _InvalidUntypedConversion
+               }
+       case *_Sum:
+               ok := t.is(func(t Type) bool {
+                       target, _, _ := check.implicitTypeAndValue(x, t)
+                       return target != nil
+               })
+               if !ok {
+                       return nil, nil, _InvalidUntypedConversion
+               }
+               // keep nil untyped (was bug #39755)
+               if x.isNil() {
+                       return Typ[UntypedNil], nil, 0
                }
        case *Interface:
                // Values must have concrete dynamic types. If the value is nil,
@@ -588,24 +679,24 @@ func (check *Checker) implicitType(x *operand, target Type) Type {
                // need the dynamic type for argument checking of say, print
                // functions)
                if x.isNil() {
-                       return Typ[UntypedNil]
+                       return Typ[UntypedNil], nil, 0
                }
                // cannot assign untyped values to non-empty interfaces
-               check.completeInterface(t)
+               check.completeInterface(token.NoPos, t)
                if !t.Empty() {
-                       return nil
+                       return nil, nil, _InvalidUntypedConversion
                }
-               return Default(x.typ)
+               return Default(x.typ), nil, 0
        case *Pointer, *Signature, *Slice, *Map, *Chan:
                if !x.isNil() {
-                       return nil
+                       return nil, nil, _InvalidUntypedConversion
                }
                // Keep nil untyped - see comment for interfaces, above.
-               return Typ[UntypedNil]
+               return Typ[UntypedNil], nil, 0
        default:
-               return nil
+               return nil, nil, _InvalidUntypedConversion
        }
-       return target
+       return target, nil, 0
 }
 
 func (check *Checker) comparison(x, y *operand, op token.Token) {
@@ -665,15 +756,16 @@ func (check *Checker) comparison(x, y *operand, op token.Token) {
        x.typ = Typ[UntypedBool]
 }
 
-func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) {
-       untypedx := isUntyped(x.typ)
+// If e != nil, it must be the shift expression; it may be nil for non-constant shifts.
+func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) {
+       // TODO(gri) This function seems overly complex. Revisit.
 
        var xval constant.Value
        if x.mode == constant_ {
                xval = constant.ToInt(x.val)
        }
 
-       if isInteger(x.typ) || untypedx && xval != nil && xval.Kind() == constant.Int {
+       if isInteger(x.typ) || isUntyped(x.typ) && xval != nil && xval.Kind() == constant.Int {
                // The lhs is of integer type or an untyped constant representable
                // as an integer. Nothing to do.
        } else {
@@ -685,10 +777,40 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) {
 
        // spec: "The right operand in a shift expression must have integer type
        // or be an untyped constant representable by a value of type uint."
+
+       // Check that constants are representable by uint, but do not convert them
+       // (see also issue #47243).
+       if y.mode == constant_ {
+               // Provide a good error message for negative shift counts.
+               yval := constant.ToInt(y.val) // consider -1, 1.0, but not -1.1
+               if yval.Kind() == constant.Int && constant.Sign(yval) < 0 {
+                       check.invalidOp(y, _InvalidShiftCount, "negative shift count %s", y)
+                       x.mode = invalid
+                       return
+               }
+
+               if isUntyped(y.typ) {
+                       // Caution: Check for representability here, rather than in the switch
+                       // below, because isInteger includes untyped integers (was bug #43697).
+                       check.representable(y, Typ[Uint])
+                       if y.mode == invalid {
+                               x.mode = invalid
+                               return
+                       }
+               }
+       }
+
+       // Check that RHS is otherwise at least of integer type.
        switch {
        case isInteger(y.typ):
-               // nothing to do
+               if !isUnsigned(y.typ) && !check.allowVersion(check.pkg, 1, 13) {
+                       check.invalidOp(y, _InvalidShiftCount, "signed shift count %s requires go1.13 or later", y)
+                       x.mode = invalid
+                       return
+               }
        case isUntyped(y.typ):
+               // This is incorrect, but preserves pre-existing behavior.
+               // See also bug #47410.
                check.convertUntyped(y, Typ[Uint])
                if y.mode == invalid {
                        x.mode = invalid
@@ -700,25 +822,20 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) {
                return
        }
 
-       var yval constant.Value
-       if y.mode == constant_ {
-               // rhs must be an integer value
-               // (Either it was of an integer type already, or it was
-               // untyped and successfully converted to a uint above.)
-               yval = constant.ToInt(y.val)
-               assert(yval.Kind() == constant.Int)
-               if constant.Sign(yval) < 0 {
-                       check.invalidOp(y, _InvalidShiftCount, "negative shift count %s", y)
-                       x.mode = invalid
-                       return
-               }
-       }
-
        if x.mode == constant_ {
                if y.mode == constant_ {
+                       // if either x or y has an unknown value, the result is unknown
+                       if x.val.Kind() == constant.Unknown || y.val.Kind() == constant.Unknown {
+                               x.val = constant.MakeUnknown()
+                               // ensure the correct type - see comment below
+                               if !isInteger(x.typ) {
+                                       x.typ = Typ[UntypedInt]
+                               }
+                               return
+                       }
                        // rhs must be within reasonable bounds in constant shifts
-                       const shiftBound = 1023 - 1 + 52 // so we can express smallestFloat64
-                       s, ok := constant.Uint64Val(yval)
+                       const shiftBound = 1023 - 1 + 52 // so we can express smallestFloat64 (see issue #44057)
+                       s, ok := constant.Uint64Val(y.val)
                        if !ok || s > shiftBound {
                                check.invalidOp(y, _InvalidShiftCount, "invalid shift count %s", y)
                                x.mode = invalid
@@ -733,19 +850,17 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) {
                        }
                        // x is a constant so xval != nil and it must be of Int kind.
                        x.val = constant.Shift(xval, op, uint(s))
-                       // Typed constants must be representable in
-                       // their type after each constant operation.
-                       if isTyped(x.typ) {
-                               if e != nil {
-                                       x.expr = e // for better error message
-                               }
-                               check.representable(x, x.typ.Underlying().(*Basic))
+                       x.expr = e
+                       opPos := x.Pos()
+                       if b, _ := e.(*ast.BinaryExpr); b != nil {
+                               opPos = b.OpPos
                        }
+                       check.overflow(x, op, opPos)
                        return
                }
 
                // non-constant shift with constant lhs
-               if untypedx {
+               if isUntyped(x.typ) {
                        // spec: "If the left operand of a non-constant shift
                        // expression is an untyped constant, the type of the
                        // constant is what it would be if the shift expression
@@ -785,24 +900,30 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) {
        x.mode = value
 }
 
-var binaryOpPredicates = opPredicates{
-       token.ADD: func(typ Type) bool { return isNumeric(typ) || isString(typ) },
-       token.SUB: isNumeric,
-       token.MUL: isNumeric,
-       token.QUO: isNumeric,
-       token.REM: isInteger,
+var binaryOpPredicates opPredicates
 
-       token.AND:     isInteger,
-       token.OR:      isInteger,
-       token.XOR:     isInteger,
-       token.AND_NOT: isInteger,
+func init() {
+       // Setting binaryOpPredicates in init avoids declaration cycles.
+       binaryOpPredicates = opPredicates{
+               token.ADD: isNumericOrString,
+               token.SUB: isNumeric,
+               token.MUL: isNumeric,
+               token.QUO: isNumeric,
+               token.REM: isInteger,
 
-       token.LAND: isBoolean,
-       token.LOR:  isBoolean,
+               token.AND:     isInteger,
+               token.OR:      isInteger,
+               token.XOR:     isInteger,
+               token.AND_NOT: isInteger,
+
+               token.LAND: isBoolean,
+               token.LOR:  isBoolean,
+       }
 }
 
-// The binary expression e may be nil. It's passed in for better error messages only.
-func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, op token.Token, opPos token.Pos) {
+// If e != nil, it must be the binary expression; it may be nil for non-constant expressions
+// (when invoked for an assignment operation where the binary expression is implicit).
+func (check *Checker) binary(x *operand, e ast.Expr, lhs, rhs ast.Expr, op token.Token, opPos token.Pos) {
        var y operand
 
        check.expr(x, lhs)
@@ -877,30 +998,19 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o
        }
 
        if x.mode == constant_ && y.mode == constant_ {
-               xval := x.val
-               yval := y.val
-               typ := x.typ.Underlying().(*Basic)
+               // if either x or y has an unknown value, the result is unknown
+               if x.val.Kind() == constant.Unknown || y.val.Kind() == constant.Unknown {
+                       x.val = constant.MakeUnknown()
+                       // x.typ is unchanged
+                       return
+               }
                // force integer division of integer operands
-               if op == token.QUO && isInteger(typ) {
+               if op == token.QUO && isInteger(x.typ) {
                        op = token.QUO_ASSIGN
                }
-               x.val = constant.BinaryOp(xval, op, yval)
-               // report error if valid operands lead to an invalid result
-               if xval.Kind() != constant.Unknown && yval.Kind() != constant.Unknown && x.val.Kind() == constant.Unknown {
-                       // TODO(gri) We should report exactly what went wrong. At the
-                       //           moment we don't have the (go/constant) API for that.
-                       //           See also TODO in go/constant/value.go.
-                       check.errorf(atPos(opPos), _InvalidConstVal, "constant result is not representable")
-                       // TODO(gri) Should we mark operands with unknown values as invalid?
-               }
-               // Typed constants must be representable in
-               // their type after each constant operation.
-               if isTyped(typ) {
-                       if e != nil {
-                               x.expr = e // for better error message
-                       }
-                       check.representable(x, typ)
-               }
+               x.val = constant.BinaryOp(x.val, op, y.val)
+               x.expr = e
+               check.overflow(x, op, opPos)
                return
        }
 
@@ -908,100 +1018,6 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o
        // x.typ is unchanged
 }
 
-// index checks an index expression for validity.
-// If max >= 0, it is the upper bound for index.
-// If the result typ is != Typ[Invalid], index is valid and typ is its (possibly named) integer type.
-// If the result val >= 0, index is valid and val is its constant int value.
-func (check *Checker) index(index ast.Expr, max int64) (typ Type, val int64) {
-       typ = Typ[Invalid]
-       val = -1
-
-       var x operand
-       check.expr(&x, index)
-       if x.mode == invalid {
-               return
-       }
-
-       // an untyped constant must be representable as Int
-       check.convertUntyped(&x, Typ[Int])
-       if x.mode == invalid {
-               return
-       }
-
-       // the index must be of integer type
-       if !isInteger(x.typ) {
-               check.invalidArg(&x, _InvalidIndex, "index %s must be integer", &x)
-               return
-       }
-
-       if x.mode != constant_ {
-               return x.typ, -1
-       }
-
-       // a constant index i must be in bounds
-       if constant.Sign(x.val) < 0 {
-               check.invalidArg(&x, _InvalidIndex, "index %s must not be negative", &x)
-               return
-       }
-
-       v, valid := constant.Int64Val(constant.ToInt(x.val))
-       if !valid || max >= 0 && v >= max {
-               check.errorf(&x, _InvalidIndex, "index %s is out of bounds", &x)
-               return
-       }
-
-       // 0 <= v [ && v < max ]
-       return Typ[Int], v
-}
-
-// indexElts checks the elements (elts) of an array or slice composite literal
-// against the literal's element type (typ), and the element indices against
-// the literal length if known (length >= 0). It returns the length of the
-// literal (maximum index value + 1).
-//
-func (check *Checker) indexedElts(elts []ast.Expr, typ Type, length int64) int64 {
-       visited := make(map[int64]bool, len(elts))
-       var index, max int64
-       for _, e := range elts {
-               // determine and check index
-               validIndex := false
-               eval := e
-               if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
-                       if typ, i := check.index(kv.Key, length); typ != Typ[Invalid] {
-                               if i >= 0 {
-                                       index = i
-                                       validIndex = true
-                               } else {
-                                       check.errorf(e, _InvalidLitIndex, "index %s must be integer constant", kv.Key)
-                               }
-                       }
-                       eval = kv.Value
-               } else if length >= 0 && index >= length {
-                       check.errorf(e, _OversizeArrayLit, "index %d is out of bounds (>= %d)", index, length)
-               } else {
-                       validIndex = true
-               }
-
-               // if we have a valid index, check for duplicate entries
-               if validIndex {
-                       if visited[index] {
-                               check.errorf(e, _DuplicateLitKey, "duplicate index %d in array or slice literal", index)
-                       }
-                       visited[index] = true
-               }
-               index++
-               if index > max {
-                       max = index
-               }
-
-               // check element against composite literal element type
-               var x operand
-               check.exprWithHint(&x, eval, typ)
-               check.assignment(&x, typ, "array or slice literal")
-       }
-       return max
-}
-
 // exprKind describes the kind of an expression; the kind
 // determines if an expression is valid in 'statement context'.
 type exprKind int
@@ -1018,7 +1034,7 @@ const (
 //
 func (check *Checker) rawExpr(x *operand, e ast.Expr, hint Type) exprKind {
        if trace {
-               check.trace(e.Pos(), "%s", e)
+               check.trace(e.Pos(), "expr %s", e)
                check.indent++
                defer func() {
                        check.indent--
@@ -1027,31 +1043,7 @@ func (check *Checker) rawExpr(x *operand, e ast.Expr, hint Type) exprKind {
        }
 
        kind := check.exprInternal(x, e, hint)
-
-       // convert x into a user-friendly set of values
-       // TODO(gri) this code can be simplified
-       var typ Type
-       var val constant.Value
-       switch x.mode {
-       case invalid:
-               typ = Typ[Invalid]
-       case novalue:
-               typ = (*Tuple)(nil)
-       case constant_:
-               typ = x.typ
-               val = x.val
-       default:
-               typ = x.typ
-       }
-       assert(x.expr != nil && typ != nil)
-
-       if isUntyped(typ) {
-               // delay type and value recording until we know the type
-               // or until the end of type checking
-               check.rememberUntyped(x.expr, false, x.mode, typ.(*Basic), val)
-       } else {
-               check.recordTypeAndValue(e, x.mode, typ, val)
-       }
+       check.record(x)
 
        return kind
 }
@@ -1079,6 +1071,24 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                goto Error
 
        case *ast.BasicLit:
+               switch e.Kind {
+               case token.INT, token.FLOAT, token.IMAG:
+                       check.langCompat(e)
+                       // The max. mantissa precision for untyped numeric values
+                       // is 512 bits, or 4048 bits for each of the two integer
+                       // parts of a fraction for floating-point numbers that are
+                       // represented accurately in the go/constant package.
+                       // Constant literals that are longer than this many bits
+                       // are not meaningful; and excessively long constants may
+                       // consume a lot of space and time for a useless conversion.
+                       // Cap constant length with a generous upper limit that also
+                       // allows for separators between all digits.
+                       const limit = 10000
+                       if len(e.Value) > limit {
+                               check.errorf(e, _InvalidConstVal, "excessively long constant: %s... (%d chars)", e.Value[:10], len(e.Value))
+                               goto Error
+                       }
+               }
                x.setConst(e.Kind, e.Value)
                if x.mode == invalid {
                        // The parser already establishes syntactic correctness.
@@ -1091,18 +1101,20 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
 
        case *ast.FuncLit:
                if sig, ok := check.typ(e.Type).(*Signature); ok {
-                       // Anonymous functions are considered part of the
-                       // init expression/func declaration which contains
-                       // them: use existing package-level declaration info.
-                       decl := check.decl // capture for use in closure below
-                       iota := check.iota // capture for use in closure below (#22345)
-                       // Don't type-check right away because the function may
-                       // be part of a type definition to which the function
-                       // body refers. Instead, type-check as soon as possible,
-                       // but before the enclosing scope contents changes (#22992).
-                       check.later(func() {
-                               check.funcBody(decl, "<function literal>", sig, e.Body, iota)
-                       })
+                       if !check.conf.IgnoreFuncBodies && e.Body != nil {
+                               // Anonymous functions are considered part of the
+                               // init expression/func declaration which contains
+                               // them: use existing package-level declaration info.
+                               decl := check.decl // capture for use in closure below
+                               iota := check.iota // capture for use in closure below (#22345)
+                               // Don't type-check right away because the function may
+                               // be part of a type definition to which the function
+                               // body refers. Instead, type-check as soon as possible,
+                               // but before the enclosing scope contents changes (#22992).
+                               check.later(func() {
+                                       check.funcBody(decl, "<function literal>", sig, e.Body, iota)
+                               })
+                       }
                        x.mode = value
                        x.typ = sig
                } else {
@@ -1123,7 +1135,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                                        // We have an "open" [...]T array type.
                                        // Create a new ArrayType with unknown length (-1)
                                        // and finish setting it up after analyzing the literal.
-                                       typ = &Array{len: -1, elem: check.typ(atyp.Elt)}
+                                       typ = &Array{len: -1, elem: check.varType(atyp.Elt)}
                                        base = typ
                                        break
                                }
@@ -1134,7 +1146,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                case hint != nil:
                        // no composite literal type present - use hint (element type of enclosing type)
                        typ = hint
-                       base, _ = deref(typ.Underlying()) // *T implies &T{}
+                       base, _ = deref(under(typ)) // *T implies &T{}
 
                default:
                        // TODO(gri) provide better error messages depending on context
@@ -1142,7 +1154,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                        goto Error
                }
 
-               switch utyp := base.Underlying().(type) {
+               switch utyp := optype(base).(type) {
                case *Struct:
                        if len(e.Elts) == 0 {
                                break
@@ -1270,7 +1282,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                                        duplicate := false
                                        // if the key is of interface type, the type is also significant when checking for duplicates
                                        xkey := keyVal(x.val)
-                                       if _, ok := utyp.key.Underlying().(*Interface); ok {
+                                       if asInterface(utyp.key) != nil {
                                                for _, vtyp := range visited[xkey] {
                                                        if check.identical(vtyp, x.typ) {
                                                                duplicate = true
@@ -1322,184 +1334,30 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                check.selector(x, e)
 
        case *ast.IndexExpr:
-               check.expr(x, e.X)
-               if x.mode == invalid {
-                       check.use(e.Index)
-                       goto Error
+               if check.indexExpr(x, e) {
+                       check.funcInst(x, e)
                }
-
-               valid := false
-               length := int64(-1) // valid if >= 0
-               switch typ := x.typ.Underlying().(type) {
-               case *Basic:
-                       if isString(typ) {
-                               valid = true
-                               if x.mode == constant_ {
-                                       length = int64(len(constant.StringVal(x.val)))
-                               }
-                               // an indexed string always yields a byte value
-                               // (not a constant) even if the string and the
-                               // index are constant
-                               x.mode = value
-                               x.typ = universeByte // use 'byte' name
-                       }
-
-               case *Array:
-                       valid = true
-                       length = typ.len
-                       if x.mode != variable {
-                               x.mode = value
-                       }
-                       x.typ = typ.elem
-
-               case *Pointer:
-                       if typ, _ := typ.base.Underlying().(*Array); typ != nil {
-                               valid = true
-                               length = typ.len
-                               x.mode = variable
-                               x.typ = typ.elem
-                       }
-
-               case *Slice:
-                       valid = true
-                       x.mode = variable
-                       x.typ = typ.elem
-
-               case *Map:
-                       var key operand
-                       check.expr(&key, e.Index)
-                       check.assignment(&key, typ.key, "map index")
-                       // ok to continue even if indexing failed - map element type is known
-                       x.mode = mapindex
-                       x.typ = typ.elem
-                       x.expr = e
-                       return expression
-               }
-
-               if !valid {
-                       check.invalidOp(x, _NonIndexableOperand, "cannot index %s", x)
-                       goto Error
-               }
-
-               if e.Index == nil {
-                       check.invalidAST(e, "missing index for %s", x)
+               if x.mode == invalid {
                        goto Error
                }
 
-               check.index(e.Index, length)
-               // ok to continue
-
        case *ast.SliceExpr:
-               check.expr(x, e.X)
+               check.sliceExpr(x, e)
                if x.mode == invalid {
-                       check.use(e.Low, e.High, e.Max)
-                       goto Error
-               }
-
-               valid := false
-               length := int64(-1) // valid if >= 0
-               switch typ := x.typ.Underlying().(type) {
-               case *Basic:
-                       if isString(typ) {
-                               if e.Slice3 {
-                                       check.invalidOp(x, _InvalidSliceExpr, "3-index slice of string")
-                                       goto Error
-                               }
-                               valid = true
-                               if x.mode == constant_ {
-                                       length = int64(len(constant.StringVal(x.val)))
-                               }
-                               // spec: "For untyped string operands the result
-                               // is a non-constant value of type string."
-                               if typ.kind == UntypedString {
-                                       x.typ = Typ[String]
-                               }
-                       }
-
-               case *Array:
-                       valid = true
-                       length = typ.len
-                       if x.mode != variable {
-                               check.invalidOp(x, _NonSliceableOperand, "cannot slice %s (value not addressable)", x)
-                               goto Error
-                       }
-                       x.typ = &Slice{elem: typ.elem}
-
-               case *Pointer:
-                       if typ, _ := typ.base.Underlying().(*Array); typ != nil {
-                               valid = true
-                               length = typ.len
-                               x.typ = &Slice{elem: typ.elem}
-                       }
-
-               case *Slice:
-                       valid = true
-                       // x.typ doesn't change
-               }
-
-               if !valid {
-                       check.invalidOp(x, _NonSliceableOperand, "cannot slice %s", x)
-                       goto Error
-               }
-
-               x.mode = value
-
-               // spec: "Only the first index may be omitted; it defaults to 0."
-               if e.Slice3 && (e.High == nil || e.Max == nil) {
-                       check.invalidAST(inNode(e, e.Rbrack), "2nd and 3rd index required in 3-index slice")
                        goto Error
                }
 
-               // check indices
-               var ind [3]int64
-               for i, expr := range []ast.Expr{e.Low, e.High, e.Max} {
-                       x := int64(-1)
-                       switch {
-                       case expr != nil:
-                               // The "capacity" is only known statically for strings, arrays,
-                               // and pointers to arrays, and it is the same as the length for
-                               // those types.
-                               max := int64(-1)
-                               if length >= 0 {
-                                       max = length + 1
-                               }
-                               if _, v := check.index(expr, max); v >= 0 {
-                                       x = v
-                               }
-                       case i == 0:
-                               // default is 0 for the first index
-                               x = 0
-                       case length >= 0:
-                               // default is length (== capacity) otherwise
-                               x = length
-                       }
-                       ind[i] = x
-               }
-
-               // constant indices must be in range
-               // (check.index already checks that existing indices >= 0)
-       L:
-               for i, x := range ind[:len(ind)-1] {
-                       if x > 0 {
-                               for _, y := range ind[i+1:] {
-                                       if y >= 0 && x > y {
-                                               check.errorf(inNode(e, e.Rbrack), _SwappedSliceIndices, "swapped slice indices: %d > %d", x, y)
-                                               break L // only report one error, ok to continue
-                                       }
-                               }
-                       }
-               }
-
        case *ast.TypeAssertExpr:
                check.expr(x, e.X)
                if x.mode == invalid {
                        goto Error
                }
-               xtyp, _ := x.typ.Underlying().(*Interface)
+               xtyp, _ := under(x.typ).(*Interface)
                if xtyp == nil {
                        check.invalidOp(x, _InvalidAssert, "%s is not an interface", x)
                        goto Error
                }
+               check.ordinaryType(x, xtyp)
                // x.(type) expressions are handled explicitly in type switches
                if e.Type == nil {
                        // Don't use invalidAST because this can occur in the AST produced by
@@ -1507,7 +1365,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                        check.error(e, _BadTypeKeyword, "use of .(type) outside type switch")
                        goto Error
                }
-               T := check.typ(e.Type)
+               T := check.varType(e.Type)
                if T == Typ[Invalid] {
                        goto Error
                }
@@ -1516,7 +1374,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                x.typ = T
 
        case *ast.CallExpr:
-               return check.call(x, e)
+               return check.callExpr(x, e)
 
        case *ast.StarExpr:
                check.exprOrType(x, e.X)
@@ -1526,7 +1384,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                case typexpr:
                        x.typ = &Pointer{base: x.typ}
                default:
-                       if typ, ok := x.typ.Underlying().(*Pointer); ok {
+                       if typ := asPointer(x.typ); typ != nil {
                                x.mode = variable
                                x.typ = typ.base
                        } else {
@@ -1536,11 +1394,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                }
 
        case *ast.UnaryExpr:
-               check.expr(x, e.X)
-               if x.mode == invalid {
-                       goto Error
-               }
-               check.unary(x, e, e.Op)
+               check.unary(x, e)
                if x.mode == invalid {
                        goto Error
                }
@@ -1571,7 +1425,12 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                // types, which are comparatively rare.
 
        default:
-               panic(fmt.Sprintf("%s: unknown expression type %T", check.fset.Position(e.Pos()), e))
+               if typeparams.IsListExpr(e) {
+                       // catch-all for unexpected expression lists
+                       check.errorf(e, _Todo, "unexpected list of expressions")
+               } else {
+                       panic(fmt.Sprintf("%s: unknown expression type %T", check.fset.Position(e.Pos()), e))
+               }
        }
 
        // everything went well
@@ -1627,46 +1486,20 @@ func (check *Checker) typeAssertion(at positioner, x *operand, xtyp *Interface,
        check.errorf(at, _ImpossibleAssert, "%s cannot have dynamic type %s (%s)", x, T, msg)
 }
 
-func (check *Checker) singleValue(x *operand) {
-       if x.mode == value {
-               // tuple types are never named - no need for underlying type below
-               if t, ok := x.typ.(*Tuple); ok {
-                       assert(t.Len() != 1)
-                       check.errorf(x, _TooManyValues, "%d-valued %s where single value is expected", t.Len(), x)
-                       x.mode = invalid
-               }
-       }
-}
-
 // expr typechecks expression e and initializes x with the expression value.
 // The result must be a single value.
 // If an error occurred, x.mode is set to invalid.
 //
 func (check *Checker) expr(x *operand, e ast.Expr) {
-       check.multiExpr(x, e)
+       check.rawExpr(x, e, nil)
+       check.exclude(x, 1<<novalue|1<<builtin|1<<typexpr)
        check.singleValue(x)
 }
 
-// multiExpr is like expr but the result may be a multi-value.
+// multiExpr is like expr but the result may also be a multi-value.
 func (check *Checker) multiExpr(x *operand, e ast.Expr) {
        check.rawExpr(x, e, nil)
-       var msg string
-       var code errorCode
-       switch x.mode {
-       default:
-               return
-       case novalue:
-               msg = "%s used as value"
-               code = _TooManyValues
-       case builtin:
-               msg = "%s must be called"
-               code = _UncalledBuiltin
-       case typexpr:
-               msg = "%s is not an expression"
-               code = _NotAnExpr
-       }
-       check.errorf(x, code, msg, x)
-       x.mode = invalid
+       check.exclude(x, 1<<novalue|1<<builtin|1<<typexpr)
 }
 
 // exprWithHint typechecks expression e and initializes x with the expression value;
@@ -1676,24 +1509,8 @@ func (check *Checker) multiExpr(x *operand, e ast.Expr) {
 func (check *Checker) exprWithHint(x *operand, e ast.Expr, hint Type) {
        assert(hint != nil)
        check.rawExpr(x, e, hint)
+       check.exclude(x, 1<<novalue|1<<builtin|1<<typexpr)
        check.singleValue(x)
-       var msg string
-       var code errorCode
-       switch x.mode {
-       default:
-               return
-       case novalue:
-               msg = "%s used as value"
-               code = _TooManyValues
-       case builtin:
-               msg = "%s must be called"
-               code = _UncalledBuiltin
-       case typexpr:
-               msg = "%s is not an expression"
-               code = _NotAnExpr
-       }
-       check.errorf(x, code, msg, x)
-       x.mode = invalid
 }
 
 // exprOrType typechecks expression or type e and initializes x with the expression value or type.
@@ -1701,9 +1518,46 @@ func (check *Checker) exprWithHint(x *operand, e ast.Expr, hint Type) {
 //
 func (check *Checker) exprOrType(x *operand, e ast.Expr) {
        check.rawExpr(x, e, nil)
+       check.exclude(x, 1<<novalue)
        check.singleValue(x)
-       if x.mode == novalue {
-               check.errorf(x, _NotAnExpr, "%s used as value or type", x)
+}
+
+// exclude reports an error if x.mode is in modeset and sets x.mode to invalid.
+// The modeset may contain any of 1<<novalue, 1<<builtin, 1<<typexpr.
+func (check *Checker) exclude(x *operand, modeset uint) {
+       if modeset&(1<<x.mode) != 0 {
+               var msg string
+               var code errorCode
+               switch x.mode {
+               case novalue:
+                       if modeset&(1<<typexpr) != 0 {
+                               msg = "%s used as value"
+                       } else {
+                               msg = "%s used as value or type"
+                       }
+                       code = _TooManyValues
+               case builtin:
+                       msg = "%s must be called"
+                       code = _UncalledBuiltin
+               case typexpr:
+                       msg = "%s is not an expression"
+                       code = _NotAnExpr
+               default:
+                       unreachable()
+               }
+               check.errorf(x, code, msg, x)
                x.mode = invalid
        }
 }
+
+// singleValue reports an error if x describes a tuple and sets x.mode to invalid.
+func (check *Checker) singleValue(x *operand) {
+       if x.mode == value {
+               // tuple types are never named - no need for underlying type below
+               if t, ok := x.typ.(*Tuple); ok {
+                       assert(t.Len() != 1)
+                       check.errorf(x, _TooManyValues, "%d-valued %s where single value is expected", t.Len(), x)
+                       x.mode = invalid
+               }
+       }
+}
index 28d605f5ee8410a08fff044bfa5be2f571a2922b..f05e6424d44d88a89e4fecde277b15f34344320b 100644 (file)
@@ -8,7 +8,9 @@ package types
 
 import (
        "bytes"
+       "fmt"
        "go/ast"
+       "go/internal/typeparams"
 )
 
 // ExprString returns the (possibly shortened) string representation for x.
@@ -31,7 +33,7 @@ func WriteExpr(buf *bytes.Buffer, x ast.Expr) {
 
        switch x := x.(type) {
        default:
-               buf.WriteString("(bad expr)") // nil, ast.BadExpr, ast.KeyValueExpr
+               buf.WriteString(fmt.Sprintf("(ast: %T)", x)) // nil, ast.BadExpr, ast.KeyValueExpr
 
        case *ast.Ident:
                buf.WriteString(x.Name)
@@ -68,7 +70,13 @@ func WriteExpr(buf *bytes.Buffer, x ast.Expr) {
        case *ast.IndexExpr:
                WriteExpr(buf, x.X)
                buf.WriteByte('[')
-               WriteExpr(buf, x.Index)
+               exprs := typeparams.UnpackExpr(x.Index)
+               for i, e := range exprs {
+                       if i > 0 {
+                               buf.WriteString(", ")
+                       }
+                       WriteExpr(buf, e)
+               }
                buf.WriteByte(']')
 
        case *ast.SliceExpr:
@@ -98,12 +106,7 @@ func WriteExpr(buf *bytes.Buffer, x ast.Expr) {
        case *ast.CallExpr:
                WriteExpr(buf, x.Fun)
                buf.WriteByte('(')
-               for i, arg := range x.Args {
-                       if i > 0 {
-                               buf.WriteString(", ")
-                       }
-                       WriteExpr(buf, arg)
-               }
+               writeExprList(buf, x.Args)
                if x.Ellipsis.IsValid() {
                        buf.WriteString("...")
                }
@@ -134,7 +137,7 @@ func WriteExpr(buf *bytes.Buffer, x ast.Expr) {
 
        case *ast.StructType:
                buf.WriteString("struct{")
-               writeFieldList(buf, x.Fields, "; ", false)
+               writeFieldList(buf, x.Fields.List, "; ", false)
                buf.WriteByte('}')
 
        case *ast.FuncType:
@@ -142,8 +145,29 @@ func WriteExpr(buf *bytes.Buffer, x ast.Expr) {
                writeSigExpr(buf, x)
 
        case *ast.InterfaceType:
+               // separate type list types from method list
+               // TODO(gri) we can get rid of this extra code if writeExprList does the separation
+               var types []ast.Expr
+               var methods []*ast.Field
+               for _, f := range x.Methods.List {
+                       if len(f.Names) > 1 && f.Names[0].Name == "type" {
+                               // type list type
+                               types = append(types, f.Type)
+                       } else {
+                               // method or embedded interface
+                               methods = append(methods, f)
+                       }
+               }
+
                buf.WriteString("interface{")
-               writeFieldList(buf, x.Methods, "; ", true)
+               writeFieldList(buf, methods, "; ", true)
+               if len(types) > 0 {
+                       if len(methods) > 0 {
+                               buf.WriteString("; ")
+                       }
+                       buf.WriteString("type ")
+                       writeExprList(buf, types)
+               }
                buf.WriteByte('}')
 
        case *ast.MapType:
@@ -169,7 +193,7 @@ func WriteExpr(buf *bytes.Buffer, x ast.Expr) {
 
 func writeSigExpr(buf *bytes.Buffer, sig *ast.FuncType) {
        buf.WriteByte('(')
-       writeFieldList(buf, sig.Params, ", ", false)
+       writeFieldList(buf, sig.Params.List, ", ", false)
        buf.WriteByte(')')
 
        res := sig.Results
@@ -188,23 +212,18 @@ func writeSigExpr(buf *bytes.Buffer, sig *ast.FuncType) {
 
        // multiple or named result(s)
        buf.WriteByte('(')
-       writeFieldList(buf, res, ", ", false)
+       writeFieldList(buf, res.List, ", ", false)
        buf.WriteByte(')')
 }
 
-func writeFieldList(buf *bytes.Buffer, fields *ast.FieldList, sep string, iface bool) {
-       for i, f := range fields.List {
+func writeFieldList(buf *bytes.Buffer, list []*ast.Field, sep string, iface bool) {
+       for i, f := range list {
                if i > 0 {
                        buf.WriteString(sep)
                }
 
                // field list names
-               for i, name := range f.Names {
-                       if i > 0 {
-                               buf.WriteString(", ")
-                       }
-                       buf.WriteString(name.Name)
-               }
+               writeIdentList(buf, f.Names)
 
                // types of interface methods consist of signatures only
                if sig, _ := f.Type.(*ast.FuncType); sig != nil && iface {
@@ -222,3 +241,21 @@ func writeFieldList(buf *bytes.Buffer, fields *ast.FieldList, sep string, iface
                // ignore tag
        }
 }
+
+func writeIdentList(buf *bytes.Buffer, list []*ast.Ident) {
+       for i, x := range list {
+               if i > 0 {
+                       buf.WriteString(", ")
+               }
+               buf.WriteString(x.Name)
+       }
+}
+
+func writeExprList(buf *bytes.Buffer, list []ast.Expr) {
+       for i, x := range list {
+               if i > 0 {
+                       buf.WriteString(", ")
+               }
+               WriteExpr(buf, x)
+       }
+}
index 52709df17bdad6831537b3f56853c52dcb4efc04..ca1d42c14d5aec3d543529ace321d4f9fd54ca17 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 // Build this command explicitly: go build gotype.go
diff --git a/libgo/go/go/types/index.go b/libgo/go/go/types/index.go
new file mode 100644 (file)
index 0000000..2ba3475
--- /dev/null
@@ -0,0 +1,446 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements typechecking of index/slice expressions.
+
+package types
+
+import (
+       "go/ast"
+       "go/constant"
+       "go/internal/typeparams"
+)
+
+// If e is a valid function instantiation, indexExpr returns true.
+// In that case x represents the uninstantiated function value and
+// it is the caller's responsibility to instantiate the function.
+func (check *Checker) indexExpr(x *operand, e *ast.IndexExpr) (isFuncInst bool) {
+       check.exprOrType(x, e.X)
+
+       switch x.mode {
+       case invalid:
+               check.use(typeparams.UnpackExpr(e.Index)...)
+               return false
+
+       case typexpr:
+               // type instantiation
+               x.mode = invalid
+               x.typ = check.varType(e)
+               if x.typ != Typ[Invalid] {
+                       x.mode = typexpr
+               }
+               return false
+
+       case value:
+               if sig := asSignature(x.typ); sig != nil && len(sig.tparams) > 0 {
+                       // function instantiation
+                       return true
+               }
+       }
+
+       valid := false
+       length := int64(-1) // valid if >= 0
+       switch typ := optype(x.typ).(type) {
+       case *Basic:
+               if isString(typ) {
+                       valid = true
+                       if x.mode == constant_ {
+                               length = int64(len(constant.StringVal(x.val)))
+                       }
+                       // an indexed string always yields a byte value
+                       // (not a constant) even if the string and the
+                       // index are constant
+                       x.mode = value
+                       x.typ = universeByte // use 'byte' name
+               }
+
+       case *Array:
+               valid = true
+               length = typ.len
+               if x.mode != variable {
+                       x.mode = value
+               }
+               x.typ = typ.elem
+
+       case *Pointer:
+               if typ := asArray(typ.base); typ != nil {
+                       valid = true
+                       length = typ.len
+                       x.mode = variable
+                       x.typ = typ.elem
+               }
+
+       case *Slice:
+               valid = true
+               x.mode = variable
+               x.typ = typ.elem
+
+       case *Map:
+               index := check.singleIndex(e)
+               if index == nil {
+                       x.mode = invalid
+                       return
+               }
+               var key operand
+               check.expr(&key, index)
+               check.assignment(&key, typ.key, "map index")
+               // ok to continue even if indexing failed - map element type is known
+               x.mode = mapindex
+               x.typ = typ.elem
+               x.expr = e
+               return
+
+       case *_Sum:
+               // A sum type can be indexed if all of the sum's types
+               // support indexing and have the same index and element
+               // type. Special rules apply for maps in the sum type.
+               var tkey, telem Type // key is for map types only
+               nmaps := 0           // number of map types in sum type
+               if typ.is(func(t Type) bool {
+                       var e Type
+                       switch t := under(t).(type) {
+                       case *Basic:
+                               if isString(t) {
+                                       e = universeByte
+                               }
+                       case *Array:
+                               e = t.elem
+                       case *Pointer:
+                               if t := asArray(t.base); t != nil {
+                                       e = t.elem
+                               }
+                       case *Slice:
+                               e = t.elem
+                       case *Map:
+                               // If there are multiple maps in the sum type,
+                               // they must have identical key types.
+                               // TODO(gri) We may be able to relax this rule
+                               // but it becomes complicated very quickly.
+                               if tkey != nil && !Identical(t.key, tkey) {
+                                       return false
+                               }
+                               tkey = t.key
+                               e = t.elem
+                               nmaps++
+                       case *_TypeParam:
+                               check.errorf(x, 0, "type of %s contains a type parameter - cannot index (implementation restriction)", x)
+                       case *instance:
+                               panic("unimplemented")
+                       }
+                       if e == nil || telem != nil && !Identical(e, telem) {
+                               return false
+                       }
+                       telem = e
+                       return true
+               }) {
+                       // If there are maps, the index expression must be assignable
+                       // to the map key type (as for simple map index expressions).
+                       if nmaps > 0 {
+                               index := check.singleIndex(e)
+                               if index == nil {
+                                       x.mode = invalid
+                                       return
+                               }
+                               var key operand
+                               check.expr(&key, index)
+                               check.assignment(&key, tkey, "map index")
+                               // ok to continue even if indexing failed - map element type is known
+
+                               // If there are only maps, we are done.
+                               if nmaps == len(typ.types) {
+                                       x.mode = mapindex
+                                       x.typ = telem
+                                       x.expr = e
+                                       return
+                               }
+
+                               // Otherwise we have mix of maps and other types. For
+                               // now we require that the map key be an integer type.
+                               // TODO(gri) This is probably not good enough.
+                               valid = isInteger(tkey)
+                               // avoid 2nd indexing error if indexing failed above
+                               if !valid && key.mode == invalid {
+                                       x.mode = invalid
+                                       return
+                               }
+                               x.mode = value // map index expressions are not addressable
+                       } else {
+                               // no maps
+                               valid = true
+                               x.mode = variable
+                       }
+                       x.typ = telem
+               }
+       }
+
+       if !valid {
+               check.invalidOp(x, _NonIndexableOperand, "cannot index %s", x)
+               x.mode = invalid
+               return
+       }
+
+       index := check.singleIndex(e)
+       if index == nil {
+               x.mode = invalid
+               return
+       }
+
+       // In pathological (invalid) cases (e.g.: type T1 [][[]T1{}[0][0]]T0)
+       // the element type may be accessed before it's set. Make sure we have
+       // a valid type.
+       if x.typ == nil {
+               x.typ = Typ[Invalid]
+       }
+
+       check.index(index, length)
+       return false
+}
+
+func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) {
+       check.expr(x, e.X)
+       if x.mode == invalid {
+               check.use(e.Low, e.High, e.Max)
+               return
+       }
+
+       valid := false
+       length := int64(-1) // valid if >= 0
+       switch typ := optype(x.typ).(type) {
+       case *Basic:
+               if isString(typ) {
+                       if e.Slice3 {
+                               check.invalidOp(x, _InvalidSliceExpr, "3-index slice of string")
+                               x.mode = invalid
+                               return
+                       }
+                       valid = true
+                       if x.mode == constant_ {
+                               length = int64(len(constant.StringVal(x.val)))
+                       }
+                       // spec: "For untyped string operands the result
+                       // is a non-constant value of type string."
+                       if typ.kind == UntypedString {
+                               x.typ = Typ[String]
+                       }
+               }
+
+       case *Array:
+               valid = true
+               length = typ.len
+               if x.mode != variable {
+                       check.invalidOp(x, _NonSliceableOperand, "cannot slice %s (value not addressable)", x)
+                       x.mode = invalid
+                       return
+               }
+               x.typ = &Slice{elem: typ.elem}
+
+       case *Pointer:
+               if typ := asArray(typ.base); typ != nil {
+                       valid = true
+                       length = typ.len
+                       x.typ = &Slice{elem: typ.elem}
+               }
+
+       case *Slice:
+               valid = true
+               // x.typ doesn't change
+
+       case *_Sum, *_TypeParam:
+               check.errorf(x, 0, "generic slice expressions not yet implemented")
+               x.mode = invalid
+               return
+       }
+
+       if !valid {
+               check.invalidOp(x, _NonSliceableOperand, "cannot slice %s", x)
+               x.mode = invalid
+               return
+       }
+
+       x.mode = value
+
+       // spec: "Only the first index may be omitted; it defaults to 0."
+       if e.Slice3 && (e.High == nil || e.Max == nil) {
+               check.invalidAST(inNode(e, e.Rbrack), "2nd and 3rd index required in 3-index slice")
+               x.mode = invalid
+               return
+       }
+
+       // check indices
+       var ind [3]int64
+       for i, expr := range []ast.Expr{e.Low, e.High, e.Max} {
+               x := int64(-1)
+               switch {
+               case expr != nil:
+                       // The "capacity" is only known statically for strings, arrays,
+                       // and pointers to arrays, and it is the same as the length for
+                       // those types.
+                       max := int64(-1)
+                       if length >= 0 {
+                               max = length + 1
+                       }
+                       if _, v := check.index(expr, max); v >= 0 {
+                               x = v
+                       }
+               case i == 0:
+                       // default is 0 for the first index
+                       x = 0
+               case length >= 0:
+                       // default is length (== capacity) otherwise
+                       x = length
+               }
+               ind[i] = x
+       }
+
+       // constant indices must be in range
+       // (check.index already checks that existing indices >= 0)
+L:
+       for i, x := range ind[:len(ind)-1] {
+               if x > 0 {
+                       for _, y := range ind[i+1:] {
+                               if y >= 0 && x > y {
+                                       check.errorf(inNode(e, e.Rbrack), _SwappedSliceIndices, "swapped slice indices: %d > %d", x, y)
+                                       break L // only report one error, ok to continue
+                               }
+                       }
+               }
+       }
+}
+
+// singleIndex returns the (single) index from the index expression e.
+// If the index is missing, or if there are multiple indices, an error
+// is reported and the result is nil.
+func (check *Checker) singleIndex(e *ast.IndexExpr) ast.Expr {
+       index := e.Index
+       if index == nil {
+               check.invalidAST(e, "missing index for %s", e)
+               return nil
+       }
+
+       indexes := typeparams.UnpackExpr(index)
+       if len(indexes) == 0 {
+               check.invalidAST(index, "index expression %v with 0 indices", index)
+               return nil
+       }
+       if len(indexes) > 1 {
+               // TODO(rFindley) should this get a distinct error code?
+               check.invalidOp(indexes[1], _InvalidIndex, "more than one index")
+       }
+       return indexes[0]
+}
+
+// index checks an index expression for validity.
+// If max >= 0, it is the upper bound for index.
+// If the result typ is != Typ[Invalid], index is valid and typ is its (possibly named) integer type.
+// If the result val >= 0, index is valid and val is its constant int value.
+func (check *Checker) index(index ast.Expr, max int64) (typ Type, val int64) {
+       typ = Typ[Invalid]
+       val = -1
+
+       var x operand
+       check.expr(&x, index)
+       if !check.isValidIndex(&x, _InvalidIndex, "index", false) {
+               return
+       }
+
+       if x.mode != constant_ {
+               return x.typ, -1
+       }
+
+       if x.val.Kind() == constant.Unknown {
+               return
+       }
+
+       v, ok := constant.Int64Val(x.val)
+       assert(ok)
+       if max >= 0 && v >= max {
+               check.invalidArg(&x, _InvalidIndex, "index %s is out of bounds", &x)
+               return
+       }
+
+       // 0 <= v [ && v < max ]
+       return x.typ, v
+}
+
+func (check *Checker) isValidIndex(x *operand, code errorCode, what string, allowNegative bool) bool {
+       if x.mode == invalid {
+               return false
+       }
+
+       // spec: "a constant index that is untyped is given type int"
+       check.convertUntyped(x, Typ[Int])
+       if x.mode == invalid {
+               return false
+       }
+
+       // spec: "the index x must be of integer type or an untyped constant"
+       if !isInteger(x.typ) {
+               check.invalidArg(x, code, "%s %s must be integer", what, x)
+               return false
+       }
+
+       if x.mode == constant_ {
+               // spec: "a constant index must be non-negative ..."
+               if !allowNegative && constant.Sign(x.val) < 0 {
+                       check.invalidArg(x, code, "%s %s must not be negative", what, x)
+                       return false
+               }
+
+               // spec: "... and representable by a value of type int"
+               if !representableConst(x.val, check, Typ[Int], &x.val) {
+                       check.invalidArg(x, code, "%s %s overflows int", what, x)
+                       return false
+               }
+       }
+
+       return true
+}
+
+// indexElts checks the elements (elts) of an array or slice composite literal
+// against the literal's element type (typ), and the element indices against
+// the literal length if known (length >= 0). It returns the length of the
+// literal (maximum index value + 1).
+//
+func (check *Checker) indexedElts(elts []ast.Expr, typ Type, length int64) int64 {
+       visited := make(map[int64]bool, len(elts))
+       var index, max int64
+       for _, e := range elts {
+               // determine and check index
+               validIndex := false
+               eval := e
+               if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
+                       if typ, i := check.index(kv.Key, length); typ != Typ[Invalid] {
+                               if i >= 0 {
+                                       index = i
+                                       validIndex = true
+                               } else {
+                                       check.errorf(e, _InvalidLitIndex, "index %s must be integer constant", kv.Key)
+                               }
+                       }
+                       eval = kv.Value
+               } else if length >= 0 && index >= length {
+                       check.errorf(e, _OversizeArrayLit, "index %d is out of bounds (>= %d)", index, length)
+               } else {
+                       validIndex = true
+               }
+
+               // if we have a valid index, check for duplicate entries
+               if validIndex {
+                       if visited[index] {
+                               check.errorf(e, _DuplicateLitKey, "duplicate index %d in array or slice literal", index)
+                       }
+                       visited[index] = true
+               }
+               index++
+               if index > max {
+                       max = index
+               }
+
+               // check element against composite literal element type
+               var x operand
+               check.exprWithHint(&x, eval, typ)
+               check.assignment(&x, typ, "array or slice literal")
+       }
+       return max
+}
diff --git a/libgo/go/go/types/infer.go b/libgo/go/go/types/infer.go
new file mode 100644 (file)
index 0000000..5d49351
--- /dev/null
@@ -0,0 +1,482 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements type parameter inference given
+// a list of concrete arguments and a parameter list.
+
+package types
+
+import (
+       "go/token"
+       "strings"
+)
+
+// infer attempts to infer the complete set of type arguments for generic function instantiation/call
+// based on the given type parameters tparams, type arguments targs, function parameters params, and
+// function arguments args, if any. There must be at least one type parameter, no more type arguments
+// than type parameters, and params and args must match in number (incl. zero).
+// If successful, infer returns the complete list of type arguments, one for each type parameter.
+// Otherwise the result is nil and appropriate errors will be reported unless report is set to false.
+//
+// Inference proceeds in 3 steps:
+//
+//   1) Start with given type arguments.
+//   2) Infer type arguments from typed function arguments.
+//   3) Infer type arguments from untyped function arguments.
+//
+// Constraint type inference is used after each step to expand the set of type arguments.
+//
+func (check *Checker) infer(posn positioner, tparams []*TypeName, targs []Type, params *Tuple, args []*operand, report bool) (result []Type) {
+       if debug {
+               defer func() {
+                       assert(result == nil || len(result) == len(tparams))
+                       for _, targ := range result {
+                               assert(targ != nil)
+                       }
+                       //check.dump("### inferred targs = %s", result)
+               }()
+       }
+
+       // There must be at least one type parameter, and no more type arguments than type parameters.
+       n := len(tparams)
+       assert(n > 0 && len(targs) <= n)
+
+       // Function parameters and arguments must match in number.
+       assert(params.Len() == len(args))
+
+       // --- 0 ---
+       // If we already have all type arguments, we're done.
+       if len(targs) == n {
+               return targs
+       }
+       // len(targs) < n
+
+       // --- 1 ---
+       // Explicitly provided type arguments take precedence over any inferred types;
+       // and types inferred via constraint type inference take precedence over types
+       // inferred from function arguments.
+       // If we have type arguments, see how far we get with constraint type inference.
+       if len(targs) > 0 {
+               var index int
+               targs, index = check.inferB(tparams, targs, report)
+               if targs == nil || index < 0 {
+                       return targs
+               }
+       }
+
+       // Continue with the type arguments we have now. Avoid matching generic
+       // parameters that already have type arguments against function arguments:
+       // It may fail because matching uses type identity while parameter passing
+       // uses assignment rules. Instantiate the parameter list with the type
+       // arguments we have, and continue with that parameter list.
+
+       // First, make sure we have a "full" list of type arguments, so of which
+       // may be nil (unknown).
+       if len(targs) < n {
+               targs2 := make([]Type, n)
+               copy(targs2, targs)
+               targs = targs2
+       }
+       // len(targs) == n
+
+       // Substitute type arguments for their respective type parameters in params,
+       // if any. Note that nil targs entries are ignored by check.subst.
+       // TODO(gri) Can we avoid this (we're setting known type argumemts below,
+       //           but that doesn't impact the isParameterized check for now).
+       if params.Len() > 0 {
+               smap := makeSubstMap(tparams, targs)
+               params = check.subst(token.NoPos, params, smap).(*Tuple)
+       }
+
+       // --- 2 ---
+       // Unify parameter and argument types for generic parameters with typed arguments
+       // and collect the indices of generic parameters with untyped arguments.
+       // Terminology: generic parameter = function parameter with a type-parameterized type
+       u := newUnifier(check, false)
+       u.x.init(tparams)
+
+       // Set the type arguments which we know already.
+       for i, targ := range targs {
+               if targ != nil {
+                       u.x.set(i, targ)
+               }
+       }
+
+       errorf := func(kind string, tpar, targ Type, arg *operand) {
+               if !report {
+                       return
+               }
+               // provide a better error message if we can
+               targs, index := u.x.types()
+               if index == 0 {
+                       // The first type parameter couldn't be inferred.
+                       // If none of them could be inferred, don't try
+                       // to provide the inferred type in the error msg.
+                       allFailed := true
+                       for _, targ := range targs {
+                               if targ != nil {
+                                       allFailed = false
+                                       break
+                               }
+                       }
+                       if allFailed {
+                               check.errorf(arg, _Todo, "%s %s of %s does not match %s (cannot infer %s)", kind, targ, arg.expr, tpar, typeNamesString(tparams))
+                               return
+                       }
+               }
+               smap := makeSubstMap(tparams, targs)
+               // TODO(rFindley): pass a positioner here, rather than arg.Pos().
+               inferred := check.subst(arg.Pos(), tpar, smap)
+               if inferred != tpar {
+                       check.errorf(arg, _Todo, "%s %s of %s does not match inferred type %s for %s", kind, targ, arg.expr, inferred, tpar)
+               } else {
+                       check.errorf(arg, 0, "%s %s of %s does not match %s", kind, targ, arg.expr, tpar)
+               }
+       }
+
+       // indices of the generic parameters with untyped arguments - save for later
+       var indices []int
+       for i, arg := range args {
+               par := params.At(i)
+               // If we permit bidirectional unification, this conditional code needs to be
+               // executed even if par.typ is not parameterized since the argument may be a
+               // generic function (for which we want to infer its type arguments).
+               if isParameterized(tparams, par.typ) {
+                       if arg.mode == invalid {
+                               // An error was reported earlier. Ignore this targ
+                               // and continue, we may still be able to infer all
+                               // targs resulting in fewer follon-on errors.
+                               continue
+                       }
+                       if targ := arg.typ; isTyped(targ) {
+                               // If we permit bidirectional unification, and targ is
+                               // a generic function, we need to initialize u.y with
+                               // the respective type parameters of targ.
+                               if !u.unify(par.typ, targ) {
+                                       errorf("type", par.typ, targ, arg)
+                                       return nil
+                               }
+                       } else {
+                               indices = append(indices, i)
+                       }
+               }
+       }
+
+       // If we've got all type arguments, we're done.
+       var index int
+       targs, index = u.x.types()
+       if index < 0 {
+               return targs
+       }
+
+       // See how far we get with constraint type inference.
+       // Note that even if we don't have any type arguments, constraint type inference
+       // may produce results for constraints that explicitly specify a type.
+       targs, index = check.inferB(tparams, targs, report)
+       if targs == nil || index < 0 {
+               return targs
+       }
+
+       // --- 3 ---
+       // Use any untyped arguments to infer additional type arguments.
+       // Some generic parameters with untyped arguments may have been given
+       // a type by now, we can ignore them.
+       for _, i := range indices {
+               par := params.At(i)
+               // Since untyped types are all basic (i.e., non-composite) types, an
+               // untyped argument will never match a composite parameter type; the
+               // only parameter type it can possibly match against is a *TypeParam.
+               // Thus, only consider untyped arguments for generic parameters that
+               // are not of composite types and which don't have a type inferred yet.
+               if tpar, _ := par.typ.(*_TypeParam); tpar != nil && targs[tpar.index] == nil {
+                       arg := args[i]
+                       targ := Default(arg.typ)
+                       // The default type for an untyped nil is untyped nil. We must not
+                       // infer an untyped nil type as type parameter type. Ignore untyped
+                       // nil by making sure all default argument types are typed.
+                       if isTyped(targ) && !u.unify(par.typ, targ) {
+                               errorf("default type", par.typ, targ, arg)
+                               return nil
+                       }
+               }
+       }
+
+       // If we've got all type arguments, we're done.
+       targs, index = u.x.types()
+       if index < 0 {
+               return targs
+       }
+
+       // Again, follow up with constraint type inference.
+       targs, index = check.inferB(tparams, targs, report)
+       if targs == nil || index < 0 {
+               return targs
+       }
+
+       // At least one type argument couldn't be inferred.
+       assert(index >= 0 && targs[index] == nil)
+       tpar := tparams[index]
+       if report {
+               check.errorf(posn, _Todo, "cannot infer %s (%v) (%v)", tpar.name, tpar.pos, targs)
+       }
+       return nil
+}
+
+// typeNamesString produces a string containing all the
+// type names in list suitable for human consumption.
+func typeNamesString(list []*TypeName) string {
+       // common cases
+       n := len(list)
+       switch n {
+       case 0:
+               return ""
+       case 1:
+               return list[0].name
+       case 2:
+               return list[0].name + " and " + list[1].name
+       }
+
+       // general case (n > 2)
+       var b strings.Builder
+       for i, tname := range list[:n-1] {
+               if i > 0 {
+                       b.WriteString(", ")
+               }
+               b.WriteString(tname.name)
+       }
+       b.WriteString(", and ")
+       b.WriteString(list[n-1].name)
+       return b.String()
+}
+
+// IsParameterized reports whether typ contains any of the type parameters of tparams.
+func isParameterized(tparams []*TypeName, typ Type) bool {
+       w := tpWalker{
+               seen:    make(map[Type]bool),
+               tparams: tparams,
+       }
+       return w.isParameterized(typ)
+}
+
+type tpWalker struct {
+       seen    map[Type]bool
+       tparams []*TypeName
+}
+
+func (w *tpWalker) isParameterized(typ Type) (res bool) {
+       // detect cycles
+       if x, ok := w.seen[typ]; ok {
+               return x
+       }
+       w.seen[typ] = false
+       defer func() {
+               w.seen[typ] = res
+       }()
+
+       switch t := typ.(type) {
+       case nil, *Basic: // TODO(gri) should nil be handled here?
+               break
+
+       case *Array:
+               return w.isParameterized(t.elem)
+
+       case *Slice:
+               return w.isParameterized(t.elem)
+
+       case *Struct:
+               for _, fld := range t.fields {
+                       if w.isParameterized(fld.typ) {
+                               return true
+                       }
+               }
+
+       case *Pointer:
+               return w.isParameterized(t.base)
+
+       case *Tuple:
+               n := t.Len()
+               for i := 0; i < n; i++ {
+                       if w.isParameterized(t.At(i).typ) {
+                               return true
+                       }
+               }
+
+       case *_Sum:
+               return w.isParameterizedList(t.types)
+
+       case *Signature:
+               // t.tparams may not be nil if we are looking at a signature
+               // of a generic function type (or an interface method) that is
+               // part of the type we're testing. We don't care about these type
+               // parameters.
+               // Similarly, the receiver of a method may declare (rather then
+               // use) type parameters, we don't care about those either.
+               // Thus, we only need to look at the input and result parameters.
+               return w.isParameterized(t.params) || w.isParameterized(t.results)
+
+       case *Interface:
+               if t.allMethods != nil {
+                       // TODO(rFindley) at some point we should enforce completeness here
+                       for _, m := range t.allMethods {
+                               if w.isParameterized(m.typ) {
+                                       return true
+                               }
+                       }
+                       return w.isParameterizedList(unpackType(t.allTypes))
+               }
+
+               return t.iterate(func(t *Interface) bool {
+                       for _, m := range t.methods {
+                               if w.isParameterized(m.typ) {
+                                       return true
+                               }
+                       }
+                       return w.isParameterizedList(unpackType(t.types))
+               }, nil)
+
+       case *Map:
+               return w.isParameterized(t.key) || w.isParameterized(t.elem)
+
+       case *Chan:
+               return w.isParameterized(t.elem)
+
+       case *Named:
+               return w.isParameterizedList(t.targs)
+
+       case *_TypeParam:
+               // t must be one of w.tparams
+               return t.index < len(w.tparams) && w.tparams[t.index].typ == t
+
+       case *instance:
+               return w.isParameterizedList(t.targs)
+
+       default:
+               unreachable()
+       }
+
+       return false
+}
+
+func (w *tpWalker) isParameterizedList(list []Type) bool {
+       for _, t := range list {
+               if w.isParameterized(t) {
+                       return true
+               }
+       }
+       return false
+}
+
+// inferB returns the list of actual type arguments inferred from the type parameters'
+// bounds and an initial set of type arguments. If type inference is impossible because
+// unification fails, an error is reported if report is set to true, the resulting types
+// list is nil, and index is 0.
+// Otherwise, types is the list of inferred type arguments, and index is the index of the
+// first type argument in that list that couldn't be inferred (and thus is nil). If all
+// type arguments were inferred successfully, index is < 0. The number of type arguments
+// provided may be less than the number of type parameters, but there must be at least one.
+func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (types []Type, index int) {
+       assert(len(tparams) >= len(targs) && len(targs) > 0)
+
+       // Setup bidirectional unification between those structural bounds
+       // and the corresponding type arguments (which may be nil!).
+       u := newUnifier(check, false)
+       u.x.init(tparams)
+       u.y = u.x // type parameters between LHS and RHS of unification are identical
+
+       // Set the type arguments which we know already.
+       for i, targ := range targs {
+               if targ != nil {
+                       u.x.set(i, targ)
+               }
+       }
+
+       // Unify type parameters with their structural constraints, if any.
+       for _, tpar := range tparams {
+               typ := tpar.typ.(*_TypeParam)
+               sbound := check.structuralType(typ.bound)
+               if sbound != nil {
+                       if !u.unify(typ, sbound) {
+                               if report {
+                                       check.errorf(tpar, _Todo, "%s does not match %s", tpar, sbound)
+                               }
+                               return nil, 0
+                       }
+               }
+       }
+
+       // u.x.types() now contains the incoming type arguments plus any additional type
+       // arguments for which there were structural constraints. The newly inferred non-
+       // nil entries may still contain references to other type parameters. For instance,
+       // for [A any, B interface{type []C}, C interface{type *A}], if A == int
+       // was given, unification produced the type list [int, []C, *A]. We eliminate the
+       // remaining type parameters by substituting the type parameters in this type list
+       // until nothing changes anymore.
+       types, _ = u.x.types()
+       if debug {
+               for i, targ := range targs {
+                       assert(targ == nil || types[i] == targ)
+               }
+       }
+
+       // dirty tracks the indices of all types that may still contain type parameters.
+       // We know that nil type entries and entries corresponding to provided (non-nil)
+       // type arguments are clean, so exclude them from the start.
+       var dirty []int
+       for i, typ := range types {
+               if typ != nil && (i >= len(targs) || targs[i] == nil) {
+                       dirty = append(dirty, i)
+               }
+       }
+
+       for len(dirty) > 0 {
+               // TODO(gri) Instead of creating a new substMap for each iteration,
+               // provide an update operation for substMaps and only change when
+               // needed. Optimization.
+               smap := makeSubstMap(tparams, types)
+               n := 0
+               for _, index := range dirty {
+                       t0 := types[index]
+                       if t1 := check.subst(token.NoPos, t0, smap); t1 != t0 {
+                               types[index] = t1
+                               dirty[n] = index
+                               n++
+                       }
+               }
+               dirty = dirty[:n]
+       }
+
+       // Once nothing changes anymore, we may still have type parameters left;
+       // e.g., a structural constraint *P may match a type parameter Q but we
+       // don't have any type arguments to fill in for *P or Q (issue #45548).
+       // Don't let such inferences escape, instead nil them out.
+       for i, typ := range types {
+               if typ != nil && isParameterized(tparams, typ) {
+                       types[i] = nil
+               }
+       }
+
+       // update index
+       index = -1
+       for i, typ := range types {
+               if typ == nil {
+                       index = i
+                       break
+               }
+       }
+
+       return
+}
+
+// structuralType returns the structural type of a constraint, if any.
+func (check *Checker) structuralType(constraint Type) Type {
+       if iface, _ := under(constraint).(*Interface); iface != nil {
+               check.completeInterface(token.NoPos, iface)
+               types := unpackType(iface.allTypes)
+               if len(types) == 1 {
+                       return types[0]
+               }
+               return nil
+       }
+       return constraint
+}
index 34850eb03487732119e394218702775a52232f2c..6d08f88667f90209dd0cf0adeba06835247d3b42 100644 (file)
@@ -385,9 +385,9 @@ func TestIssue28005(t *testing.T) {
                        }
                }
                if obj == nil {
-                       t.Fatal("interface not found")
+                       t.Fatal("object X not found")
                }
-               iface := obj.Type().Underlying().(*Interface) // I must be an interface
+               iface := obj.Type().Underlying().(*Interface) // object X must be an interface
 
                // Each iface method m is embedded; and m's receiver base type name
                // must match the method's name per the choice in the source file.
@@ -477,7 +477,7 @@ func TestIssue34151(t *testing.T) {
        }
 
        bast := mustParse(t, bsrc)
-       conf := Config{Importer: importHelper{a}}
+       conf := Config{Importer: importHelper{pkg: a}}
        b, err := conf.Check(bast.Name.Name, fset, []*ast.File{bast}, nil)
        if err != nil {
                t.Errorf("package %s failed to typecheck: %v", b.Name(), err)
@@ -485,14 +485,18 @@ func TestIssue34151(t *testing.T) {
 }
 
 type importHelper struct {
-       pkg *Package
+       pkg      *Package
+       fallback Importer
 }
 
 func (h importHelper) Import(path string) (*Package, error) {
-       if path != h.pkg.Path() {
+       if path == h.pkg.Path() {
+               return h.pkg, nil
+       }
+       if h.fallback == nil {
                return nil, fmt.Errorf("got package path %q; want %q", path, h.pkg.Path())
        }
-       return h.pkg, nil
+       return h.fallback.Import(path)
 }
 
 // TestIssue34921 verifies that we don't update an imported type's underlying
@@ -516,7 +520,7 @@ func TestIssue34921(t *testing.T) {
        var pkg *Package
        for _, src := range sources {
                f := mustParse(t, src)
-               conf := Config{Importer: importHelper{pkg}}
+               conf := Config{Importer: importHelper{pkg: pkg}}
                res, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, nil)
                if err != nil {
                        t.Errorf("%q failed to typecheck: %v", src, err)
@@ -549,3 +553,90 @@ func TestIssue43088(t *testing.T) {
        Comparable(T1)
        Comparable(T2)
 }
+
+func TestIssue44515(t *testing.T) {
+       typ := Unsafe.Scope().Lookup("Pointer").Type()
+
+       got := TypeString(typ, nil)
+       want := "unsafe.Pointer"
+       if got != want {
+               t.Errorf("got %q; want %q", got, want)
+       }
+
+       qf := func(pkg *Package) string {
+               if pkg == Unsafe {
+                       return "foo"
+               }
+               return ""
+       }
+       got = TypeString(typ, qf)
+       want = "foo.Pointer"
+       if got != want {
+               t.Errorf("got %q; want %q", got, want)
+       }
+}
+
+func TestIssue43124(t *testing.T) {
+       t.Skip("skipping for gccgo--no importer")
+
+       // TODO(rFindley) move this to testdata by enhancing support for importing.
+
+       // All involved packages have the same name (template). Error messages should
+       // disambiguate between text/template and html/template by printing the full
+       // path.
+       const (
+               asrc = `package a; import "text/template"; func F(template.Template) {}; func G(int) {}`
+               bsrc = `
+package b
+
+import (
+       "a"
+       "html/template"
+)
+
+func _() {
+       // Packages should be fully qualified when there is ambiguity within the
+       // error string itself.
+       a.F(template /* ERROR cannot use.*html/template.* as .*text/template */ .Template{})
+}
+`
+               csrc = `
+package c
+
+import (
+       "a"
+       "fmt"
+       "html/template"
+)
+
+// Issue #46905: make sure template is not the first package qualified.
+var _ fmt.Stringer = 1 // ERROR cannot use 1.*as fmt\.Stringer
+
+// Packages should be fully qualified when there is ambiguity in reachable
+// packages. In this case both a (and for that matter html/template) import
+// text/template.
+func _() { a.G(template /* ERROR cannot use .*html/template.*Template */ .Template{}) }
+`
+
+               tsrc = `
+package template
+
+import "text/template"
+
+type T int
+
+// Verify that the current package name also causes disambiguation.
+var _ T = template /* ERROR cannot use.*text/template.* as T value */.Template{}
+`
+       )
+
+       a, err := pkgFor("a", asrc, nil)
+       if err != nil {
+               t.Fatalf("package a failed to typecheck: %v", err)
+       }
+       imp := importHelper{pkg: a, fallback: importer.Default()}
+
+       checkFiles(t, nil, "", []string{"b.go"}, [][]byte{[]byte(bsrc)}, false, imp)
+       checkFiles(t, nil, "", []string{"c.go"}, [][]byte{[]byte(csrc)}, false, imp)
+       checkFiles(t, nil, "", []string{"t.go"}, [][]byte{[]byte(tsrc)}, false, imp)
+}
index 3c9ff182ec7c2446628ad857fa9264dbe2126115..9c7bfd4bb97da8db276c633874c8dda8186dffda 100644 (file)
@@ -6,6 +6,8 @@
 
 package types
 
+import "go/token"
+
 // LookupFieldOrMethod looks up a field or method with given package and name
 // in T and returns the corresponding *Var or *Func, an index sequence, and a
 // bool indicating if there were any pointer indirections on the path to the
@@ -53,7 +55,7 @@ func (check *Checker) lookupFieldOrMethod(T Type, addressable bool, pkg *Package
        // Thus, if we have a named pointer type, proceed with the underlying
        // pointer type but discard the result if it is a method since we would
        // not have found it for T (see also issue 8590).
-       if t, _ := T.(*Named); t != nil {
+       if t := asNamed(T); t != nil {
                if p, _ := t.underlying.(*Pointer); p != nil {
                        obj, index, indirect = check.rawLookupFieldOrMethod(p, false, pkg, name)
                        if _, ok := obj.(*Func); ok {
@@ -83,7 +85,8 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack
        typ, isPtr := deref(T)
 
        // *typ where typ is an interface has no methods.
-       if isPtr && IsInterface(typ) {
+       // Be cautious: typ may be nil (issue 39634, crash #3).
+       if typ == nil || isPtr && IsInterface(typ) {
                return
        }
 
@@ -104,12 +107,13 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack
                var next []embeddedType // embedded types found at current depth
 
                // look for (pkg, name) in all types at current depth
+               var tpar *_TypeParam // set if obj receiver is a type parameter
                for _, e := range current {
                        typ := e.typ
 
                        // If we have a named type, we may have associated methods.
                        // Look for those first.
-                       if named, _ := typ.(*Named); named != nil {
+                       if named := asNamed(typ); named != nil {
                                if seen[named] {
                                        // We have seen this type before, at a more shallow depth
                                        // (note that multiples of this type at the current depth
@@ -136,10 +140,17 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack
                                        continue // we can't have a matching field or interface method
                                }
 
-                               // continue with underlying type
-                               typ = named.underlying
+                               // continue with underlying type, but only if it's not a type parameter
+                               // TODO(gri) is this what we want to do for type parameters? (spec question)
+                               // TODO(#45639) the error message produced as a result of skipping an
+                               //              underlying type parameter should be improved.
+                               typ = named.under()
+                               if asTypeParam(typ) != nil {
+                                       continue
+                               }
                        }
 
+                       tpar = nil
                        switch t := typ.(type) {
                        case *Struct:
                                // look for a matching field and collect embedded types
@@ -175,7 +186,7 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack
                        case *Interface:
                                // look for a matching method
                                // TODO(gri) t.allMethods is sorted - use binary search
-                               check.completeInterface(t)
+                               check.completeInterface(token.NoPos, t)
                                if i, m := lookupMethod(t.allMethods, pkg, name); m != nil {
                                        assert(m.typ != nil)
                                        index = concat(e.index, i)
@@ -185,6 +196,20 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack
                                        obj = m
                                        indirect = e.indirect
                                }
+
+                       case *_TypeParam:
+                               // only consider explicit methods in the type parameter bound, not
+                               // methods that may be common to all types in the type list.
+                               if i, m := lookupMethod(t.Bound().allMethods, pkg, name); m != nil {
+                                       assert(m.typ != nil)
+                                       index = concat(e.index, i)
+                                       if obj != nil || e.multiples {
+                                               return nil, index, false // collision
+                                       }
+                                       tpar = t
+                                       obj = m
+                                       indirect = e.indirect
+                               }
                        }
                }
 
@@ -194,8 +219,12 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack
                        //        contains m and the argument list can be assigned to the parameter
                        //        list of m. If x is addressable and &x's method set contains m, x.m()
                        //        is shorthand for (&x).m()".
-                       if f, _ := obj.(*Func); f != nil && ptrRecv(f) && !indirect && !addressable {
-                               return nil, nil, true // pointer/addressable receiver required
+                       if f, _ := obj.(*Func); f != nil {
+                               // determine if method has a pointer receiver
+                               hasPtrRecv := tpar == nil && ptrRecv(f)
+                               if hasPtrRecv && !indirect && !addressable {
+                                       return nil, nil, true // pointer/addressable receiver required
+                               }
                        }
                        return
                }
@@ -267,7 +296,8 @@ func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType b
        return m, typ != nil
 }
 
-// missingMethod is like MissingMethod but accepts a receiver.
+// missingMethod is like MissingMethod but accepts a *Checker as
+// receiver and an addressable flag.
 // The receiver may be nil if missingMethod is invoked through
 // an exported API call (such as MissingMethod), i.e., when all
 // methods have been type-checked.
@@ -276,32 +306,53 @@ func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType b
 // To improve error messages, also report the wrong signature
 // when the method exists on *V instead of V.
 func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, wrongType *Func) {
-       check.completeInterface(T)
+       check.completeInterface(token.NoPos, T)
 
        // fast path for common case
        if T.Empty() {
                return
        }
 
-       if ityp, _ := V.Underlying().(*Interface); ityp != nil {
-               check.completeInterface(ityp)
+       if ityp := asInterface(V); ityp != nil {
+               check.completeInterface(token.NoPos, ityp)
                // TODO(gri) allMethods is sorted - can do this more efficiently
                for _, m := range T.allMethods {
-                       _, obj := lookupMethod(ityp.allMethods, m.pkg, m.name)
-                       switch {
-                       case obj == nil:
-                               if static {
-                                       return m, nil
+                       _, f := lookupMethod(ityp.allMethods, m.pkg, m.name)
+
+                       if f == nil {
+                               // if m is the magic method == we're ok (interfaces are comparable)
+                               if m.name == "==" || !static {
+                                       continue
                                }
-                       case !check.identical(obj.Type(), m.typ):
-                               return m, obj
+                               return m, f
+                       }
+
+                       ftyp := f.typ.(*Signature)
+                       mtyp := m.typ.(*Signature)
+                       if len(ftyp.tparams) != len(mtyp.tparams) {
+                               return m, f
+                       }
+
+                       // If the methods have type parameters we don't care whether they
+                       // are the same or not, as long as they match up. Use unification
+                       // to see if they can be made to match.
+                       // TODO(gri) is this always correct? what about type bounds?
+                       // (Alternative is to rename/subst type parameters and compare.)
+                       u := newUnifier(check, true)
+                       u.x.init(ftyp.tparams)
+                       if !u.unify(ftyp, mtyp) {
+                               return m, f
                        }
                }
+
                return
        }
 
        // A concrete type implements T if it implements all methods of T.
+       Vd, _ := deref(V)
+       Vn := asNamed(Vd)
        for _, m := range T.allMethods {
+               // TODO(gri) should this be calling lookupFieldOrMethod instead (and why not)?
                obj, _, _ := check.rawLookupFieldOrMethod(V, false, m.pkg, m.name)
 
                // Check if *V implements this method of T.
@@ -316,6 +367,10 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
                // we must have a method (not a field of matching function type)
                f, _ := obj.(*Func)
                if f == nil {
+                       // if m is the magic method == and V is comparable, we're ok
+                       if m.name == "==" && Comparable(V) {
+                               continue
+                       }
                        return m, nil
                }
 
@@ -324,7 +379,41 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
                        check.objDecl(f, nil)
                }
 
-               if !check.identical(f.typ, m.typ) {
+               // both methods must have the same number of type parameters
+               ftyp := f.typ.(*Signature)
+               mtyp := m.typ.(*Signature)
+               if len(ftyp.tparams) != len(mtyp.tparams) {
+                       return m, f
+               }
+
+               // If V is a (instantiated) generic type, its methods are still
+               // parameterized using the original (declaration) receiver type
+               // parameters (subst simply copies the existing method list, it
+               // does not instantiate the methods).
+               // In order to compare the signatures, substitute the receiver
+               // type parameters of ftyp with V's instantiation type arguments.
+               // This lazily instantiates the signature of method f.
+               if Vn != nil && len(Vn.tparams) > 0 {
+                       // Be careful: The number of type arguments may not match
+                       // the number of receiver parameters. If so, an error was
+                       // reported earlier but the length discrepancy is still
+                       // here. Exit early in this case to prevent an assertion
+                       // failure in makeSubstMap.
+                       // TODO(gri) Can we avoid this check by fixing the lengths?
+                       if len(ftyp.rparams) != len(Vn.targs) {
+                               return
+                       }
+                       ftyp = check.subst(token.NoPos, ftyp, makeSubstMap(ftyp.rparams, Vn.targs)).(*Signature)
+               }
+
+               // If the methods have type parameters we don't care whether they
+               // are the same or not, as long as they match up. Use unification
+               // to see if they can be made to match.
+               // TODO(gri) is this always correct? what about type bounds?
+               // (Alternative is to rename/subst type parameters and compare.)
+               u := newUnifier(check, true)
+               u.x.init(ftyp.tparams)
+               if !u.unify(ftyp, mtyp) {
                        return m, f
                }
        }
@@ -337,11 +426,13 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
 // method required by V and whether it is missing or just has the wrong type.
 // The receiver may be nil if assertableTo is invoked through an exported API call
 // (such as AssertableTo), i.e., when all methods have been type-checked.
+// If the global constant forceStrict is set, assertions that are known to fail
+// are not permitted.
 func (check *Checker) assertableTo(V *Interface, T Type) (method, wrongType *Func) {
        // no static check is required if T is an interface
        // spec: "If T is an interface type, x.(T) asserts that the
        //        dynamic type of x implements the interface T."
-       if _, ok := T.Underlying().(*Interface); ok && !strict {
+       if asInterface(T) != nil && !forceStrict {
                return
        }
        return check.missingMethod(T, V, false)
@@ -359,8 +450,8 @@ func deref(typ Type) (Type, bool) {
 // derefStructPtr dereferences typ if it is a (named or unnamed) pointer to a
 // (named or unnamed) struct and returns its base. Otherwise it returns typ.
 func derefStructPtr(typ Type) Type {
-       if p, _ := typ.Underlying().(*Pointer); p != nil {
-               if _, ok := p.base.Underlying().(*Struct); ok {
+       if p := asPointer(typ); p != nil {
+               if asStruct(p.base) != nil {
                        return p.base
                }
        }
index c34d732b7ac36494427b329301397dbb7f848a2c..ae8011a2eeef92f8246631d13cf24d1cc5780504 100644 (file)
@@ -63,7 +63,7 @@ func (s *MethodSet) Lookup(pkg *Package, name string) *Selection {
 var emptyMethodSet MethodSet
 
 // Note: NewMethodSet is intended for external use only as it
-//       requires interfaces to be complete. If may be used
+//       requires interfaces to be complete. It may be used
 //       internally if LookupFieldOrMethod completed the same
 //       interfaces beforehand.
 
@@ -73,6 +73,9 @@ func NewMethodSet(T Type) *MethodSet {
        // WARNING: The code in this function is extremely subtle - do not modify casually!
        //          This function and lookupFieldOrMethod should be kept in sync.
 
+       // TODO(rfindley) confirm that this code is in sync with lookupFieldOrMethod
+       //                with respect to type params.
+
        // method set up to the current depth, allocated lazily
        var base methodSet
 
@@ -108,7 +111,7 @@ func NewMethodSet(T Type) *MethodSet {
 
                        // If we have a named type, we may have associated methods.
                        // Look for those first.
-                       if named, _ := typ.(*Named); named != nil {
+                       if named := asNamed(typ); named != nil {
                                if seen[named] {
                                        // We have seen this type before, at a more shallow depth
                                        // (note that multiples of this type at the current depth
@@ -124,8 +127,12 @@ func NewMethodSet(T Type) *MethodSet {
 
                                mset = mset.add(named.methods, e.index, e.indirect, e.multiples)
 
-                               // continue with underlying type
+                               // continue with underlying type, but only if it's not a type parameter
+                               // TODO(rFindley): should this use named.under()? Can there be a difference?
                                typ = named.underlying
+                               if _, ok := typ.(*_TypeParam); ok {
+                                       continue
+                               }
                        }
 
                        switch t := typ.(type) {
@@ -151,6 +158,9 @@ func NewMethodSet(T Type) *MethodSet {
 
                        case *Interface:
                                mset = mset.add(t.allMethods, e.index, true, e.multiples)
+
+                       case *_TypeParam:
+                               mset = mset.add(t.Bound().allMethods, e.index, true, e.multiples)
                        }
                }
 
diff --git a/libgo/go/go/types/methodset_test.go b/libgo/go/go/types/methodset_test.go
new file mode 100644 (file)
index 0000000..4a373fa
--- /dev/null
@@ -0,0 +1,109 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types_test
+
+import (
+       "testing"
+
+       "go/internal/typeparams"
+       . "go/types"
+)
+
+func TestNewMethodSet(t *testing.T) {
+       type method struct {
+               name     string
+               index    []int
+               indirect bool
+       }
+
+       // Tests are expressed src -> methods, for simplifying the composite literal.
+       // Should be kept in sync with TestLookupFieldOrMethod.
+       tests := map[string][]method{
+               // Named types
+               "var a T; type T struct{}; func (T) f() {}":   {{"f", []int{0}, false}},
+               "var a *T; type T struct{}; func (T) f() {}":  {{"f", []int{0}, true}},
+               "var a T; type T struct{}; func (*T) f() {}":  {},
+               "var a *T; type T struct{}; func (*T) f() {}": {{"f", []int{0}, true}},
+
+               // Interfaces
+               "var a T; type T interface{ f() }":                           {{"f", []int{0}, true}},
+               "var a T1; type ( T1 T2; T2 interface{ f() } )":              {{"f", []int{0}, true}},
+               "var a T1; type ( T1 interface{ T2 }; T2 interface{ f() } )": {{"f", []int{0}, true}},
+
+               // Embedding
+               "var a struct{ E }; type E interface{ f() }":            {{"f", []int{0, 0}, true}},
+               "var a *struct{ E }; type E interface{ f() }":           {{"f", []int{0, 0}, true}},
+               "var a struct{ E }; type E struct{}; func (E) f() {}":   {{"f", []int{0, 0}, false}},
+               "var a struct{ *E }; type E struct{}; func (E) f() {}":  {{"f", []int{0, 0}, true}},
+               "var a struct{ E }; type E struct{}; func (*E) f() {}":  {},
+               "var a struct{ *E }; type E struct{}; func (*E) f() {}": {{"f", []int{0, 0}, true}},
+
+               // collisions
+               "var a struct{ E1; *E2 }; type ( E1 interface{ f() }; E2 struct{ f int })":            {},
+               "var a struct{ E1; *E2 }; type ( E1 struct{ f int }; E2 struct{} ); func (E2) f() {}": {},
+       }
+
+       genericTests := map[string][]method{
+               // By convention, look up a in the scope of "g"
+               "type C interface{ f() }; func g[T C](a T){}":                       {{"f", []int{0}, true}},
+               "type C interface{ f() }; func g[T C]() { var a T; _ = a }":         {{"f", []int{0}, true}},
+               "type C interface{ f() }; func g[T C]() { var a struct{T}; _ = a }": {{"f", []int{0, 0}, true}},
+
+               // Issue #45639.
+               "type C interface{ f() }; func g[T C]() { type Y T; var a Y; _ = a }": {},
+       }
+
+       check := func(src string, methods []method, generic bool) {
+               pkgName := "p"
+               if generic {
+                       // The generic_ prefix causes pkgFor to allow generic code.
+                       pkgName = "generic_p"
+               }
+               pkg, err := pkgFor("test", "package "+pkgName+";"+src, nil)
+               if err != nil {
+                       t.Errorf("%s: incorrect test case: %s", src, err)
+                       return
+               }
+
+               scope := pkg.Scope()
+               if generic {
+                       fn := pkg.Scope().Lookup("g").(*Func)
+                       scope = fn.Scope()
+               }
+               obj := scope.Lookup("a")
+               if obj == nil {
+                       t.Errorf("%s: incorrect test case - no object a", src)
+                       return
+               }
+
+               ms := NewMethodSet(obj.Type())
+               if got, want := ms.Len(), len(methods); got != want {
+                       t.Errorf("%s: got %d methods, want %d", src, got, want)
+                       return
+               }
+               for i, m := range methods {
+                       sel := ms.At(i)
+                       if got, want := sel.Obj().Name(), m.name; got != want {
+                               t.Errorf("%s [method %d]: got name = %q at, want %q", src, i, got, want)
+                       }
+                       if got, want := sel.Index(), m.index; !sameSlice(got, want) {
+                               t.Errorf("%s [method %d]: got index = %v, want %v", src, i, got, want)
+                       }
+                       if got, want := sel.Indirect(), m.indirect; got != want {
+                               t.Errorf("%s [method %d]: got indirect = %v, want %v", src, i, got, want)
+                       }
+               }
+       }
+
+       for src, methods := range tests {
+               check(src, methods, false)
+       }
+
+       if typeparams.Enabled {
+               for src, methods := range genericTests {
+                       check(src, methods, true)
+               }
+       }
+}
index 374b24d1acfa03e47da92ba7dd49f9e5297db13c..50346ec6919407e41e730b09c849a324938b18de 100644 (file)
@@ -36,6 +36,9 @@ type Object interface {
        // color returns the object's color.
        color() color
 
+       // setType sets the type of the object.
+       setType(Type)
+
        // setOrder sets the order number of the object. It must be > 0.
        setOrder(uint32)
 
@@ -149,6 +152,7 @@ func (obj *object) color() color        { return obj.color_ }
 func (obj *object) scopePos() token.Pos { return obj.scopePos_ }
 
 func (obj *object) setParent(parent *Scope)   { obj.parent = parent }
+func (obj *object) setType(typ Type)          { obj.typ = typ }
 func (obj *object) setOrder(order uint32)     { assert(order > 0); obj.order_ = order }
 func (obj *object) setColor(color color)      { assert(color != white); obj.color_ = color }
 func (obj *object) setScopePos(pos token.Pos) { obj.scopePos_ = pos }
@@ -299,7 +303,7 @@ type Func struct {
 // NewFunc returns a new function with the given signature, representing
 // the function's type.
 func NewFunc(pos token.Pos, pkg *Package, name string, sig *Signature) *Func {
-       // don't store a nil signature
+       // don't store a (typed) nil signature
        var typ Type
        if sig != nil {
                typ = sig
@@ -420,7 +424,7 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) {
                if tname.IsAlias() {
                        buf.WriteString(" =")
                } else {
-                       typ = typ.Underlying()
+                       typ = under(typ)
                }
        }
 
index 3e1ac312d9a5e46d33c1518c3f5cefbd9eb0198e..6463728cec6a37b9308fa8853663104deaa2ed90 100644 (file)
@@ -158,7 +158,16 @@ func operandString(x *operand, qf Qualifier) string {
        // <typ>
        if hasType {
                if x.typ != Typ[Invalid] {
-                       buf.WriteString(" of type ")
+                       var intro string
+                       switch {
+                       case isGeneric(x.typ):
+                               intro = " of generic type "
+                       case asTypeParam(x.typ) != nil:
+                               intro = " of type parameter type "
+                       default:
+                               intro = " of type "
+                       }
+                       buf.WriteString(intro)
                        WriteType(&buf, x.typ, qf)
                } else {
                        buf.WriteString(" with invalid type")
@@ -213,9 +222,10 @@ func (x *operand) isNil() bool {
 
 // assignableTo reports whether x is assignable to a variable of type T. If the
 // result is false and a non-nil reason is provided, it may be set to a more
-// detailed explanation of the failure (result != ""). The check parameter may
-// be nil if assignableTo is invoked through an exported API call, i.e., when
-// all methods have been type-checked.
+// detailed explanation of the failure (result != ""). The returned error code
+// is only valid if the (first) result is false. The check parameter may be nil
+// if assignableTo is invoked through an exported API call, i.e., when all
+// methods have been type-checked.
 func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, errorCode) {
        if x.mode == invalid || T == Typ[Invalid] {
                return true, 0 // avoid spurious errors
@@ -228,20 +238,25 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
                return true, 0
        }
 
-       Vu := V.Underlying()
-       Tu := T.Underlying()
+       Vu := optype(V)
+       Tu := optype(T)
 
        // x is an untyped value representable by a value of type T.
        if isUntyped(Vu) {
-               if t, ok := Tu.(*Basic); ok && x.mode == constant_ {
-                       return representableConst(x.val, check, t, nil), _IncompatibleAssign
+               if t, ok := Tu.(*_Sum); ok {
+                       return t.is(func(t Type) bool {
+                               // TODO(gri) this could probably be more efficient
+                               ok, _ := x.assignableTo(check, t, reason)
+                               return ok
+                       }), _IncompatibleAssign
                }
-               return check.implicitType(x, Tu) != nil, _IncompatibleAssign
+               newType, _, _ := check.implicitTypeAndValue(x, Tu)
+               return newType != nil, _IncompatibleAssign
        }
        // Vu is typed
 
-       // x's type V and T have identical underlying types and at least one of V or
-       // T is not a named type.
+       // x's type V and T have identical underlying types
+       // and at least one of V or T is not a named type
        if check.identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) {
                return true, 0
        }
@@ -271,11 +286,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
        // and at least one of V or T is not a named type
        if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv {
                if Tc, ok := Tu.(*Chan); ok && check.identical(Vc.elem, Tc.elem) {
-                       if !isNamed(V) || !isNamed(T) {
-                               return true, 0
-                       } else {
-                               return false, _InvalidChanAssign
-                       }
+                       return !isNamed(V) || !isNamed(T), _InvalidChanAssign
                }
        }
 
index 148edbfb767a47d642077d1dbe2c42ed692779f4..7bb026414f8c36366b47cf164236662dbe5e9dc9 100644 (file)
@@ -6,75 +6,84 @@
 
 package types
 
-import "sort"
+import (
+       "go/token"
+)
 
+// isNamed reports whether typ has a name.
+// isNamed may be called with types that are not fully set up.
 func isNamed(typ Type) bool {
-       if _, ok := typ.(*Basic); ok {
-               return ok
+       switch typ.(type) {
+       case *Basic, *Named, *_TypeParam, *instance:
+               return true
        }
-       _, ok := typ.(*Named)
-       return ok
-}
-
-func isBoolean(typ Type) bool {
-       t, ok := typ.Underlying().(*Basic)
-       return ok && t.info&IsBoolean != 0
-}
-
-func isInteger(typ Type) bool {
-       t, ok := typ.Underlying().(*Basic)
-       return ok && t.info&IsInteger != 0
-}
-
-func isUnsigned(typ Type) bool {
-       t, ok := typ.Underlying().(*Basic)
-       return ok && t.info&IsUnsigned != 0
-}
-
-func isFloat(typ Type) bool {
-       t, ok := typ.Underlying().(*Basic)
-       return ok && t.info&IsFloat != 0
-}
-
-func isComplex(typ Type) bool {
-       t, ok := typ.Underlying().(*Basic)
-       return ok && t.info&IsComplex != 0
+       return false
 }
 
-func isNumeric(typ Type) bool {
-       t, ok := typ.Underlying().(*Basic)
-       return ok && t.info&IsNumeric != 0
+// isGeneric reports whether a type is a generic, uninstantiated type (generic
+// signatures are not included).
+func isGeneric(typ Type) bool {
+       // A parameterized type is only instantiated if it doesn't have an instantiation already.
+       named, _ := typ.(*Named)
+       return named != nil && named.obj != nil && named.tparams != nil && named.targs == nil
 }
 
-func isString(typ Type) bool {
-       t, ok := typ.Underlying().(*Basic)
-       return ok && t.info&IsString != 0
+func is(typ Type, what BasicInfo) bool {
+       switch t := optype(typ).(type) {
+       case *Basic:
+               return t.info&what != 0
+       case *_Sum:
+               return t.is(func(typ Type) bool { return is(typ, what) })
+       }
+       return false
 }
 
+func isBoolean(typ Type) bool  { return is(typ, IsBoolean) }
+func isInteger(typ Type) bool  { return is(typ, IsInteger) }
+func isUnsigned(typ Type) bool { return is(typ, IsUnsigned) }
+func isFloat(typ Type) bool    { return is(typ, IsFloat) }
+func isComplex(typ Type) bool  { return is(typ, IsComplex) }
+func isNumeric(typ Type) bool  { return is(typ, IsNumeric) }
+func isString(typ Type) bool   { return is(typ, IsString) }
+
+// Note that if typ is a type parameter, isInteger(typ) || isFloat(typ) does not
+// produce the expected result because a type list that contains both an integer
+// and a floating-point type is neither (all) integers, nor (all) floats.
+// Use isIntegerOrFloat instead.
+func isIntegerOrFloat(typ Type) bool { return is(typ, IsInteger|IsFloat) }
+
+// isNumericOrString is the equivalent of isIntegerOrFloat for isNumeric(typ) || isString(typ).
+func isNumericOrString(typ Type) bool { return is(typ, IsNumeric|IsString) }
+
+// isTyped reports whether typ is typed; i.e., not an untyped
+// constant or boolean. isTyped may be called with types that
+// are not fully set up.
 func isTyped(typ Type) bool {
-       t, ok := typ.Underlying().(*Basic)
-       return !ok || t.info&IsUntyped == 0
+       // isTyped is called with types that are not fully
+       // set up. Must not call asBasic()!
+       // A *Named or *instance type is always typed, so
+       // we only need to check if we have a true *Basic
+       // type.
+       t, _ := typ.(*Basic)
+       return t == nil || t.info&IsUntyped == 0
 }
 
+// isUntyped(typ) is the same as !isTyped(typ).
 func isUntyped(typ Type) bool {
-       t, ok := typ.Underlying().(*Basic)
-       return ok && t.info&IsUntyped != 0
+       return !isTyped(typ)
 }
 
-func isOrdered(typ Type) bool {
-       t, ok := typ.Underlying().(*Basic)
-       return ok && t.info&IsOrdered != 0
-}
+func isOrdered(typ Type) bool { return is(typ, IsOrdered) }
 
 func isConstType(typ Type) bool {
-       t, ok := typ.Underlying().(*Basic)
-       return ok && t.info&IsConstType != 0
+       // Type parameters are never const types.
+       t, _ := under(typ).(*Basic)
+       return t != nil && t.info&IsConstType != 0
 }
 
 // IsInterface reports whether typ is an interface type.
 func IsInterface(typ Type) bool {
-       _, ok := typ.Underlying().(*Interface)
-       return ok
+       return asInterface(typ) != nil
 }
 
 // Comparable reports whether values of type T are comparable.
@@ -91,7 +100,19 @@ func comparable(T Type, seen map[Type]bool) bool {
        }
        seen[T] = true
 
-       switch t := T.Underlying().(type) {
+       // If T is a type parameter not constrained by any type
+       // list (i.e., it's underlying type is the top type),
+       // T is comparable if it has the == method. Otherwise,
+       // the underlying type "wins". For instance
+       //
+       //     interface{ comparable; type []byte }
+       //
+       // is not comparable because []byte is not comparable.
+       if t := asTypeParam(T); t != nil && optype(t) == theTop {
+               return t.Bound()._IsComparable()
+       }
+
+       switch t := optype(T).(type) {
        case *Basic:
                // assume invalid types to be comparable
                // to avoid follow-up errors
@@ -107,17 +128,26 @@ func comparable(T Type, seen map[Type]bool) bool {
                return true
        case *Array:
                return comparable(t.elem, seen)
+       case *_Sum:
+               pred := func(t Type) bool {
+                       return comparable(t, seen)
+               }
+               return t.is(pred)
+       case *_TypeParam:
+               return t.Bound()._IsComparable()
        }
        return false
 }
 
 // hasNil reports whether a type includes the nil value.
 func hasNil(typ Type) bool {
-       switch t := typ.Underlying().(type) {
+       switch t := optype(typ).(type) {
        case *Basic:
                return t.kind == UnsafePointer
        case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan:
                return true
+       case *_Sum:
+               return t.is(hasNil)
        }
        return false
 }
@@ -144,7 +174,12 @@ func (p *ifacePair) identical(q *ifacePair) bool {
        return p.x == q.x && p.y == q.y || p.x == q.y && p.y == q.x
 }
 
+// For changes to this code the corresponding changes should be made to unifier.nify.
 func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool {
+       // types must be expanded for comparison
+       x = expandf(x)
+       y = expandf(y)
+
        if x == y {
                return true
        }
@@ -221,12 +256,38 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool {
                // and result values, corresponding parameter and result types are identical,
                // and either both functions are variadic or neither is. Parameter and result
                // names are not required to match.
+               // Generic functions must also have matching type parameter lists, but for the
+               // parameter names.
                if y, ok := y.(*Signature); ok {
                        return x.variadic == y.variadic &&
+                               check.identicalTParams(x.tparams, y.tparams, cmpTags, p) &&
                                check.identical0(x.params, y.params, cmpTags, p) &&
                                check.identical0(x.results, y.results, cmpTags, p)
                }
 
+       case *_Sum:
+               // Two sum types are identical if they contain the same types.
+               // (Sum types always consist of at least two types. Also, the
+               // the set (list) of types in a sum type consists of unique
+               // types - each type appears exactly once. Thus, two sum types
+               // must contain the same number of types to have chance of
+               // being equal.
+               if y, ok := y.(*_Sum); ok && len(x.types) == len(y.types) {
+                       // Every type in x.types must be in y.types.
+                       // Quadratic algorithm, but probably good enough for now.
+                       // TODO(gri) we need a fast quick type ID/hash for all types.
+               L:
+                       for _, x := range x.types {
+                               for _, y := range y.types {
+                                       if Identical(x, y) {
+                                               continue L // x is in y.types
+                                       }
+                               }
+                               return false // x is not in y.types
+                       }
+                       return true
+               }
+
        case *Interface:
                // Two interface types are identical if they have the same set of methods with
                // the same names and identical function types. Lower-case method names from
@@ -237,8 +298,8 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool {
                        // that case, interfaces are expected to be complete and lazy completion
                        // here is not needed.
                        if check != nil {
-                               check.completeInterface(x)
-                               check.completeInterface(y)
+                               check.completeInterface(token.NoPos, x)
+                               check.completeInterface(token.NoPos, y)
                        }
                        a := x.allMethods
                        b := y.allMethods
@@ -273,8 +334,8 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool {
                                        p = p.prev
                                }
                                if debug {
-                                       assert(sort.IsSorted(byUniqueMethodName(a)))
-                                       assert(sort.IsSorted(byUniqueMethodName(b)))
+                                       assertSortedMethods(a)
+                                       assertSortedMethods(b)
                                }
                                for i, f := range a {
                                        g := b[i]
@@ -303,10 +364,25 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool {
                // Two named types are identical if their type names originate
                // in the same type declaration.
                if y, ok := y.(*Named); ok {
+                       // TODO(gri) Why is x == y not sufficient? And if it is,
+                       //           we can just return false here because x == y
+                       //           is caught in the very beginning of this function.
                        return x.obj == y.obj
                }
 
+       case *_TypeParam:
+               // nothing to do (x and y being equal is caught in the very beginning of this function)
+
+       // case *instance:
+       //      unreachable since types are expanded
+
+       case *bottom, *top:
+               // Either both types are theBottom, or both are theTop in which
+               // case the initial x == y check will have caught them. Otherwise
+               // they are not identical.
+
        case nil:
+               // avoid a crash in case of nil type
 
        default:
                unreachable()
@@ -315,6 +391,19 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool {
        return false
 }
 
+func (check *Checker) identicalTParams(x, y []*TypeName, cmpTags bool, p *ifacePair) bool {
+       if len(x) != len(y) {
+               return false
+       }
+       for i, x := range x {
+               y := y[i]
+               if !check.identical0(x.typ.(*_TypeParam).bound, y.typ.(*_TypeParam).bound, cmpTags, p) {
+                       return false
+               }
+       }
+       return true
+}
+
 // Default returns the default "typed" type for an "untyped" type;
 // it returns the incoming type for all other types. The default type
 // for untyped nil is untyped nil.
index b637f8b8cacf75793f564660081bc0c741daab1f..114647a2fffecb937bd785c3d85e3467626499a4 100644 (file)
@@ -8,6 +8,7 @@ import (
        "fmt"
        "go/ast"
        "go/constant"
+       "go/internal/typeparams"
        "go/token"
        "sort"
        "strconv"
@@ -19,11 +20,11 @@ import (
 type declInfo struct {
        file      *Scope        // scope of file containing this declaration
        lhs       []*Var        // lhs of n:1 variable declarations, or nil
-       typ       ast.Expr      // type, or nil
-       init      ast.Expr      // init/orig expression, or nil
+       vtyp      ast.Expr      // type, or nil (for const and var declarations only)
+       init      ast.Expr      // init/orig expression, or nil (for const and var declarations only)
        inherited bool          // if set, the init expression is inherited from a previous constant declaration
+       tdecl     *ast.TypeSpec // type declaration, or nil
        fdecl     *ast.FuncDecl // func declaration, or nil
-       alias     bool          // type alias declaration
 
        // The deps field tracks initialization expression dependencies.
        deps map[Object]bool // lazily initialized
@@ -130,7 +131,7 @@ func (check *Checker) filename(fileNo int) string {
        return fmt.Sprintf("file[%d]", fileNo)
 }
 
-func (check *Checker) importPackage(pos token.Pos, path, dir string) *Package {
+func (check *Checker) importPackage(at positioner, path, dir string) *Package {
        // If we already have a package for the given (path, dir)
        // pair, use it instead of doing a full import.
        // Checker.impMap only caches packages that are marked Complete
@@ -170,7 +171,7 @@ func (check *Checker) importPackage(pos token.Pos, path, dir string) *Package {
                        imp = nil // create fake package below
                }
                if err != nil {
-                       check.errorf(atPos(pos), _BrokenImport, "could not import %s (%s)", path, err)
+                       check.errorf(at, _BrokenImport, "could not import %s (%s)", path, err)
                        if imp == nil {
                                // create a new fake package
                                // come up with a sensible package name (heuristic)
@@ -191,7 +192,11 @@ func (check *Checker) importPackage(pos token.Pos, path, dir string) *Package {
        // package should be complete or marked fake, but be cautious
        if imp.complete || imp.fake {
                check.impMap[key] = imp
-               check.pkgCnt[imp.name]++
+               // Once we've formatted an error message once, keep the pkgPathMap
+               // up-to-date on subsequent imports.
+               if check.pkgPathMap != nil {
+                       check.markImports(imp)
+               }
                return imp
        }
 
@@ -216,7 +221,13 @@ func (check *Checker) collectObjects() {
                pkgImports[imp] = true
        }
 
-       var methods []*Func // list of methods with non-blank _ names
+       type methodInfo struct {
+               obj  *Func      // method
+               ptr  bool       // true if pointer receiver
+               recv *ast.Ident // receiver type name
+       }
+       var methods []methodInfo // collected methods with valid receivers and non-blank _ names
+       var fileScopes []*Scope
        for fileNo, file := range check.files {
                // The package identifier denotes the current package,
                // but there is no corresponding package object.
@@ -230,6 +241,7 @@ func (check *Checker) collectObjects() {
                        pos, end = token.Pos(f.Base()), token.Pos(f.Base()+f.Size())
                }
                fileScope := NewScope(check.pkg.scope, pos, end, check.filename(fileNo))
+               fileScopes = append(fileScopes, fileScope)
                check.recordScope(file, fileScope)
 
                // determine file directory, necessary to resolve imports
@@ -247,19 +259,11 @@ func (check *Checker) collectObjects() {
                                        return
                                }
 
-                               imp := check.importPackage(d.spec.Path.Pos(), path, fileDir)
+                               imp := check.importPackage(d.spec.Path, path, fileDir)
                                if imp == nil {
                                        return
                                }
 
-                               // add package to list of explicit imports
-                               // (this functionality is provided as a convenience
-                               // for clients; it is not needed for type-checking)
-                               if !pkgImports[imp] {
-                                       pkgImports[imp] = true
-                                       pkg.imports = append(pkg.imports, imp)
-                               }
-
                                // local name overrides imported package name
                                name := imp.name
                                if d.spec.Name != nil {
@@ -269,27 +273,41 @@ func (check *Checker) collectObjects() {
                                                check.errorf(d.spec.Name, _ImportCRenamed, `cannot rename import "C"`)
                                                return
                                        }
-                                       if name == "init" {
-                                               check.errorf(d.spec.Name, _InvalidInitDecl, "cannot declare init - must be func")
-                                               return
-                                       }
                                }
 
-                               obj := NewPkgName(d.spec.Pos(), pkg, name, imp)
+                               if name == "init" {
+                                       check.errorf(d.spec.Name, _InvalidInitDecl, "cannot import package as init - init must be a func")
+                                       return
+                               }
+
+                               // add package to list of explicit imports
+                               // (this functionality is provided as a convenience
+                               // for clients; it is not needed for type-checking)
+                               if !pkgImports[imp] {
+                                       pkgImports[imp] = true
+                                       pkg.imports = append(pkg.imports, imp)
+                               }
+
+                               pkgName := NewPkgName(d.spec.Pos(), pkg, name, imp)
                                if d.spec.Name != nil {
                                        // in a dot-import, the dot represents the package
-                                       check.recordDef(d.spec.Name, obj)
+                                       check.recordDef(d.spec.Name, pkgName)
                                } else {
-                                       check.recordImplicit(d.spec, obj)
+                                       check.recordImplicit(d.spec, pkgName)
                                }
 
                                if path == "C" {
                                        // match cmd/compile (not prescribed by spec)
-                                       obj.used = true
+                                       pkgName.used = true
                                }
 
                                // add import to file scope
+                               check.imports = append(check.imports, pkgName)
                                if name == "." {
+                                       // dot-import
+                                       if check.dotImportMap == nil {
+                                               check.dotImportMap = make(map[dotImportKey]*PkgName)
+                                       }
                                        // merge imported scope with file scope
                                        for _, obj := range imp.scope.elems {
                                                // A package scope may contain non-exported objects,
@@ -303,16 +321,15 @@ func (check *Checker) collectObjects() {
                                                        if alt := fileScope.Insert(obj); alt != nil {
                                                                check.errorf(d.spec.Name, _DuplicateDecl, "%s redeclared in this block", obj.Name())
                                                                check.reportAltDecl(alt)
+                                                       } else {
+                                                               check.dotImportMap[dotImportKey{fileScope, obj}] = pkgName
                                                        }
                                                }
                                        }
-                                       // add position to set of dot-import positions for this file
-                                       // (this is only needed for "imported but not used" errors)
-                                       check.addUnusedDotImport(fileScope, imp, d.spec)
                                } else {
                                        // declare imported package object in file scope
                                        // (no need to provide s.Name since we called check.recordDef earlier)
-                                       check.declare(fileScope, nil, obj, token.NoPos)
+                                       check.declare(fileScope, nil, pkgName, token.NoPos)
                                }
                        case constDecl:
                                // declare all constants
@@ -324,7 +341,7 @@ func (check *Checker) collectObjects() {
                                                init = d.init[i]
                                        }
 
-                                       d := &declInfo{file: fileScope, typ: d.typ, init: init, inherited: d.inherited}
+                                       d := &declInfo{file: fileScope, vtyp: d.typ, init: init, inherited: d.inherited}
                                        check.declarePkgObj(name, obj, d)
                                }
 
@@ -339,7 +356,7 @@ func (check *Checker) collectObjects() {
                                        // The lhs elements are only set up after the for loop below,
                                        // but that's ok because declareVar only collects the declInfo
                                        // for a later phase.
-                                       d1 = &declInfo{file: fileScope, lhs: lhs, typ: d.spec.Type, init: d.spec.Values[0]}
+                                       d1 = &declInfo{file: fileScope, lhs: lhs, vtyp: d.spec.Type, init: d.spec.Values[0]}
                                }
 
                                // declare all variables
@@ -354,26 +371,44 @@ func (check *Checker) collectObjects() {
                                                if i < len(d.spec.Values) {
                                                        init = d.spec.Values[i]
                                                }
-                                               di = &declInfo{file: fileScope, typ: d.spec.Type, init: init}
+                                               di = &declInfo{file: fileScope, vtyp: d.spec.Type, init: init}
                                        }
 
                                        check.declarePkgObj(name, obj, di)
                                }
                        case typeDecl:
                                obj := NewTypeName(d.spec.Name.Pos(), pkg, d.spec.Name.Name, nil)
-                               check.declarePkgObj(d.spec.Name, obj, &declInfo{file: fileScope, typ: d.spec.Type, alias: d.spec.Assign.IsValid()})
+                               check.declarePkgObj(d.spec.Name, obj, &declInfo{file: fileScope, tdecl: d.spec})
                        case funcDecl:
                                info := &declInfo{file: fileScope, fdecl: d.decl}
                                name := d.decl.Name.Name
                                obj := NewFunc(d.decl.Name.Pos(), pkg, name, nil)
-                               if d.decl.Recv == nil {
+                               if d.decl.Recv.NumFields() == 0 {
                                        // regular function
+                                       if d.decl.Recv != nil {
+                                               check.error(d.decl.Recv, _BadRecv, "method is missing receiver")
+                                               // treat as function
+                                       }
+                                       if name == "init" || (name == "main" && check.pkg.name == "main") {
+                                               code := _InvalidInitDecl
+                                               if name == "main" {
+                                                       code = _InvalidMainDecl
+                                               }
+                                               if tparams := typeparams.Get(d.decl.Type); tparams != nil {
+                                                       check.softErrorf(tparams, code, "func %s must have no type parameters", name)
+                                               }
+                                               if t := d.decl.Type; t.Params.NumFields() != 0 || t.Results != nil {
+                                                       // TODO(rFindley) Should this be a hard error?
+                                                       check.softErrorf(d.decl, code, "func %s must have no arguments and no return values", name)
+                                               }
+                                       }
                                        if name == "init" {
                                                // don't declare init functions in the package scope - they are invisible
                                                obj.parent = pkg.scope
                                                check.recordDef(d.decl.Name, obj)
                                                // init functions must have a body
                                                if d.decl.Body == nil {
+                                                       // TODO(gri) make this error message consistent with the others above
                                                        check.softErrorf(obj, _MissingInitBody, "missing function body")
                                                }
                                        } else {
@@ -381,11 +416,18 @@ func (check *Checker) collectObjects() {
                                        }
                                } else {
                                        // method
-                                       // (Methods with blank _ names are never found; no need to collect
-                                       // them for later type association. They will still be type-checked
-                                       // with all the other functions.)
-                                       if name != "_" {
-                                               methods = append(methods, obj)
+
+                                       // TODO(rFindley) earlier versions of this code checked that methods
+                                       //                have no type parameters, but this is checked later
+                                       //                when type checking the function type. Confirm that
+                                       //                we don't need to check tparams here.
+
+                                       ptr, recv, _ := check.unpackRecv(d.decl.Recv.List[0].Type, false)
+                                       // (Methods with invalid receiver cannot be associated to a type, and
+                                       // methods with blank _ names are never found; no need to collect any
+                                       // of them. They will still be type-checked with all the other functions.)
+                                       if recv != nil && name != "_" {
+                                               methods = append(methods, methodInfo{obj, ptr, recv})
                                        }
                                        check.recordDef(d.decl.Name, obj)
                                }
@@ -400,7 +442,7 @@ func (check *Checker) collectObjects() {
        }
 
        // verify that objects in package and file scopes have different names
-       for _, scope := range check.pkg.scope.children /* file scopes */ {
+       for _, scope := range fileScopes {
                for _, obj := range scope.elems {
                        if alt := pkg.scope.Lookup(obj.Name()); alt != nil {
                                if pkg, ok := obj.(*PkgName); ok {
@@ -423,31 +465,84 @@ func (check *Checker) collectObjects() {
                return // nothing to do
        }
        check.methods = make(map[*TypeName][]*Func)
-       for _, f := range methods {
-               fdecl := check.objMap[f].fdecl
-               if list := fdecl.Recv.List; len(list) > 0 {
-                       // f is a method.
-                       // Determine the receiver base type and associate f with it.
-                       ptr, base := check.resolveBaseTypeName(list[0].Type)
-                       if base != nil {
-                               f.hasPtrRecv = ptr
-                               check.methods[base] = append(check.methods[base], f)
+       for i := range methods {
+               m := &methods[i]
+               // Determine the receiver base type and associate m with it.
+               ptr, base := check.resolveBaseTypeName(m.ptr, m.recv)
+               if base != nil {
+                       m.obj.hasPtrRecv = ptr
+                       check.methods[base] = append(check.methods[base], m.obj)
+               }
+       }
+}
+
+// unpackRecv unpacks a receiver type and returns its components: ptr indicates whether
+// rtyp is a pointer receiver, rname is the receiver type name, and tparams are its
+// type parameters, if any. The type parameters are only unpacked if unpackParams is
+// set. If rname is nil, the receiver is unusable (i.e., the source has a bug which we
+// cannot easily work around).
+func (check *Checker) unpackRecv(rtyp ast.Expr, unpackParams bool) (ptr bool, rname *ast.Ident, tparams []*ast.Ident) {
+L: // unpack receiver type
+       // This accepts invalid receivers such as ***T and does not
+       // work for other invalid receivers, but we don't care. The
+       // validity of receiver expressions is checked elsewhere.
+       for {
+               switch t := rtyp.(type) {
+               case *ast.ParenExpr:
+                       rtyp = t.X
+               case *ast.StarExpr:
+                       ptr = true
+                       rtyp = t.X
+               default:
+                       break L
+               }
+       }
+
+       // unpack type parameters, if any
+       if ptyp, _ := rtyp.(*ast.IndexExpr); ptyp != nil {
+               rtyp = ptyp.X
+               if unpackParams {
+                       for _, arg := range typeparams.UnpackExpr(ptyp.Index) {
+                               var par *ast.Ident
+                               switch arg := arg.(type) {
+                               case *ast.Ident:
+                                       par = arg
+                               case *ast.BadExpr:
+                                       // ignore - error already reported by parser
+                               case nil:
+                                       check.invalidAST(ptyp, "parameterized receiver contains nil parameters")
+                               default:
+                                       check.errorf(arg, _Todo, "receiver type parameter %s must be an identifier", arg)
+                               }
+                               if par == nil {
+                                       par = &ast.Ident{NamePos: arg.Pos(), Name: "_"}
+                               }
+                               tparams = append(tparams, par)
                        }
                }
        }
+
+       // unpack receiver name
+       if name, _ := rtyp.(*ast.Ident); name != nil {
+               rname = name
+       }
+
+       return
 }
 
 // resolveBaseTypeName returns the non-alias base type name for typ, and whether
 // there was a pointer indirection to get to it. The base type name must be declared
 // in package scope, and there can be at most one pointer indirection. If no such type
 // name exists, the returned base is nil.
-func (check *Checker) resolveBaseTypeName(typ ast.Expr) (ptr bool, base *TypeName) {
+func (check *Checker) resolveBaseTypeName(seenPtr bool, name *ast.Ident) (ptr bool, base *TypeName) {
        // Algorithm: Starting from a type expression, which may be a name,
        // we follow that type through alias declarations until we reach a
        // non-alias type name. If we encounter anything but pointer types or
        // parentheses we're done. If we encounter more than one pointer type
        // we're done.
+       ptr = seenPtr
        var seen map[*TypeName]bool
+       var typ ast.Expr = name
        for {
                typ = unparen(typ)
 
@@ -487,13 +582,13 @@ func (check *Checker) resolveBaseTypeName(typ ast.Expr) (ptr bool, base *TypeNam
 
                // we're done if tdecl defined tname as a new type
                // (rather than an alias)
-               tdecl := check.objMap[tname] // must exist for objects in package scope
-               if !tdecl.alias {
+               tdecl := check.objMap[tname].tdecl // must exist for objects in package scope
+               if !tdecl.Assign.IsValid() {
                        return ptr, tname
                }
 
                // otherwise, continue resolving
-               typ = tdecl.typ
+               typ = tdecl.Type
                if seen == nil {
                        seen = make(map[*TypeName]bool)
                }
@@ -515,7 +610,7 @@ func (check *Checker) packageObjects() {
        // add new methods to already type-checked types (from a prior Checker.Files call)
        for _, obj := range objList {
                if obj, _ := obj.(*TypeName); obj != nil && obj.typ != nil {
-                       check.addMethodDecls(obj)
+                       check.collectMethods(obj)
                }
        }
 
@@ -529,7 +624,7 @@ func (check *Checker) packageObjects() {
        // phase 1
        for _, obj := range objList {
                // If we have a type alias, collect it for the 2nd phase.
-               if tname, _ := obj.(*TypeName); tname != nil && check.objMap[tname].alias {
+               if tname, _ := obj.(*TypeName); tname != nil && check.objMap[tname].tdecl.Assign.IsValid() {
                        aliasList = append(aliasList, tname)
                        continue
                }
@@ -566,39 +661,30 @@ func (check *Checker) unusedImports() {
        // any of its exported identifiers. To import a package solely for its side-effects
        // (initialization), use the blank identifier as explicit package name."
 
-       // check use of regular imported packages
-       for _, scope := range check.pkg.scope.children /* file scopes */ {
-               for _, obj := range scope.elems {
-                       if obj, ok := obj.(*PkgName); ok {
-                               // Unused "blank imports" are automatically ignored
-                               // since _ identifiers are not entered into scopes.
-                               if !obj.used {
-                                       path := obj.imported.path
-                                       base := pkgName(path)
-                                       if obj.name == base {
-                                               check.softErrorf(obj, _UnusedImport, "%q imported but not used", path)
-                                       } else {
-                                               check.softErrorf(obj, _UnusedImport, "%q imported but not used as %s", path, obj.name)
-                                       }
-                               }
-                       }
-               }
-       }
-
-       // check use of dot-imported packages
-       for _, unusedDotImports := range check.unusedDotImports {
-               for pkg, pos := range unusedDotImports {
-                       check.softErrorf(pos, _UnusedImport, "%q imported but not used", pkg.path)
+       for _, obj := range check.imports {
+               if !obj.used && obj.name != "_" {
+                       check.errorUnusedPkg(obj)
                }
        }
 }
 
-// pkgName returns the package name (last element) of an import path.
-func pkgName(path string) string {
-       if i := strings.LastIndex(path, "/"); i >= 0 {
-               path = path[i+1:]
+func (check *Checker) errorUnusedPkg(obj *PkgName) {
+       // If the package was imported with a name other than the final
+       // import path element, show it explicitly in the error message.
+       // Note that this handles both renamed imports and imports of
+       // packages containing unconventional package declarations.
+       // Note that this uses / always, even on Windows, because Go import
+       // paths always use forward slashes.
+       path := obj.imported.path
+       elem := path
+       if i := strings.LastIndex(elem, "/"); i >= 0 {
+               elem = elem[i+1:]
+       }
+       if obj.name == "" || obj.name == "." || obj.name == elem {
+               check.softErrorf(obj, _UnusedImport, "%q imported but not used", path)
+       } else {
+               check.softErrorf(obj, _UnusedImport, "%q imported but not used as %s", path, obj.name)
        }
-       return path
 }
 
 // dir makes a good-faith attempt to return the directory
diff --git a/libgo/go/go/types/sanitize.go b/libgo/go/go/types/sanitize.go
new file mode 100644 (file)
index 0000000..727ec17
--- /dev/null
@@ -0,0 +1,206 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types
+
+// sanitizeInfo walks the types contained in info to ensure that all instances
+// are expanded.
+//
+// This includes some objects that may be shared across concurrent
+// type-checking passes (such as those in the universe scope), so we are
+// careful here not to write types that are already sanitized. This avoids a
+// data race as any shared types should already be sanitized.
+func sanitizeInfo(info *Info) {
+       var s sanitizer = make(map[Type]Type)
+
+       // Note: Some map entries are not references.
+       // If modified, they must be assigned back.
+
+       for e, tv := range info.Types {
+               if typ := s.typ(tv.Type); typ != tv.Type {
+                       tv.Type = typ
+                       info.Types[e] = tv
+               }
+       }
+
+       inferred := getInferred(info)
+       for e, inf := range inferred {
+               changed := false
+               for i, targ := range inf.Targs {
+                       if typ := s.typ(targ); typ != targ {
+                               inf.Targs[i] = typ
+                               changed = true
+                       }
+               }
+               if typ := s.typ(inf.Sig); typ != inf.Sig {
+                       inf.Sig = typ.(*Signature)
+                       changed = true
+               }
+               if changed {
+                       inferred[e] = inf
+               }
+       }
+
+       for _, obj := range info.Defs {
+               if obj != nil {
+                       if typ := s.typ(obj.Type()); typ != obj.Type() {
+                               obj.setType(typ)
+                       }
+               }
+       }
+
+       for _, obj := range info.Uses {
+               if obj != nil {
+                       if typ := s.typ(obj.Type()); typ != obj.Type() {
+                               obj.setType(typ)
+                       }
+               }
+       }
+
+       // TODO(gri) sanitize as needed
+       // - info.Implicits
+       // - info.Selections
+       // - info.Scopes
+       // - info.InitOrder
+}
+
+type sanitizer map[Type]Type
+
+func (s sanitizer) typ(typ Type) Type {
+       if typ == nil {
+               return nil
+       }
+
+       if t, found := s[typ]; found {
+               return t
+       }
+       s[typ] = typ
+
+       switch t := typ.(type) {
+       case *Basic, *bottom, *top:
+               // nothing to do
+
+       case *Array:
+               if elem := s.typ(t.elem); elem != t.elem {
+                       t.elem = elem
+               }
+
+       case *Slice:
+               if elem := s.typ(t.elem); elem != t.elem {
+                       t.elem = elem
+               }
+
+       case *Struct:
+               s.varList(t.fields)
+
+       case *Pointer:
+               if base := s.typ(t.base); base != t.base {
+                       t.base = base
+               }
+
+       case *Tuple:
+               s.tuple(t)
+
+       case *Signature:
+               s.var_(t.recv)
+               s.tuple(t.params)
+               s.tuple(t.results)
+
+       case *_Sum:
+               s.typeList(t.types)
+
+       case *Interface:
+               s.funcList(t.methods)
+               if types := s.typ(t.types); types != t.types {
+                       t.types = types
+               }
+               s.typeList(t.embeddeds)
+               s.funcList(t.allMethods)
+               if allTypes := s.typ(t.allTypes); allTypes != t.allTypes {
+                       t.allTypes = allTypes
+               }
+
+       case *Map:
+               if key := s.typ(t.key); key != t.key {
+                       t.key = key
+               }
+               if elem := s.typ(t.elem); elem != t.elem {
+                       t.elem = elem
+               }
+
+       case *Chan:
+               if elem := s.typ(t.elem); elem != t.elem {
+                       t.elem = elem
+               }
+
+       case *Named:
+               if debug && t.check != nil {
+                       panic("internal error: Named.check != nil")
+               }
+               if orig := s.typ(t.orig); orig != t.orig {
+                       t.orig = orig
+               }
+               if under := s.typ(t.underlying); under != t.underlying {
+                       t.underlying = under
+               }
+               s.typeList(t.targs)
+               s.funcList(t.methods)
+
+       case *_TypeParam:
+               if bound := s.typ(t.bound); bound != t.bound {
+                       t.bound = bound
+               }
+
+       case *instance:
+               typ = t.expand()
+               s[t] = typ
+
+       default:
+               panic("unimplemented")
+       }
+
+       return typ
+}
+
+func (s sanitizer) var_(v *Var) {
+       if v != nil {
+               if typ := s.typ(v.typ); typ != v.typ {
+                       v.typ = typ
+               }
+       }
+}
+
+func (s sanitizer) varList(list []*Var) {
+       for _, v := range list {
+               s.var_(v)
+       }
+}
+
+func (s sanitizer) tuple(t *Tuple) {
+       if t != nil {
+               s.varList(t.vars)
+       }
+}
+
+func (s sanitizer) func_(f *Func) {
+       if f != nil {
+               if typ := s.typ(f.typ); typ != f.typ {
+                       f.typ = typ
+               }
+       }
+}
+
+func (s sanitizer) funcList(list []*Func) {
+       for _, f := range list {
+               s.func_(f)
+       }
+}
+
+func (s sanitizer) typeList(list []Type) {
+       for i, t := range list {
+               if typ := s.typ(t); typ != t {
+                       list[i] = typ
+               }
+       }
+}
index 8c9d9ab8b8010be3674fd948e641048fdfe1d20d..26c28d1c4e3c46437d8640b893137ef3b0ccdcef 100644 (file)
@@ -108,6 +108,40 @@ func (s *Scope) Insert(obj Object) Object {
        return nil
 }
 
+// squash merges s with its parent scope p by adding all
+// objects of s to p, adding all children of s to the
+// children of p, and removing s from p's children.
+// The function f is called for each object obj in s which
+// has an object alt in p. s should be discarded after
+// having been squashed.
+func (s *Scope) squash(err func(obj, alt Object)) {
+       p := s.parent
+       assert(p != nil)
+       for _, obj := range s.elems {
+               obj.setParent(nil)
+               if alt := p.Insert(obj); alt != nil {
+                       err(obj, alt)
+               }
+       }
+
+       j := -1 // index of s in p.children
+       for i, ch := range p.children {
+               if ch == s {
+                       j = i
+                       break
+               }
+       }
+       assert(j >= 0)
+       k := len(p.children) - 1
+       p.children[j] = p.children[k]
+       p.children = p.children[:k]
+
+       p.children = append(p.children, s.children...)
+
+       s.children = nil
+       s.elems = nil
+}
+
 // Pos and End describe the scope's source code extent [pos, end).
 // The results are guaranteed to be valid only if the type-checked
 // AST has complete position information. The extent is undefined
diff --git a/libgo/go/go/types/sizeof_test.go b/libgo/go/go/types/sizeof_test.go
new file mode 100644 (file)
index 0000000..5a9d07c
--- /dev/null
@@ -0,0 +1,63 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types
+
+import (
+       "reflect"
+       "testing"
+)
+
+// Signal size changes of important structures.
+func TestSizeof(t *testing.T) {
+       const _64bit = ^uint(0)>>32 != 0
+
+       var tests = []struct {
+               val    interface{} // type as a value
+               _32bit uintptr     // size on 32bit platforms
+               _64bit uintptr     // size on 64bit platforms
+       }{
+               // Types
+               {Basic{}, 16, 32},
+               {Array{}, 16, 24},
+               {Slice{}, 8, 16},
+               {Struct{}, 24, 48},
+               {Pointer{}, 8, 16},
+               {Tuple{}, 12, 24},
+               {Signature{}, 44, 88},
+               {_Sum{}, 12, 24},
+               {Interface{}, 60, 120},
+               {Map{}, 16, 32},
+               {Chan{}, 12, 24},
+               {Named{}, 64, 128},
+               {_TypeParam{}, 28, 48},
+               {instance{}, 44, 88},
+               {bottom{}, 0, 0},
+               {top{}, 0, 0},
+
+               // Objects
+               {PkgName{}, 48, 88},
+               {Const{}, 48, 88},
+               {TypeName{}, 40, 72},
+               {Var{}, 44, 80},
+               {Func{}, 44, 80},
+               {Label{}, 44, 80},
+               {Builtin{}, 44, 80},
+               {Nil{}, 40, 72},
+
+               // Misc
+               {Scope{}, 40, 80},
+               {Package{}, 40, 80},
+       }
+       for _, test := range tests {
+               got := reflect.TypeOf(test.val).Size()
+               want := test._32bit
+               if _64bit {
+                       want = test._64bit
+               }
+               if got != want {
+                       t.Errorf("unsafe.Sizeof(%T) = %d, want %d", test.val, got, want)
+               }
+       }
+}
index 4787b242cc02ac65d49a2349bc4394eaf7bb5b29..3b334ac5c60528bc15173d854c6d77a969b50c19 100644 (file)
@@ -48,7 +48,7 @@ type StdSizes struct {
 func (s *StdSizes) Alignof(T Type) int64 {
        // For arrays and structs, alignment is defined in terms
        // of alignment of the elements and fields, respectively.
-       switch t := T.Underlying().(type) {
+       switch t := optype(T).(type) {
        case *Array:
                // spec: "For a variable x of array type: unsafe.Alignof(x)
                // is the same as unsafe.Alignof(x[0]), but at least 1."
@@ -118,7 +118,7 @@ var basicSizes = [...]byte{
 }
 
 func (s *StdSizes) Sizeof(T Type) int64 {
-       switch t := T.Underlying().(type) {
+       switch t := optype(T).(type) {
        case *Basic:
                assert(isTyped(T))
                k := t.kind
@@ -148,6 +148,8 @@ func (s *StdSizes) Sizeof(T Type) int64 {
                }
                offsets := s.Offsetsof(t.fields)
                return offsets[n-1] + s.Sizeof(t.fields[n-1].typ)
+       case *_Sum:
+               panic("Sizeof unimplemented for type sum")
        case *Interface:
                return s.WordSize * 2
        }
@@ -241,7 +243,7 @@ func (conf *Config) offsetsof(T *Struct) []int64 {
 func (conf *Config) offsetof(typ Type, index []int) int64 {
        var o int64
        for _, i := range index {
-               s := typ.Underlying().(*Struct)
+               s := asStruct(typ)
                o += conf.offsetsof(s)[i]
                typ = s.fields[i].typ
        }
index 208311e557f373e1af3cb91d231a2c1d9dd365cc..de30bdb6eba56cc5a4f59ceb71ffb5fa1993ab71 100644 (file)
@@ -26,9 +26,15 @@ import (
        . "go/types"
 )
 
+// The cmd/*/internal packages may have been deleted as part of a binary
+// release. Import from source instead.
+//
+// (See https://golang.org/issue/43232 and
+// https://github.com/golang/build/blob/df58bbac082bc87c4a3cdfe336d1ffe60bbaa916/cmd/release/release.go#L533-L545.)
+//
 // Use the same importer for all std lib tests to
 // avoid repeated importing of the same packages.
-var stdLibImporter = importer.Default()
+var stdLibImporter = importer.ForCompiler(token.NewFileSet(), "source", nil)
 
 func TestStdlib(t *testing.T) {
        testenv.MustHaveGoBuild(t)
@@ -108,6 +114,7 @@ func testTestDir(t *testing.T, path string, ignore ...string) {
                // get per-file instructions
                expectErrors := false
                filename := filepath.Join(path, f.Name())
+               goVersion := ""
                if comment := firstComment(filename); comment != "" {
                        fields := strings.Fields(comment)
                        switch fields[0] {
@@ -117,13 +124,17 @@ func testTestDir(t *testing.T, path string, ignore ...string) {
                                expectErrors = true
                                for _, arg := range fields[1:] {
                                        if arg == "-0" || arg == "-+" || arg == "-std" {
-                                               // Marked explicitly as not expected errors (-0),
+                                               // Marked explicitly as not expecting errors (-0),
                                                // or marked as compiling runtime/stdlib, which is only done
                                                // to trigger runtime/stdlib-only error output.
                                                // In both cases, the code should typecheck.
                                                expectErrors = false
                                                break
                                        }
+                                       const prefix = "-lang="
+                                       if strings.HasPrefix(arg, prefix) {
+                                               goVersion = arg[len(prefix):]
+                                       }
                                }
                        }
                }
@@ -132,6 +143,7 @@ func testTestDir(t *testing.T, path string, ignore ...string) {
                file, err := parser.ParseFile(fset, filename, nil, 0)
                if err == nil {
                        conf := Config{Importer: stdLibImporter}
+                       SetGoVersion(&conf, goVersion)
                        _, err = conf.Check(filename, fset, []*ast.File{file}, nil)
                }
 
@@ -159,6 +171,7 @@ func TestStdTest(t *testing.T) {
                "directive.go",   // tests compiler rejection of bad directive placement - ignore
                "embedfunc.go",   // tests //go:embed
                "embedvers.go",   // tests //go:embed
+               "linkname2.go",   // go/types doesn't check validity of //go:xxx directives
        )
 }
 
@@ -172,19 +185,15 @@ func TestStdFixed(t *testing.T) {
        testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "fixedbugs"),
                "bug248.go", "bug302.go", "bug369.go", // complex test instructions - ignore
                "issue6889.go",   // gc-specific test
-               "issue7746.go",   // large constants - consumes too much memory
                "issue11362.go",  // canonical import path check
                "issue16369.go",  // go/types handles this correctly - not an issue
                "issue18459.go",  // go/types doesn't check validity of //go:xxx directives
                "issue18882.go",  // go/types doesn't check validity of //go:xxx directives
-               "issue20232.go",  // go/types handles larger constants than gc
                "issue20529.go",  // go/types does not have constraints on stack size
                "issue22200.go",  // go/types does not have constraints on stack size
                "issue22200b.go", // go/types does not have constraints on stack size
                "issue25507.go",  // go/types does not have constraints on stack size
                "issue20780.go",  // go/types does not have constraints on stack size
-               "issue31747.go",  // go/types does not have constraints on language level (-lang=go1.12) (see #31793)
-               "issue34329.go",  // go/types does not have constraints on language level (-lang=go1.13) (see #31793)
                "bug251.go",      // issue #34333 which was exposed with fix for #34151
                "issue42058a.go", // go/types does not have constraints on channel element size
                "issue42058b.go", // go/types does not have constraints on channel element size
@@ -200,6 +209,9 @@ func TestStdKen(t *testing.T) {
 // Package paths of excluded packages.
 var excluded = map[string]bool{
        "builtin": true,
+
+       // See #46027: some imports are missing for this submodule.
+       "crypto/ed25519/internal/edwards25519/field/_asm": true,
 }
 
 // typecheck typechecks the given package files.
index d88e47170c3a676b3ffa83acebb82a27fbb0e5cf..47f6dcfbd1ce8f6f5b25f0da36a2ef144afb1feb 100644 (file)
@@ -14,6 +14,10 @@ import (
 )
 
 func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body *ast.BlockStmt, iota constant.Value) {
+       if check.conf.IgnoreFuncBodies {
+               panic("internal error: function body not ignored")
+       }
+
        if trace {
                check.trace(body.Pos(), "--- %s: %s", name, sig)
                defer func() {
@@ -49,6 +53,11 @@ func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body
                check.error(atPos(body.Rbrace), _MissingReturn, "missing return")
        }
 
+       // TODO(gri) Should we make it an error to declare generic functions
+       //           where the type parameters are not used?
+       // 12/19/2018: Probably not - it can make sense to have an API with
+       //           all functions uniformly sharing the same type parameters.
+
        // spec: "Implementation restriction: A compiler may make it illegal to
        // declare a variable inside a function body if the variable is never used."
        check.usage(sig.scope)
@@ -147,9 +156,9 @@ func (check *Checker) multipleDefaults(list []ast.Stmt) {
        }
 }
 
-func (check *Checker) openScope(s ast.Stmt, comment string) {
-       scope := NewScope(check.scope, s.Pos(), s.End(), comment)
-       check.recordScope(s, scope)
+func (check *Checker) openScope(node ast.Node, comment string) {
+       scope := NewScope(check.scope, node.Pos(), node.End(), comment)
+       check.recordScope(node, scope)
        check.scope = scope
 }
 
@@ -269,10 +278,13 @@ L:
 func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []ast.Expr, seen map[Type]ast.Expr) (T Type) {
 L:
        for _, e := range types {
-               T = check.typOrNil(e)
+               T = check.typeOrNil(e)
                if T == Typ[Invalid] {
                        continue L
                }
+               if T != nil {
+                       check.ordinaryType(e, T)
+               }
                // look for duplicate types
                // (quadratic algorithm, but type switches tend to be reasonably small)
                for t, other := range seen {
@@ -355,8 +367,8 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
                        return
                }
 
-               tch, ok := ch.typ.Underlying().(*Chan)
-               if !ok {
+               tch := asChan(ch.typ)
+               if tch == nil {
                        check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to non-chan type %s", ch.typ)
                        return
                }
@@ -609,7 +621,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
                        return
                }
 
-               // rhs must be of the form: expr.(type) and expr must be an interface
+               // rhs must be of the form: expr.(type) and expr must be an ordinary interface
                expr, _ := rhs.(*ast.TypeAssertExpr)
                if expr == nil || expr.Type != nil {
                        check.invalidAST(s, "incorrect form of type switch guard")
@@ -620,11 +632,12 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
                if x.mode == invalid {
                        return
                }
-               xtyp, _ := x.typ.Underlying().(*Interface)
+               xtyp, _ := under(x.typ).(*Interface)
                if xtyp == nil {
                        check.errorf(&x, _InvalidTypeSwitch, "%s is not an interface", &x)
                        return
                }
+               check.ordinaryType(&x, xtyp)
 
                check.multipleDefaults(s.Body.List)
 
@@ -761,45 +774,24 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
                // determine key/value types
                var key, val Type
                if x.mode != invalid {
-                       switch typ := x.typ.Underlying().(type) {
-                       case *Basic:
-                               if isString(typ) {
-                                       key = Typ[Int]
-                                       val = universeRune // use 'rune' name
-                               }
-                       case *Array:
-                               key = Typ[Int]
-                               val = typ.elem
-                       case *Slice:
-                               key = Typ[Int]
-                               val = typ.elem
-                       case *Pointer:
-                               if typ, _ := typ.base.Underlying().(*Array); typ != nil {
-                                       key = Typ[Int]
-                                       val = typ.elem
-                               }
-                       case *Map:
-                               key = typ.key
-                               val = typ.elem
-                       case *Chan:
-                               key = typ.elem
-                               val = Typ[Invalid]
-                               if typ.dir == SendOnly {
-                                       check.errorf(&x, _InvalidChanRange, "cannot range over send-only channel %s", &x)
-                                       // ok to continue
-                               }
-                               if s.Value != nil {
-                                       check.errorf(atPos(s.Value.Pos()), _InvalidIterVar, "iteration over %s permits only one iteration variable", &x)
-                                       // ok to continue
+                       typ := optype(x.typ)
+                       if _, ok := typ.(*Chan); ok && s.Value != nil {
+                               // TODO(gri) this also needs to happen for channels in generic variables
+                               check.softErrorf(atPos(s.Value.Pos()), _InvalidIterVar, "range over %s permits only one iteration variable", &x)
+                               // ok to continue
+                       }
+                       var msg string
+                       key, val, msg = rangeKeyVal(typ, isVarName(s.Key), isVarName(s.Value))
+                       if key == nil || msg != "" {
+                               if msg != "" {
+                                       // TODO(rFindley) should this be parenthesized, to be consistent with other qualifiers?
+                                       msg = ": " + msg
                                }
+                               check.softErrorf(&x, _InvalidRangeExpr, "cannot range over %s%s", &x, msg)
+                               // ok to continue
                        }
                }
 
-               if key == nil {
-                       check.errorf(&x, _InvalidRangeExpr, "cannot range over %s", &x)
-                       // ok to continue
-               }
-
                // check assignment to/declaration of iteration variables
                // (irregular assignment, cannot easily map to existing assignment checks)
 
@@ -879,3 +871,72 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
                check.invalidAST(s, "invalid statement")
        }
 }
+
+// isVarName reports whether x is a non-nil, non-blank (_) expression.
+func isVarName(x ast.Expr) bool {
+       if x == nil {
+               return false
+       }
+       ident, _ := unparen(x).(*ast.Ident)
+       return ident == nil || ident.Name != "_"
+}
+
+// rangeKeyVal returns the key and value type produced by a range clause
+// over an expression of type typ, and possibly an error message. If the
+// range clause is not permitted the returned key is nil or msg is not
+// empty (in that case we still may have a non-nil key type which can be
+// used to reduce the chance for follow-on errors).
+// The wantKey, wantVal, and hasVal flags indicate which of the iteration
+// variables are used or present; this matters if we range over a generic
+// type where not all keys or values are of the same type.
+func rangeKeyVal(typ Type, wantKey, wantVal bool) (Type, Type, string) {
+       switch typ := typ.(type) {
+       case *Basic:
+               if isString(typ) {
+                       return Typ[Int], universeRune, "" // use 'rune' name
+               }
+       case *Array:
+               return Typ[Int], typ.elem, ""
+       case *Slice:
+               return Typ[Int], typ.elem, ""
+       case *Pointer:
+               if typ := asArray(typ.base); typ != nil {
+                       return Typ[Int], typ.elem, ""
+               }
+       case *Map:
+               return typ.key, typ.elem, ""
+       case *Chan:
+               var msg string
+               if typ.dir == SendOnly {
+                       msg = "send-only channel"
+               }
+               return typ.elem, Typ[Invalid], msg
+       case *_Sum:
+               first := true
+               var key, val Type
+               var msg string
+               typ.is(func(t Type) bool {
+                       k, v, m := rangeKeyVal(under(t), wantKey, wantVal)
+                       if k == nil || m != "" {
+                               key, val, msg = k, v, m
+                               return false
+                       }
+                       if first {
+                               key, val, msg = k, v, m
+                               first = false
+                               return true
+                       }
+                       if wantKey && !Identical(key, k) {
+                               key, val, msg = nil, nil, "all possible values must have the same key type"
+                               return false
+                       }
+                       if wantVal && !Identical(val, v) {
+                               key, val, msg = nil, nil, "all possible values must have the same element type"
+                               return false
+                       }
+                       return true
+               })
+               return key, val, msg
+       }
+       return nil, nil, ""
+}
diff --git a/libgo/go/go/types/subst.go b/libgo/go/go/types/subst.go
new file mode 100644 (file)
index 0000000..931375f
--- /dev/null
@@ -0,0 +1,543 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements instantiation of generic types
+// through substitution of type parameters by actual
+// types.
+
+package types
+
+import (
+       "bytes"
+       "fmt"
+       "go/token"
+)
+
+// TODO(rFindley) decide error codes for the errors in this file, and check
+//                if error spans can be improved
+
+type substMap struct {
+       // The targs field is currently needed for *Named type substitution.
+       // TODO(gri) rewrite that code, get rid of this field, and make this
+       //           struct just the map (proj)
+       targs []Type
+       proj  map[*_TypeParam]Type
+}
+
+// makeSubstMap creates a new substitution map mapping tpars[i] to targs[i].
+// If targs[i] is nil, tpars[i] is not substituted.
+func makeSubstMap(tpars []*TypeName, targs []Type) *substMap {
+       assert(len(tpars) == len(targs))
+       proj := make(map[*_TypeParam]Type, len(tpars))
+       for i, tpar := range tpars {
+               // We must expand type arguments otherwise *instance
+               // types end up as components in composite types.
+               // TODO(gri) explain why this causes problems, if it does
+               targ := expand(targs[i]) // possibly nil
+               targs[i] = targ
+               proj[tpar.typ.(*_TypeParam)] = targ
+       }
+       return &substMap{targs, proj}
+}
+
+func (m *substMap) String() string {
+       return fmt.Sprintf("%s", m.proj)
+}
+
+func (m *substMap) empty() bool {
+       return len(m.proj) == 0
+}
+
+func (m *substMap) lookup(tpar *_TypeParam) Type {
+       if t := m.proj[tpar]; t != nil {
+               return t
+       }
+       return tpar
+}
+
+func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, poslist []token.Pos) (res Type) {
+       if trace {
+               check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs))
+               check.indent++
+               defer func() {
+                       check.indent--
+                       var under Type
+                       if res != nil {
+                               // Calling under() here may lead to endless instantiations.
+                               // Test case: type T[P any] T[P]
+                               // TODO(gri) investigate if that's a bug or to be expected.
+                               under = res.Underlying()
+                       }
+                       check.trace(pos, "=> %s (under = %s)", res, under)
+               }()
+       }
+
+       assert(len(poslist) <= len(targs))
+
+       // TODO(gri) What is better here: work with TypeParams, or work with TypeNames?
+       var tparams []*TypeName
+       switch t := typ.(type) {
+       case *Named:
+               tparams = t.tparams
+       case *Signature:
+               tparams = t.tparams
+               defer func() {
+                       // If we had an unexpected failure somewhere don't panic below when
+                       // asserting res.(*Signature). Check for *Signature in case Typ[Invalid]
+                       // is returned.
+                       if _, ok := res.(*Signature); !ok {
+                               return
+                       }
+                       // If the signature doesn't use its type parameters, subst
+                       // will not make a copy. In that case, make a copy now (so
+                       // we can set tparams to nil w/o causing side-effects).
+                       if t == res {
+                               copy := *t
+                               res = &copy
+                       }
+                       // After instantiating a generic signature, it is not generic
+                       // anymore; we need to set tparams to nil.
+                       res.(*Signature).tparams = nil
+               }()
+
+       default:
+               check.dump("%v: cannot instantiate %v", pos, typ)
+               unreachable() // only defined types and (defined) functions can be generic
+       }
+
+       // the number of supplied types must match the number of type parameters
+       if len(targs) != len(tparams) {
+               // TODO(gri) provide better error message
+               check.errorf(atPos(pos), _Todo, "got %d arguments but %d type parameters", len(targs), len(tparams))
+               return Typ[Invalid]
+       }
+
+       if len(tparams) == 0 {
+               return typ // nothing to do (minor optimization)
+       }
+
+       smap := makeSubstMap(tparams, targs)
+
+       // check bounds
+       for i, tname := range tparams {
+               tpar := tname.typ.(*_TypeParam)
+               iface := tpar.Bound()
+               if iface.Empty() {
+                       continue // no type bound
+               }
+
+               targ := targs[i]
+
+               // best position for error reporting
+               pos := pos
+               if i < len(poslist) {
+                       pos = poslist[i]
+               }
+
+               // The type parameter bound is parameterized with the same type parameters
+               // as the instantiated type; before we can use it for bounds checking we
+               // need to instantiate it with the type arguments with which we instantiate
+               // the parameterized type.
+               iface = check.subst(pos, iface, smap).(*Interface)
+
+               // targ must implement iface (methods)
+               // - check only if we have methods
+               check.completeInterface(token.NoPos, iface)
+               if len(iface.allMethods) > 0 {
+                       // If the type argument is a pointer to a type parameter, the type argument's
+                       // method set is empty.
+                       // TODO(gri) is this what we want? (spec question)
+                       if base, isPtr := deref(targ); isPtr && asTypeParam(base) != nil {
+                               check.errorf(atPos(pos), 0, "%s has no methods", targ)
+                               break
+                       }
+                       if m, wrong := check.missingMethod(targ, iface, true); m != nil {
+                               // TODO(gri) needs to print updated name to avoid major confusion in error message!
+                               //           (print warning for now)
+                               // Old warning:
+                               // check.softErrorf(pos, "%s does not satisfy %s (warning: name not updated) = %s (missing method %s)", targ, tpar.bound, iface, m)
+                               if m.name == "==" {
+                                       // We don't want to report "missing method ==".
+                                       check.softErrorf(atPos(pos), 0, "%s does not satisfy comparable", targ)
+                               } else if wrong != nil {
+                                       // TODO(gri) This can still report uninstantiated types which makes the error message
+                                       //           more difficult to read then necessary.
+                                       // TODO(rFindley) should this use parentheses rather than ':' for qualification?
+                                       check.softErrorf(atPos(pos), _Todo,
+                                               "%s does not satisfy %s: wrong method signature\n\tgot  %s\n\twant %s",
+                                               targ, tpar.bound, wrong, m,
+                                       )
+                               } else {
+                                       check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (missing method %s)", targ, tpar.bound, m.name)
+                               }
+                               break
+                       }
+               }
+
+               // targ's underlying type must also be one of the interface types listed, if any
+               if iface.allTypes == nil {
+                       continue // nothing to do
+               }
+
+               // If targ is itself a type parameter, each of its possible types, but at least one, must be in the
+               // list of iface types (i.e., the targ type list must be a non-empty subset of the iface types).
+               if targ := asTypeParam(targ); targ != nil {
+                       targBound := targ.Bound()
+                       if targBound.allTypes == nil {
+                               check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ)
+                               break
+                       }
+                       for _, t := range unpackType(targBound.allTypes) {
+                               if !iface.isSatisfiedBy(t) {
+                                       // TODO(gri) match this error message with the one below (or vice versa)
+                                       check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, t, iface.allTypes)
+                                       break
+                               }
+                       }
+                       break
+               }
+
+               // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any.
+               if !iface.isSatisfiedBy(targ) {
+                       check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s or %s not found in %s)", targ, tpar.bound, targ, under(targ), iface.allTypes)
+                       break
+               }
+       }
+
+       return check.subst(pos, typ, smap)
+}
+
+// subst returns the type typ with its type parameters tpars replaced by
+// the corresponding type arguments targs, recursively.
+// subst is functional in the sense that it doesn't modify the incoming
+// type. If a substitution took place, the result type is different from
+// from the incoming type.
+func (check *Checker) subst(pos token.Pos, typ Type, smap *substMap) Type {
+       if smap.empty() {
+               return typ
+       }
+
+       // common cases
+       switch t := typ.(type) {
+       case *Basic:
+               return typ // nothing to do
+       case *_TypeParam:
+               return smap.lookup(t)
+       }
+
+       // general case
+       subst := subster{check, pos, make(map[Type]Type), smap}
+       return subst.typ(typ)
+}
+
+type subster struct {
+       check *Checker
+       pos   token.Pos
+       cache map[Type]Type
+       smap  *substMap
+}
+
+func (subst *subster) typ(typ Type) Type {
+       switch t := typ.(type) {
+       case nil:
+               // Call typOrNil if it's possible that typ is nil.
+               panic("nil typ")
+
+       case *Basic, *bottom, *top:
+               // nothing to do
+
+       case *Array:
+               elem := subst.typOrNil(t.elem)
+               if elem != t.elem {
+                       return &Array{len: t.len, elem: elem}
+               }
+
+       case *Slice:
+               elem := subst.typOrNil(t.elem)
+               if elem != t.elem {
+                       return &Slice{elem: elem}
+               }
+
+       case *Struct:
+               if fields, copied := subst.varList(t.fields); copied {
+                       return &Struct{fields: fields, tags: t.tags}
+               }
+
+       case *Pointer:
+               base := subst.typ(t.base)
+               if base != t.base {
+                       return &Pointer{base: base}
+               }
+
+       case *Tuple:
+               return subst.tuple(t)
+
+       case *Signature:
+               // TODO(gri) rethink the recv situation with respect to methods on parameterized types
+               // recv := subst.var_(t.recv) // TODO(gri) this causes a stack overflow - explain
+               recv := t.recv
+               params := subst.tuple(t.params)
+               results := subst.tuple(t.results)
+               if recv != t.recv || params != t.params || results != t.results {
+                       return &Signature{
+                               rparams: t.rparams,
+                               // TODO(rFindley) why can't we nil out tparams here, rather than in
+                               //                instantiate above?
+                               tparams:  t.tparams,
+                               scope:    t.scope,
+                               recv:     recv,
+                               params:   params,
+                               results:  results,
+                               variadic: t.variadic,
+                       }
+               }
+
+       case *_Sum:
+               types, copied := subst.typeList(t.types)
+               if copied {
+                       // Don't do it manually, with a Sum literal: the new
+                       // types list may not be unique and NewSum may remove
+                       // duplicates.
+                       return _NewSum(types)
+               }
+
+       case *Interface:
+               methods, mcopied := subst.funcList(t.methods)
+               types := t.types
+               if t.types != nil {
+                       types = subst.typ(t.types)
+               }
+               embeddeds, ecopied := subst.typeList(t.embeddeds)
+               if mcopied || types != t.types || ecopied {
+                       iface := &Interface{methods: methods, types: types, embeddeds: embeddeds}
+                       subst.check.posMap[iface] = subst.check.posMap[t] // satisfy completeInterface requirement
+                       subst.check.completeInterface(token.NoPos, iface)
+                       return iface
+               }
+
+       case *Map:
+               key := subst.typ(t.key)
+               elem := subst.typ(t.elem)
+               if key != t.key || elem != t.elem {
+                       return &Map{key: key, elem: elem}
+               }
+
+       case *Chan:
+               elem := subst.typ(t.elem)
+               if elem != t.elem {
+                       return &Chan{dir: t.dir, elem: elem}
+               }
+
+       case *Named:
+               subst.check.indent++
+               defer func() {
+                       subst.check.indent--
+               }()
+               dump := func(format string, args ...interface{}) {
+                       if trace {
+                               subst.check.trace(subst.pos, format, args...)
+                       }
+               }
+
+               if t.tparams == nil {
+                       dump(">>> %s is not parameterized", t)
+                       return t // type is not parameterized
+               }
+
+               var newTargs []Type
+
+               if len(t.targs) > 0 {
+                       // already instantiated
+                       dump(">>> %s already instantiated", t)
+                       assert(len(t.targs) == len(t.tparams))
+                       // For each (existing) type argument targ, determine if it needs
+                       // to be substituted; i.e., if it is or contains a type parameter
+                       // that has a type argument for it.
+                       for i, targ := range t.targs {
+                               dump(">>> %d targ = %s", i, targ)
+                               newTarg := subst.typ(targ)
+                               if newTarg != targ {
+                                       dump(">>> substituted %d targ %s => %s", i, targ, newTarg)
+                                       if newTargs == nil {
+                                               newTargs = make([]Type, len(t.tparams))
+                                               copy(newTargs, t.targs)
+                                       }
+                                       newTargs[i] = newTarg
+                               }
+                       }
+
+                       if newTargs == nil {
+                               dump(">>> nothing to substitute in %s", t)
+                               return t // nothing to substitute
+                       }
+               } else {
+                       // not yet instantiated
+                       dump(">>> first instantiation of %s", t)
+                       // TODO(rFindley) can we instead subst the tparam types here?
+                       newTargs = subst.smap.targs
+               }
+
+               // before creating a new named type, check if we have this one already
+               h := instantiatedHash(t, newTargs)
+               dump(">>> new type hash: %s", h)
+               if named, found := subst.check.typMap[h]; found {
+                       dump(">>> found %s", named)
+                       subst.cache[t] = named
+                       return named
+               }
+
+               // create a new named type and populate caches to avoid endless recursion
+               tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil)
+               named := subst.check.newNamed(tname, t.underlying, t.methods) // method signatures are updated lazily
+               named.tparams = t.tparams                                     // new type is still parameterized
+               named.targs = newTargs
+               subst.check.typMap[h] = named
+               subst.cache[t] = named
+
+               // do the substitution
+               dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, newTargs)
+               named.underlying = subst.typOrNil(t.underlying)
+               named.orig = named.underlying // for cycle detection (Checker.validType)
+
+               return named
+
+       case *_TypeParam:
+               return subst.smap.lookup(t)
+
+       case *instance:
+               // TODO(gri) can we avoid the expansion here and just substitute the type parameters?
+               return subst.typ(t.expand())
+
+       default:
+               panic("unimplemented")
+       }
+
+       return typ
+}
+
+// TODO(gri) Eventually, this should be more sophisticated.
+//           It won't work correctly for locally declared types.
+func instantiatedHash(typ *Named, targs []Type) string {
+       var buf bytes.Buffer
+       writeTypeName(&buf, typ.obj, nil)
+       buf.WriteByte('[')
+       writeTypeList(&buf, targs, nil, nil)
+       buf.WriteByte(']')
+
+       // With respect to the represented type, whether a
+       // type is fully expanded or stored as instance
+       // does not matter - they are the same types.
+       // Remove the instanceMarkers printed for instances.
+       res := buf.Bytes()
+       i := 0
+       for _, b := range res {
+               if b != instanceMarker {
+                       res[i] = b
+                       i++
+               }
+       }
+
+       return string(res[:i])
+}
+
+func typeListString(list []Type) string {
+       var buf bytes.Buffer
+       writeTypeList(&buf, list, nil, nil)
+       return buf.String()
+}
+
+// typOrNil is like typ but if the argument is nil it is replaced with Typ[Invalid].
+// A nil type may appear in pathological cases such as type T[P any] []func(_ T([]_))
+// where an array/slice element is accessed before it is set up.
+func (subst *subster) typOrNil(typ Type) Type {
+       if typ == nil {
+               return Typ[Invalid]
+       }
+       return subst.typ(typ)
+}
+
+func (subst *subster) var_(v *Var) *Var {
+       if v != nil {
+               if typ := subst.typ(v.typ); typ != v.typ {
+                       copy := *v
+                       copy.typ = typ
+                       return &copy
+               }
+       }
+       return v
+}
+
+func (subst *subster) tuple(t *Tuple) *Tuple {
+       if t != nil {
+               if vars, copied := subst.varList(t.vars); copied {
+                       return &Tuple{vars: vars}
+               }
+       }
+       return t
+}
+
+func (subst *subster) varList(in []*Var) (out []*Var, copied bool) {
+       out = in
+       for i, v := range in {
+               if w := subst.var_(v); w != v {
+                       if !copied {
+                               // first variable that got substituted => allocate new out slice
+                               // and copy all variables
+                               new := make([]*Var, len(in))
+                               copy(new, out)
+                               out = new
+                               copied = true
+                       }
+                       out[i] = w
+               }
+       }
+       return
+}
+
+func (subst *subster) func_(f *Func) *Func {
+       if f != nil {
+               if typ := subst.typ(f.typ); typ != f.typ {
+                       copy := *f
+                       copy.typ = typ
+                       return &copy
+               }
+       }
+       return f
+}
+
+func (subst *subster) funcList(in []*Func) (out []*Func, copied bool) {
+       out = in
+       for i, f := range in {
+               if g := subst.func_(f); g != f {
+                       if !copied {
+                               // first function that got substituted => allocate new out slice
+                               // and copy all functions
+                               new := make([]*Func, len(in))
+                               copy(new, out)
+                               out = new
+                               copied = true
+                       }
+                       out[i] = g
+               }
+       }
+       return
+}
+
+func (subst *subster) typeList(in []Type) (out []Type, copied bool) {
+       out = in
+       for i, t := range in {
+               if u := subst.typ(t); u != t {
+                       if !copied {
+                               // first function that got substituted => allocate new out slice
+                               // and copy all functions
+                               new := make([]Type, len(in))
+                               copy(new, out)
+                               out = new
+                               copied = true
+                       }
+                       out[i] = u
+               }
+       }
+       return
+}
diff --git a/libgo/go/go/types/testdata/check/builtins.go2 b/libgo/go/go/types/testdata/check/builtins.go2
new file mode 100644 (file)
index 0000000..3918d83
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file tests built-in calls on generic types.
+
+package builtins
+
+type Bmc interface {
+       type map[rune]string, chan int
+}
+
+type Bms interface {
+       type map[string]int, []int
+}
+
+type Bcs interface {
+       type chan bool, []float64
+}
+
+type Bss interface {
+       type []int, []string
+}
+
+func _[T any] () {
+       _ = make(T /* ERROR invalid argument */ )
+       _ = make(T /* ERROR invalid argument */ , 10)
+       _ = make(T /* ERROR invalid argument */ , 10, 20)
+}
+
+func _[T Bmc] () {
+       _ = make(T)
+       _ = make(T, 10)
+       _ = make /* ERROR expects 1 or 2 arguments */ (T, 10, 20)
+}
+
+func _[T Bms] () {
+       _ = make /* ERROR expects 2 arguments */ (T)
+       _ = make(T, 10)
+       _ = make /* ERROR expects 2 arguments */ (T, 10, 20)
+}
+
+func _[T Bcs] () {
+       _ = make /* ERROR expects 2 arguments */ (T)
+       _ = make(T, 10)
+       _ = make /* ERROR expects 2 arguments */ (T, 10, 20)
+}
+
+func _[T Bss] () {
+       _ = make /* ERROR expects 2 or 3 arguments */ (T)
+       _ = make(T, 10)
+       _ = make(T, 10, 20)
+}
similarity index 97%
rename from libgo/go/go/types/testdata/builtins.src
rename to libgo/go/go/types/testdata/check/builtins.src
index 98830eb08c601458c43bc77294ef1e30f97e4fd6..370752891407beef0f7d828a128144617c4796c9 100644 (file)
@@ -25,11 +25,11 @@ func append1() {
        _ = append(s, b)
        _ = append(s, x /* ERROR cannot use x */ )
        _ = append(s, s /* ERROR cannot use s */ )
-       _ = append(s... /* ERROR can only use ... with matching parameter */ )
-       _ = append(s, b, s... /* ERROR can only use ... with matching parameter */ )
+       _ = append(s...) /* ERROR not enough arguments */
+       _ = append(s, b, s /* ERROR too many arguments */ ...)
        _ = append(s, 1, 2, 3)
        _ = append(s, 1, 2, 3, x /* ERROR cannot use x */ , 5, 6, 6)
-       _ = append(s, 1, 2, s... /* ERROR can only use ... with matching parameter */ )
+       _ = append(s, 1, 2 /* ERROR too many arguments */, s...)
        _ = append([]interface{}(nil), 1, 2, "foo", x, 3.1425, false)
 
        type S []byte
@@ -283,7 +283,7 @@ func delete1() {
        delete() // ERROR not enough arguments
        delete(1) // ERROR not enough arguments
        delete(1, 2, 3) // ERROR too many arguments
-       delete(m, 0 /* ERROR not assignable */)
+       delete(m, 0 /* ERROR cannot use */)
        delete(m, s)
        _ = delete /* ERROR used as value */ (m, s)
 
@@ -514,7 +514,7 @@ func panic1() {
        panic("foo")
        panic(false)
        panic(1<<10)
-       panic(1 /* ERROR overflows */ <<1000)
+       panic(1 << /* ERROR constant shift overflow */ 1000)
        _ = panic /* ERROR used as value */ (0)
 
        var s []byte
@@ -538,7 +538,7 @@ func print1() {
        print(2.718281828)
        print(false)
        print(1<<10)
-       print(1 /* ERROR overflows */ <<1000)
+       print(1 << /* ERROR constant shift overflow */ 1000)
        println(nil /* ERROR untyped nil */ )
 
        var s []int
@@ -564,7 +564,7 @@ func println1() {
        println(2.718281828)
        println(false)
        println(1<<10)
-       println(1 /* ERROR overflows */ <<1000)
+       println(1 << /* ERROR constant shift overflow */ 1000)
        println(nil /* ERROR untyped nil */ )
 
        var s []int
@@ -695,7 +695,7 @@ func Alignof1() {
        _ = unsafe.Alignof(42)
        _ = unsafe.Alignof(new(struct{}))
        _ = unsafe.Alignof(1<<10)
-       _ = unsafe.Alignof(1 /* ERROR overflows */ <<1000)
+       _ = unsafe.Alignof(1 << /* ERROR constant shift overflow */ 1000)
        _ = unsafe.Alignof(nil /* ERROR "untyped nil */ )
        unsafe /* ERROR not used */ .Alignof(x)
 
@@ -783,7 +783,7 @@ func Sizeof1() {
        _ = unsafe.Sizeof(42)
        _ = unsafe.Sizeof(new(complex128))
        _ = unsafe.Sizeof(1<<10)
-       _ = unsafe.Sizeof(1 /* ERROR overflows */ <<1000)
+       _ = unsafe.Sizeof(1 << /* ERROR constant shift overflow */ 1000)
        _ = unsafe.Sizeof(nil /* ERROR untyped nil */ )
        unsafe /* ERROR not used */ .Sizeof(x)
 
diff --git a/libgo/go/go/types/testdata/check/chans.go2 b/libgo/go/go/types/testdata/check/chans.go2
new file mode 100644 (file)
index 0000000..fad2bce
--- /dev/null
@@ -0,0 +1,62 @@
+package chans
+
+import "runtime"
+
+// Ranger returns a Sender and a Receiver. The Receiver provides a
+// Next method to retrieve values. The Sender provides a Send method
+// to send values and a Close method to stop sending values. The Next
+// method indicates when the Sender has been closed, and the Send
+// method indicates when the Receiver has been freed.
+//
+// This is a convenient way to exit a goroutine sending values when
+// the receiver stops reading them.
+func Ranger[T any]() (*Sender[T], *Receiver[T]) {
+       c := make(chan T)
+       d := make(chan bool)
+       s := &Sender[T]{values: c, done: d}
+       r := &Receiver[T]{values: c, done: d}
+       runtime.SetFinalizer(r, r.finalize)
+       return s, r
+}
+
+// A sender is used to send values to a Receiver.
+type Sender[T any] struct {
+       values chan<- T
+       done <-chan bool
+}
+
+// Send sends a value to the receiver. It returns whether any more
+// values may be sent; if it returns false the value was not sent.
+func (s *Sender[T]) Send(v T) bool {
+       select {
+       case s.values <- v:
+               return true
+       case <-s.done:
+               return false
+       }
+}
+
+// Close tells the receiver that no more values will arrive.
+// After Close is called, the Sender may no longer be used.
+func (s *Sender[T]) Close() {
+       close(s.values)
+}
+
+// A Receiver receives values from a Sender.
+type Receiver[T any] struct {
+       values <-chan T
+       done chan<- bool
+}
+
+// Next returns the next value from the channel. The bool result
+// indicates whether the value is valid, or whether the Sender has
+// been closed and no more values will be received.
+func (r *Receiver[T]) Next() (T, bool) {
+       v, ok := <-r.values
+       return v, ok
+}
+
+// finalize is a finalizer for the receiver.
+func (r *Receiver[T]) finalize() {
+       close(r.done)
+}
similarity index 93%
rename from libgo/go/go/types/testdata/const0.src
rename to libgo/go/go/types/testdata/check/const0.src
index adbbf2863b03e55e0dfaeea860551f88dd7f1b1e..5608b1549ba8d7774c2463fa9faab3702673f061 100644 (file)
@@ -348,3 +348,16 @@ const _ = unsafe.Sizeof(func() {
        assert(one == 1)
        assert(iota == 0)
 })
+
+// untyped constants must not get arbitrarily large
+const prec = 512 // internal maximum precision for integers
+const maxInt = (1<<(prec/2) - 1) * (1<<(prec/2) + 1) // == 1<<prec - 1
+
+const _ = maxInt + /* ERROR constant addition overflow */ 1
+const _ = -maxInt - /* ERROR constant subtraction overflow */ 1
+const _ = maxInt ^ /* ERROR constant bitwise XOR overflow */ -1
+const _ = maxInt * /* ERROR constant multiplication overflow */ 2
+const _ = maxInt << /* ERROR constant shift overflow */ 2
+const _ = 1 << /* ERROR constant shift overflow */ prec
+
+const _ = ^ /* ERROR constant bitwise complement overflow */ maxInt
similarity index 92%
rename from libgo/go/go/types/testdata/const1.src
rename to libgo/go/go/types/testdata/check/const1.src
index d82770464fa73a4b84cf6dcc35f2583eed5ba3cf..c9128017cf72518f73adc4a535cc89f2418541db 100644 (file)
@@ -6,6 +6,8 @@
 
 package const1
 
+import "math"
+
 const(
        mi = ^int(0)
        mu = ^uint(0)
@@ -43,7 +45,12 @@ const (
 
 const (
        smallestFloat32 = 1.0 / (1<<(127 - 1 + 23))
-       smallestFloat64 = 1.0 / (1<<(1023 - 1 + 52))
+       // TODO(gri) The compiler limits integers to 512 bit and thus
+       //           we cannot compute the value (1<<(1023 - 1 + 52))
+       //           without overflow. For now we match the compiler.
+       //           See also issue #44057.
+       // smallestFloat64 = 1.0 / (1<<(1023 - 1 + 52))
+       smallestFloat64 = math.SmallestNonzeroFloat64
 )
 
 const (
@@ -53,7 +60,12 @@ const (
 
 const (
        maxFloat32 = 1<<127 * (1<<24 - 1) / (1.0<<23)
-       maxFloat64 = 1<<1023 * (1<<53 - 1) / (1.0<<52)
+       // TODO(gri) The compiler limits integers to 512 bit and thus
+       //           we cannot compute the value 1<<1023
+       //           without overflow. For now we match the compiler.
+       //           See also issue #44057.
+       // maxFloat64 = 1<<1023 * (1<<53 - 1) / (1.0<<52)
+       maxFloat64 = math.MaxFloat64
 )
 
 const (
similarity index 90%
rename from libgo/go/go/types/testdata/decls0.src
rename to libgo/go/go/types/testdata/check/decls0.src
index 5501b659153a83a899f40f1dbaf1e77d0594d7f5..5ad8f53f65ab20b5e21b753119df153a67bd206b 100644 (file)
@@ -184,11 +184,13 @@ func f1(x f1 /* ERROR "not a type" */ ) {}
 func f2(x *f2 /* ERROR "not a type" */ ) {}
 func f3() (x f3 /* ERROR "not a type" */ ) { return }
 func f4() (x *f4 /* ERROR "not a type" */ ) { return }
+// TODO(#43215) this should be detected as a cycle error
+func f5([unsafe.Sizeof(f5)]int) {}
 
-func (S0) m1 /* ERROR illegal cycle */ (x S0 /* ERROR value .* is not a type */ .m1) {}
-func (S0) m2 /* ERROR illegal cycle */ (x *S0 /* ERROR value .* is not a type */ .m2) {}
-func (S0) m3 /* ERROR illegal cycle */ () (x S0 /* ERROR value .* is not a type */ .m3) { return }
-func (S0) m4 /* ERROR illegal cycle */ () (x *S0 /* ERROR value .* is not a type */ .m4) { return }
+func (S0) m1 (x S0 /* ERROR value .* is not a type */ .m1) {}
+func (S0) m2 (x *S0 /* ERROR value .* is not a type */ .m2) {}
+func (S0) m3 () (x S0 /* ERROR value .* is not a type */ .m3) { return }
+func (S0) m4 () (x *S0 /* ERROR value .* is not a type */ .m4) { return }
 
 // interfaces may not have any blank methods
 type BlankI interface {
similarity index 95%
rename from libgo/go/go/types/testdata/expr3.src
rename to libgo/go/go/types/testdata/check/expr3.src
index e6777aad2bbb4fc5bf4a895a406d9c62756287b9..0525a5a33ae09012954ff7aa7c8b0d1e89733356 100644 (file)
@@ -34,6 +34,7 @@ func indexes() {
        _ = a[9]
        _ = a[10 /* ERROR "index .* out of bounds" */ ]
        _ = a[1 /* ERROR "overflows" */ <<100]
+       _ = a[1<< /* ERROR "constant shift overflow" */ 1000] // no out-of-bounds follow-on error
        _ = a[10:]
        _ = a[:10]
        _ = a[10:10]
@@ -492,26 +493,26 @@ func _calls() {
        f1(0)
        f1(x)
        f1(10.0)
-       f1() /* ERROR "too few arguments" */
+       f1() /* ERROR "not enough arguments" */
        f1(x, y /* ERROR "too many arguments" */ )
        f1(s /* ERROR "cannot use .* in argument" */ )
        f1(x ... /* ERROR "cannot use ..." */ )
        f1(g0 /* ERROR "used as value" */ ())
        f1(g1())
-       f1(g2 /* ERROR "cannot use g2" */ /* ERROR "too many arguments" */ ())
+       f1(g2 /* ERROR "too many arguments" */ ())
 
-       f2() /* ERROR "too few arguments" */
-       f2(3.14) /* ERROR "too few arguments" */
+       f2() /* ERROR "not enough arguments" */
+       f2(3.14) /* ERROR "not enough arguments" */
        f2(3.14, "foo")
        f2(x /* ERROR "cannot use .* in argument" */ , "foo")
        f2(g0 /* ERROR "used as value" */ ())
-       f2(g1 /* ERROR "cannot use .* in argument" */ ()) /* ERROR "too few arguments" */
+       f2(g1()) /* ERROR "not enough arguments" */
        f2(g2())
 
-       fs() /* ERROR "too few arguments" */
+       fs() /* ERROR "not enough arguments" */
        fs(g0 /* ERROR "used as value" */ ())
        fs(g1 /* ERROR "cannot use .* in argument" */ ())
-       fs(g2 /* ERROR "cannot use .* in argument" */ /* ERROR "too many arguments" */ ())
+       fs(g2 /* ERROR "too many arguments" */ ())
        fs(gs())
 
        fv()
@@ -519,7 +520,7 @@ func _calls() {
        fv(s /* ERROR "cannot use .* in argument" */ )
        fv(s...)
        fv(x /* ERROR "cannot use" */ ...)
-       fv(1, s... /* ERROR "can only use ... with matching parameter" */ )
+       fv(1, s /* ERROR "too many arguments" */ ...)
        fv(gs /* ERROR "cannot use .* in argument" */ ())
        fv(gs /* ERROR "cannot use .* in argument" */ ()...)
 
@@ -528,7 +529,7 @@ func _calls() {
        t.fm(1, 2.0, x)
        t.fm(s /* ERROR "cannot use .* in argument" */ )
        t.fm(g1())
-       t.fm(1, s... /* ERROR "can only use ... with matching parameter" */ )
+       t.fm(1, s /* ERROR "too many arguments" */ ...)
        t.fm(gs /* ERROR "cannot use .* in argument" */ ())
        t.fm(gs /* ERROR "cannot use .* in argument" */ ()...)
 
@@ -536,7 +537,7 @@ func _calls() {
        T.fm(t, 1, 2.0, x)
        T.fm(t, s /* ERROR "cannot use .* in argument" */ )
        T.fm(t, g1())
-       T.fm(t, 1, s... /* ERROR "can only use ... with matching parameter" */ )
+       T.fm(t, 1, s /* ERROR "too many arguments" */ ...)
        T.fm(t, gs /* ERROR "cannot use .* in argument" */ ())
        T.fm(t, gs /* ERROR "cannot use .* in argument" */ ()...)
 
@@ -545,7 +546,7 @@ func _calls() {
        i.fm(1, 2.0, x)
        i.fm(s /* ERROR "cannot use .* in argument" */ )
        i.fm(g1())
-       i.fm(1, s... /* ERROR "can only use ... with matching parameter" */ )
+       i.fm(1, s /* ERROR "too many arguments" */ ...)
        i.fm(gs /* ERROR "cannot use .* in argument" */ ())
        i.fm(gs /* ERROR "cannot use .* in argument" */ ()...)
 
diff --git a/libgo/go/go/types/testdata/check/go1_12.src b/libgo/go/go/types/testdata/check/go1_12.src
new file mode 100644 (file)
index 0000000..1e529f1
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check Go language version-specific errors.
+
+package go1_12 // go1.12
+
+// numeric literals
+const (
+       _ = 1_000 // ERROR "underscores in numeric literals requires go1.13 or later"
+       _ = 0b111 // ERROR "binary literals requires go1.13 or later"
+       _ = 0o567 // ERROR "0o/0O-style octal literals requires go1.13 or later"
+       _ = 0xabc // ok
+       _ = 0x0p1 // ERROR "hexadecimal floating-point literals requires go1.13 or later"
+
+       _ = 0B111 // ERROR "binary"
+       _ = 0O567 // ERROR "octal"
+       _ = 0Xabc // ok
+       _ = 0X0P1 // ERROR "hexadecimal floating-point"
+
+       _ = 1_000i // ERROR "underscores"
+       _ = 0b111i // ERROR "binary"
+       _ = 0o567i // ERROR "octal"
+       _ = 0xabci // ERROR "hexadecimal floating-point"
+       _ = 0x0p1i // ERROR "hexadecimal floating-point"
+)
+
+// signed shift counts
+var (
+       s int
+       _ = 1 << s // ERROR "invalid operation: signed shift count s \(variable of type int\) requires go1.13 or later"
+       _ = 1 >> s // ERROR "signed shift count"
+)
+
diff --git a/libgo/go/go/types/testdata/check/go1_13.src b/libgo/go/go/types/testdata/check/go1_13.src
new file mode 100644 (file)
index 0000000..6aa1364
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check Go language version-specific errors.
+
+package go1_13 // go1.13
+
+// interface embedding
+
+type I interface { m() }
+
+type _ interface {
+       m()
+       I // ERROR "duplicate method m"
+}
+
+type _ interface {
+       I
+       I // ERROR "duplicate method m"
+}
+
diff --git a/libgo/go/go/types/testdata/check/go1_16.src b/libgo/go/go/types/testdata/check/go1_16.src
new file mode 100644 (file)
index 0000000..fdf5c99
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check Go language version-specific errors.
+
+package go1_16 // go1.16
+
+type Slice []byte
+type Array [8]byte
+
+var s Slice
+var p = (*Array)(s /* ERROR requires go1.17 or later */ )
diff --git a/libgo/go/go/types/testdata/check/go1_8.src b/libgo/go/go/types/testdata/check/go1_8.src
new file mode 100644 (file)
index 0000000..3ead1e9
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check Go language version-specific errors.
+
+package go1_8 // go1.8
+
+// type alias declarations
+type any = /* ERROR type aliases requires go1.9 or later */ interface{}
+
similarity index 95%
rename from libgo/go/go/types/testdata/importdecl0a.src
rename to libgo/go/go/types/testdata/check/importdecl0/importdecl0a.src
index e96fca3cdd56fa86cb284276e78412b3c5f296a8..5ceb96e1fada684387f20c56894810a772875de2 100644 (file)
@@ -10,7 +10,7 @@ import (
        // we can have multiple blank imports (was bug)
        _ "math"
        _ "net/rpc"
-       init /* ERROR "cannot declare init" */ "fmt"
+       init /* ERROR "cannot import package as init" */ "fmt"
        // reflect defines a type "flag" which shows up in the gc export data
        "reflect"
        . /* ERROR "imported but not used" */ "reflect"
similarity index 93%
rename from libgo/go/go/types/testdata/importdecl0b.src
rename to libgo/go/go/types/testdata/check/importdecl0/importdecl0b.src
index 6844e7098233eb5488c860c03f5a3274f1b467d5..55690423b66ec675506fed232501d3fbd9c67b5c 100644 (file)
@@ -8,7 +8,7 @@ import "math"
 import m "math"
 
 import . "testing" // declares T in file scope
-import . /* ERROR "imported but not used" */ "unsafe"
+import . /* ERROR .unsafe. imported but not used */ "unsafe"
 import . "fmt"     // declares Println in file scope
 
 import (
similarity index 77%
rename from libgo/go/go/types/testdata/importdecl1b.src
rename to libgo/go/go/types/testdata/check/importdecl1/importdecl1b.src
index ee70bbd8e73f787c8aa3b3d792f5673d0f0aacbb..43a7bcd75396cbb34ab5ab3c1e354f9d1f4642b7 100644 (file)
@@ -4,7 +4,7 @@
 
 package importdecl1
 
-import . /* ERROR "imported but not used" */ "unsafe"
+import . /* ERROR .unsafe. imported but not used */ "unsafe"
 
 type B interface {
        A
diff --git a/libgo/go/go/types/testdata/check/issues.go2 b/libgo/go/go/types/testdata/check/issues.go2
new file mode 100644 (file)
index 0000000..8994164
--- /dev/null
@@ -0,0 +1,256 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains regression tests for bugs found.
+
+package p
+
+import "io"
+import "context"
+
+// Interfaces are always comparable (though the comparison may panic at runtime).
+func eql[T comparable](x, y T) bool {
+       return x == y
+}
+
+func _() {
+       var x interface{}
+       var y interface{ m() }
+       eql(x, y /* ERROR does not match */ ) // interfaces of different types
+       eql(x, x)
+       eql(y, y)
+       eql(y, nil)
+       eql[io.Reader](nil, nil)
+}
+
+// If we have a receiver of pointer type (below: *T) we must ignore
+// the pointer in the implementation of the method lookup because
+// the type bound of T is an interface and pointer to interface types
+// have no methods and then the lookup would fail.
+type C[T any] interface {
+    m()
+}
+
+// using type bound C
+func _[T C[T]](x *T) {
+       x.m()
+}
+
+// using an interface literal as bound
+func _[T interface{ m() }](x *T) {
+       x.m()
+}
+
+// In a generic function body all method calls will be pointer method calls.
+// If necessary, the function body will insert temporary variables, not seen
+// by the user, in order to get an addressable variable to use to call the method.
+// Thus, assume an argument type for a generic function to be the type of addressable
+// values in the generic function when checking if the argument type satisfies the
+// generic function's type bound.
+func f2[_ interface{ m1(); m2() }]()
+
+type T struct{}
+func (T) m1()
+func (*T) m2()
+
+func _() {
+       // TODO(rFindley) this error should be positioned on the 'T'.
+       f2 /* ERROR wrong method signature */ [T]()
+       f2[*T]()
+}
+
+// When a type parameter is used as an argument to instantiate a parameterized
+// type with a type list constraint, all of the type argument's types in its
+// bound, but at least one (!), must be in the type list of the bound of the
+// corresponding parameterized type's type parameter.
+type T1[P interface{type uint}] struct{}
+
+func _[P any]() {
+    _ = T1[P /* ERROR P has no type constraints */ ]{}
+}
+
+// This is the original (simplified) program causing the same issue.
+type Unsigned interface {
+       type uint
+}
+
+type T2[U Unsigned] struct {
+    s U
+}
+
+func (u T2[U]) Add1() U {
+    return u.s + 1
+}
+
+func NewT2[U any]() T2[U /* ERROR U has no type constraints */ ] {
+    return T2[U /* ERROR U has no type constraints */ ]{}
+}
+
+func _() {
+    u := NewT2[string]()
+    _ = u.Add1()
+}
+
+// When we encounter an instantiated type such as Elem[T] we must
+// not "expand" the instantiation when the type to be instantiated
+// (Elem in this case) is not yet fully set up.
+type Elem[T any] struct {
+       next *Elem[T]
+       list *List[T]
+}
+
+type List[T any] struct {
+       root Elem[T]
+}
+
+func (l *List[T]) Init() {
+       l.root.next = &l.root
+}
+
+// This is the original program causing the same issue.
+type Element2[TElem any] struct {
+       next, prev *Element2[TElem]
+       list *List2[TElem]
+       Value TElem
+}
+
+type List2[TElem any] struct {
+       root Element2[TElem]
+       len  int
+}
+
+func (l *List2[TElem]) Init() *List2[TElem] {
+       l.root.next = &l.root
+       l.root.prev = &l.root
+       l.len = 0
+       return l
+}
+
+// Self-recursive instantiations must work correctly.
+type A[P any] struct { _ *A[P] }
+
+type AB[P any] struct { _ *BA[P] }
+type BA[P any] struct { _ *AB[P] }
+
+// And a variation that also caused a problem with an
+// unresolved underlying type.
+type Element3[TElem any] struct {
+       next, prev *Element3[TElem]
+       list *List3[TElem]
+       Value TElem
+}
+
+func (e *Element3[TElem]) Next() *Element3[TElem] {
+       if p := e.next; e.list != nil && p != &e.list.root {
+               return p
+       }
+       return nil
+}
+
+type List3[TElem any] struct {
+       root Element3[TElem]
+       len  int
+}
+
+// Infinite generic type declarations must lead to an error.
+type inf1[T any] struct{ _ inf1 /* ERROR illegal cycle */ [T] }
+type inf2[T any] struct{ inf2 /* ERROR illegal cycle */ [T] }
+
+// The implementation of conversions T(x) between integers and floating-point
+// numbers checks that both T and x have either integer or floating-point
+// type. When the type of T or x is a type parameter, the respective simple
+// predicate disjunction in the implementation was wrong because if a type list
+// contains both an integer and a floating-point type, the type parameter is
+// neither an integer or a floating-point number.
+func convert[T1, T2 interface{type int, uint, float32}](v T1) T2 {
+       return T2(v)
+}
+
+func _() {
+       convert[int, uint](5)
+}
+
+// When testing binary operators, for +, the operand types must either be
+// both numeric, or both strings. The implementation had the same problem
+// with this check as the conversion issue above (issue #39623).
+
+func issue39623[T interface{type int, string}](x, y T) T {
+       return x + y
+}
+
+// Simplified, from https://go2goplay.golang.org/p/efS6x6s-9NI:
+func Sum[T interface{type int, string}](s []T) (sum T) {
+       for _, v := range s {
+               sum += v
+       }
+       return
+}
+
+// Assignability of an unnamed pointer type to a type parameter that
+// has a matching underlying type.
+func _[T interface{}, PT interface{type *T}] (x T) PT {
+    return &x
+}
+
+// Indexing of generic types containing type parameters in their type list:
+func at[T interface{ type []E }, E interface{}](x T, i int) E {
+        return x[i]
+}
+
+// A generic type inside a function acts like a named type. Its underlying
+// type is itself, its "operational type" is defined by the type list in
+// the tybe bound, if any.
+func _[T interface{type int}](x T) {
+       type myint int
+       var _ int = int(x)
+       var _ T = 42
+       var _ T = T(myint(42))
+}
+
+// Indexing a generic type with an array type bound checks length.
+// (Example by mdempsky@.)
+func _[T interface { type [10]int }](x T) {
+       _ = x[9] // ok
+       _ = x[20 /* ERROR out of bounds */ ]
+}
+
+// Pointer indirection of a generic type.
+func _[T interface{ type *int }](p T) int {
+       return *p
+}
+
+// Channel sends and receives on generic types.
+func _[T interface{ type chan int }](ch T) int {
+       ch <- 0
+       return <- ch
+}
+
+// Calling of a generic variable.
+func _[T interface{ type func() }](f T) {
+       f()
+       go f()
+}
+
+// We must compare against the underlying type of type list entries
+// when checking if a constraint is satisfied by a type. The under-
+// lying type of each type list entry must be computed after the
+// interface has been instantiated as its typelist may contain a
+// type parameter that was substituted with a defined type.
+// Test case from an (originally) failing example.
+
+type sliceOf[E any] interface{ type []E }
+
+func append[T interface{}, S sliceOf[T], T2 interface{ type T }](s S, t ...T2) S
+
+var f           func()
+var cancelSlice []context.CancelFunc
+var _ = append[context.CancelFunc, []context.CancelFunc, context.CancelFunc](cancelSlice, f)
+
+// A generic function must be instantiated with a type, not a value.
+
+func g[T any](T) T
+
+var _ = g[int]
+var _ = g[nil /* ERROR is not a type */ ]
+var _ = g(0)
similarity index 94%
rename from libgo/go/go/types/testdata/issues.src
rename to libgo/go/go/types/testdata/check/issues.src
index e0c5d7a37cf48f339273e849b07e9c88c2610aec..55fe220337f47fba7342b0cb324ffc1c6301792b 100644 (file)
@@ -6,7 +6,7 @@ package issues
 
 import (
        "fmt"
-       syn "cmd/compile/internal/syntax"
+       syn "regexp/syntax"
        t1 "text/template"
        t2 "html/template"
 )
@@ -325,14 +325,14 @@ func issue28281c(a, b, c ... /* ERROR can only use ... with final parameter */ i
 func issue28281d(... /* ERROR can only use ... with final parameter */ int, int)
 func issue28281e(a, b, c  ... /* ERROR can only use ... with final parameter */ int, d int)
 func issue28281f(... /* ERROR can only use ... with final parameter */ int, ... /* ERROR can only use ... with final parameter */ int, int)
-func (... /* ERROR expected type */ TT) f()
-func issue28281g() (... /* ERROR expected type */ TT)
+func (... /* ERROR can only use ... with final parameter */ TT) f()
+func issue28281g() (... /* ERROR can only use ... with final parameter */ TT)
 
 // Issue #26234: Make various field/method lookup errors easier to read by matching cmd/compile's output
-func issue26234a(f *syn.File) {
+func issue26234a(f *syn.Prog) {
        // The error message below should refer to the actual package name (syntax)
        // not the local package name (syn).
-       f.foo /* ERROR f.foo undefined \(type \*syntax.File has no field or method foo\) */
+       f.foo /* ERROR f\.foo undefined \(type \*syntax\.Prog has no field or method foo\) */
 }
 
 type T struct {
@@ -357,9 +357,15 @@ func issue35895() {
        var _ T = 0 // ERROR cannot use 0 \(untyped int constant\) as T
 
        // There is only one package with name syntax imported, only use the (global) package name in error messages.
-       var _ *syn.File = 0 // ERROR cannot use 0 \(untyped int constant\) as \*syntax.File
+       var _ *syn.Prog = 0 // ERROR cannot use 0 \(untyped int constant\) as \*syntax.Prog
 
        // Because both t1 and t2 have the same global package name (template),
        // qualify packages with full path name in this case.
-       var _ t1.Template = t2 /* ERROR cannot use .* \(value of type "html/template".Template\) as "text/template".Template */ .Template{}
+       var _ t1.Template = t2 /* ERROR cannot use .* \(value of type .html/template.\.Template\) as .text/template.\.Template */ .Template{}
+}
+
+func issue42989(s uint) {
+       var m map[int]string
+       delete(m, 1<<s)
+       delete(m, 1.<<s)
 }
diff --git a/libgo/go/go/types/testdata/check/linalg.go2 b/libgo/go/go/types/testdata/check/linalg.go2
new file mode 100644 (file)
index 0000000..0d27603
--- /dev/null
@@ -0,0 +1,83 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package linalg
+
+import "math"
+
+// Numeric is type bound that matches any numeric type.
+// It would likely be in a constraints package in the standard library.
+type Numeric interface {
+       type int, int8, int16, int32, int64,
+               uint, uint8, uint16, uint32, uint64, uintptr,
+               float32, float64,
+               complex64, complex128
+}
+
+func DotProduct[T Numeric](s1, s2 []T) T {
+       if len(s1) != len(s2) {
+               panic("DotProduct: slices of unequal length")
+       }
+       var r T
+       for i := range s1 {
+               r += s1[i] * s2[i]
+       }
+       return r
+}
+
+// NumericAbs matches numeric types with an Abs method.
+type NumericAbs[T any] interface {
+       Numeric
+
+       Abs() T
+}
+
+// AbsDifference computes the absolute value of the difference of
+// a and b, where the absolute value is determined by the Abs method.
+func AbsDifference[T NumericAbs[T]](a, b T) T {
+       d := a - b
+       return d.Abs()
+}
+
+// OrderedNumeric is a type bound that matches numeric types that support the < operator.
+type OrderedNumeric interface {
+       type int, int8, int16, int32, int64,
+               uint, uint8, uint16, uint32, uint64, uintptr,
+               float32, float64
+}
+
+// Complex is a type bound that matches the two complex types, which do not have a < operator.
+type Complex interface {
+       type complex64, complex128
+}
+
+// OrderedAbs is a helper type that defines an Abs method for
+// ordered numeric types.
+type OrderedAbs[T OrderedNumeric] T
+
+func (a OrderedAbs[T]) Abs() OrderedAbs[T] {
+       if a < 0 {
+               return -a
+       }
+       return a
+}
+
+// ComplexAbs is a helper type that defines an Abs method for
+// complex types.
+type ComplexAbs[T Complex] T
+
+func (a ComplexAbs[T]) Abs() ComplexAbs[T] {
+       r := float64(real(a))
+       i := float64(imag(a))
+       d := math.Sqrt(r * r + i * i)
+       return ComplexAbs[T](complex(d, 0))
+}
+
+func OrderedAbsDifference[T OrderedNumeric](a, b T) T {
+       return T(AbsDifference(OrderedAbs[T](a), OrderedAbs[T](b)))
+}
+
+func ComplexAbsDifference[T Complex](a, b T) T {
+       return T(AbsDifference(ComplexAbs[T](a), ComplexAbs[T](b)))
+}
diff --git a/libgo/go/go/types/testdata/check/main.go2 b/libgo/go/go/types/testdata/check/main.go2
new file mode 100644 (file)
index 0000000..65e9aa2
--- /dev/null
@@ -0,0 +1,7 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main[ /* ERROR "func main must have no type parameters" */ T any]() {}
diff --git a/libgo/go/go/types/testdata/check/main.src b/libgo/go/go/types/testdata/check/main.src
new file mode 100644 (file)
index 0000000..f892938
--- /dev/null
@@ -0,0 +1,9 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main()
+func /* ERROR "no arguments and no return values" */ main /* ERROR redeclared */ (int)
+func /* ERROR "no arguments and no return values" */ main /* ERROR redeclared */ () int
diff --git a/libgo/go/go/types/testdata/check/map.go2 b/libgo/go/go/types/testdata/check/map.go2
new file mode 100644 (file)
index 0000000..814d953
--- /dev/null
@@ -0,0 +1,113 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package orderedmap provides an ordered map, implemented as a binary tree.
+package orderedmap
+
+// TODO(gri) fix imports for tests
+import "chans" // ERROR could not import
+
+// Map is an ordered map.
+type Map[K, V any] struct {
+       root    *node[K, V]
+       compare func(K, K) int
+}
+
+// node is the type of a node in the binary tree.
+type node[K, V any] struct {
+       key         K
+       val         V
+       left, right *node[K, V]
+}
+
+// New returns a new map.
+func New[K, V any](compare func(K, K) int) *Map[K, V] {
+        return &Map[K, V]{compare: compare}
+}
+
+// find looks up key in the map, and returns either a pointer
+// to the node holding key, or a pointer to the location where
+// such a node would go.
+func (m *Map[K, V]) find(key K) **node[K, V] {
+       pn := &m.root
+       for *pn != nil {
+               switch cmp := m.compare(key, (*pn).key); {
+               case cmp < 0:
+                       pn = &(*pn).left
+               case cmp > 0:
+                       pn = &(*pn).right
+               default:
+                       return pn
+               }
+       }
+       return pn
+}
+
+// Insert inserts a new key/value into the map.
+// If the key is already present, the value is replaced.
+// Returns true if this is a new key, false if already present.
+func (m *Map[K, V]) Insert(key K, val V) bool {
+       pn := m.find(key)
+       if *pn != nil {
+               (*pn).val = val
+               return false
+       }
+        *pn = &node[K, V]{key: key, val: val}
+       return true
+}
+
+// Find returns the value associated with a key, or zero if not present.
+// The found result reports whether the key was found.
+func (m *Map[K, V]) Find(key K) (V, bool) {
+       pn := m.find(key)
+       if *pn == nil {
+               var zero V // see the discussion of zero values, above
+               return zero, false
+       }
+       return (*pn).val, true
+}
+
+// keyValue is a pair of key and value used when iterating.
+type keyValue[K, V any] struct {
+       key K
+       val V
+}
+
+// InOrder returns an iterator that does an in-order traversal of the map.
+func (m *Map[K, V]) InOrder() *Iterator[K, V] {
+       sender, receiver := chans.Ranger[keyValue[K, V]]()
+       var f func(*node[K, V]) bool
+       f = func(n *node[K, V]) bool {
+               if n == nil {
+                       return true
+               }
+               // Stop sending values if sender.Send returns false,
+               // meaning that nothing is listening at the receiver end.
+               return f(n.left) &&
+                        sender.Send(keyValue[K, V]{n.key, n.val}) &&
+                       f(n.right)
+       }
+       go func() {
+               f(m.root)
+               sender.Close()
+       }()
+       return &Iterator[K, V]{receiver}
+}
+
+// Iterator is used to iterate over the map.
+type Iterator[K, V any] struct {
+       r *chans.Receiver[keyValue[K, V]]
+}
+
+// Next returns the next key and value pair, and a boolean indicating
+// whether they are valid or whether we have reached the end.
+func (it *Iterator[K, V]) Next() (K, V, bool) {
+       keyval, ok := it.r.Next()
+       if !ok {
+               var zerok K
+               var zerov V
+               return zerok, zerov, false
+       }
+       return keyval.key, keyval.val, true
+}
diff --git a/libgo/go/go/types/testdata/check/map2.go2 b/libgo/go/go/types/testdata/check/map2.go2
new file mode 100644 (file)
index 0000000..2833445
--- /dev/null
@@ -0,0 +1,146 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file is like map.go2, but instead if importing chans, it contains
+// the necessary functionality at the end of the file.
+
+// Package orderedmap provides an ordered map, implemented as a binary tree.
+package orderedmap
+
+// Map is an ordered map.
+type Map[K, V any] struct {
+       root    *node[K, V]
+       compare func(K, K) int
+}
+
+// node is the type of a node in the binary tree.
+type node[K, V any] struct {
+       key         K
+       val         V
+       left, right *node[K, V]
+}
+
+// New returns a new map.
+func New[K, V any](compare func(K, K) int) *Map[K, V] {
+        return &Map[K, V]{compare: compare}
+}
+
+// find looks up key in the map, and returns either a pointer
+// to the node holding key, or a pointer to the location where
+// such a node would go.
+func (m *Map[K, V]) find(key K) **node[K, V] {
+       pn := &m.root
+       for *pn != nil {
+               switch cmp := m.compare(key, (*pn).key); {
+               case cmp < 0:
+                       pn = &(*pn).left
+               case cmp > 0:
+                       pn = &(*pn).right
+               default:
+                       return pn
+               }
+       }
+       return pn
+}
+
+// Insert inserts a new key/value into the map.
+// If the key is already present, the value is replaced.
+// Returns true if this is a new key, false if already present.
+func (m *Map[K, V]) Insert(key K, val V) bool {
+       pn := m.find(key)
+       if *pn != nil {
+               (*pn).val = val
+               return false
+       }
+       *pn = &node[K, V]{key: key, val: val}
+       return true
+}
+
+// Find returns the value associated with a key, or zero if not present.
+// The found result reports whether the key was found.
+func (m *Map[K, V]) Find(key K) (V, bool) {
+       pn := m.find(key)
+       if *pn == nil {
+               var zero V // see the discussion of zero values, above
+               return zero, false
+       }
+       return (*pn).val, true
+}
+
+// keyValue is a pair of key and value used when iterating.
+type keyValue[K, V any] struct {
+       key K
+       val V
+}
+
+// InOrder returns an iterator that does an in-order traversal of the map.
+func (m *Map[K, V]) InOrder() *Iterator[K, V] {
+       sender, receiver := chans_Ranger[keyValue[K, V]]()
+       var f func(*node[K, V]) bool
+       f = func(n *node[K, V]) bool {
+               if n == nil {
+                       return true
+               }
+               // Stop sending values if sender.Send returns false,
+               // meaning that nothing is listening at the receiver end.
+               return f(n.left) &&
+                        sender.Send(keyValue[K, V]{n.key, n.val}) &&
+                       f(n.right)
+       }
+       go func() {
+               f(m.root)
+               sender.Close()
+       }()
+       return &Iterator[K, V]{receiver}
+}
+
+// Iterator is used to iterate over the map.
+type Iterator[K, V any] struct {
+       r *chans_Receiver[keyValue[K, V]]
+}
+
+// Next returns the next key and value pair, and a boolean indicating
+// whether they are valid or whether we have reached the end.
+func (it *Iterator[K, V]) Next() (K, V, bool) {
+       keyval, ok := it.r.Next()
+       if !ok {
+               var zerok K
+               var zerov V
+               return zerok, zerov, false
+       }
+       return keyval.key, keyval.val, true
+}
+
+// chans
+
+func chans_Ranger[T any]() (*chans_Sender[T], *chans_Receiver[T])
+
+// A sender is used to send values to a Receiver.
+type chans_Sender[T any] struct {
+       values chan<- T
+       done <-chan bool
+}
+
+func (s *chans_Sender[T]) Send(v T) bool {
+       select {
+       case s.values <- v:
+               return true
+       case <-s.done:
+               return false
+       }
+}
+
+func (s *chans_Sender[T]) Close() {
+       close(s.values)
+}
+
+type chans_Receiver[T any] struct {
+       values <-chan T
+       done chan<- bool
+}
+
+func (r *chans_Receiver[T]) Next() (T, bool) {
+       v, ok := <-r.values
+       return v, ok
+}
\ No newline at end of file
similarity index 98%
rename from libgo/go/go/types/testdata/shifts.src
rename to libgo/go/go/types/testdata/check/shifts.src
index c9a38ae169ea095d0ad030c5b6238541e6319acc..4d3c59a50fd9bd59f7a056da8fd1ba0b09e04d99 100644 (file)
@@ -20,7 +20,7 @@ func shifts0() {
                // This depends on the exact spec wording which is not
                // done yet.
                // TODO(gri) revisit and adjust when spec change is done
-               _ = 1<<- /* ERROR "truncated to uint" */ 1.0
+               _ = 1<<- /* ERROR "negative shift count" */ 1.0
                _ = 1<<1075 /* ERROR "invalid shift" */
                _ = 2.0<<1
                _ = 1<<1.0
@@ -60,11 +60,13 @@ func shifts1() {
                _ uint = 1 << u
                _ float32 = 1 /* ERROR "must be integer" */ << u
 
-               // for issue 14822
+               // issue #14822
+               _ = 1<<( /* ERROR "overflows uint" */ 1<<64)
                _ = 1<<( /* ERROR "invalid shift count" */ 1<<64-1)
-               _ = 1<<( /* ERROR "invalid shift count" */ 1<<64)
-               _ = u<<(1<<63) // valid
-               _ = u<<(1<<64) // valid
+
+               // issue #43697
+               _ = u<<( /* ERROR "overflows uint" */ 1<<64)
+               _ = u<<(1<<64-1)
        )
 }
 
diff --git a/libgo/go/go/types/testdata/check/slices.go2 b/libgo/go/go/types/testdata/check/slices.go2
new file mode 100644 (file)
index 0000000..2bacd1c
--- /dev/null
@@ -0,0 +1,68 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package slices implements various slice algorithms.
+package slices
+
+// Map turns a []T1 to a []T2 using a mapping function.
+func Map[T1, T2 any](s []T1, f func(T1) T2) []T2 {
+       r := make([]T2, len(s))
+       for i, v := range s {
+               r[i] = f(v)
+       }
+       return r
+}
+
+// Reduce reduces a []T1 to a single value using a reduction function.
+func Reduce[T1, T2 any](s []T1, initializer T2, f func(T2, T1) T2) T2 {
+       r := initializer
+       for _, v := range s {
+               r = f(r, v)
+       }
+       return r
+}
+
+// Filter filters values from a slice using a filter function.
+func Filter[T any](s []T, f func(T) bool) []T {
+       var r []T
+       for _, v := range s {
+               if f(v) {
+                       r = append(r, v)
+               }
+       }
+       return r
+}
+
+// Example uses
+
+func limiter(x int) byte {
+       switch {
+       case x < 0:
+               return 0
+       default:
+               return byte(x)
+       case x > 255:
+               return 255
+       }
+}
+
+var input = []int{-4, 68954, 7, 44, 0, -555, 6945}
+var limited1 = Map[int, byte](input, limiter)
+var limited2 = Map(input, limiter) // using type inference
+
+func reducer(x float64, y int) float64 {
+       return x + float64(y)
+}
+
+var reduced1 = Reduce[int, float64](input, 0, reducer)
+var reduced2 = Reduce(input, 1i /* ERROR overflows */, reducer) // using type inference
+var reduced3 = Reduce(input, 1, reducer) // using type inference
+
+func filter(x int) bool {
+       return x&1 != 0
+}
+
+var filtered1 = Filter[int](input, filter)
+var filtered2 = Filter(input, filter) // using type inference
+
similarity index 98%
rename from libgo/go/go/types/testdata/stmt0.src
rename to libgo/go/go/types/testdata/check/stmt0.src
index 13777292a9439ba15bed008574a6316014ce8f73..76b6e70d63bacd703871aedfc02778196a7b5e6a 100644 (file)
@@ -86,11 +86,11 @@ func assignments1() {
 
        g := func(int, bool){}
        var m map[int]int
-       g(m[0]) /* ERROR "too few arguments" */
+       g(m[0]) /* ERROR "not enough arguments" */
 
        // assignments to _
        _ = nil /* ERROR "use of untyped nil" */
-       _ = 1 /* ERROR overflow */ <<1000
+       _ = 1  << /* ERROR constant shift overflow */ 1000
        (_) = 0
 }
 
@@ -143,11 +143,11 @@ func issue6487() {
 }
 
 func issue6766a() {
-       a, a /* ERROR redeclared */ := 1, 2
+       a, a /* ERROR a repeated on left side of := */ := 1, 2
        _ = a
-       a, b, b /* ERROR redeclared */ := 1, 2, 3
+       a, b, b /* ERROR b repeated on left side of := */ := 1, 2, 3
        _ = b
-       c, c /* ERROR redeclared */, b := 1, 2, 3
+       c, c /* ERROR c repeated on left side of := */, b := 1, 2, 3
        _ = c
        a, b := /* ERROR no new variables */ 1, 2
 }
@@ -886,7 +886,7 @@ func rangeloops1() {
                ee = e
                _ = ee
        }
-       for _ = range sc /* ERROR "cannot range over send-only channel" */ {}
+       for _ = range sc /* ERROR "cannot range over" */ {}
        for _ = range rc {}
 
        // constant strings
diff --git a/libgo/go/go/types/testdata/check/tinference.go2 b/libgo/go/go/types/testdata/check/tinference.go2
new file mode 100644 (file)
index 0000000..31338b3
--- /dev/null
@@ -0,0 +1,108 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tinferenceB
+
+import "strconv"
+
+type any interface{}
+
+// TODO(rFindley) the below partially applied function types should probably
+//                not be permitted (spec question).
+
+func f0[A any, B interface{type C}, C interface{type D}, D interface{type A}](A, B, C, D)
+func _() {
+       f := f0[string]
+       f("a", "b", "c", "d")
+       f0("a", "b", "c", "d")
+}
+
+func f1[A any, B interface{type A}](A, B)
+func _() {
+       f := f1[int]
+       f(int(0), int(0))
+       f1(int(0), int(0))
+}
+
+func f2[A any, B interface{type []A}](A, B)
+func _() {
+       f := f2[byte]
+       f(byte(0), []byte{})
+       f2(byte(0), []byte{})
+}
+
+func f3[A any, B interface{type C}, C interface{type *A}](A, B, C)
+func _() {
+       f := f3[int]
+       var x int
+       f(x, &x, &x)
+       f3(x, &x, &x)
+}
+
+func f4[A any, B interface{type []C}, C interface{type *A}](A, B, C)
+func _() {
+       f := f4[int]
+       var x int
+       f(x, []*int{}, &x)
+       f4(x, []*int{}, &x)
+}
+
+func f5[A interface{type struct{b B; c C}}, B any, C interface{type *B}](x B) A
+func _() {
+       x := f5(1.2)
+       var _ float64 = x.b
+       var _ float64 = *x.c
+}
+
+func f6[A any, B interface{type struct{f []A}}](B) A
+func _() {
+       x := f6(struct{f []string}{})
+       var _ string = x
+}
+
+// TODO(gri) Need to flag invalid recursive constraints. At the
+// moment these cause infinite recursions and stack overflow.
+// func f7[A interface{type B}, B interface{type A}]()
+
+// More realistic examples
+
+func Double[S interface{ type []E }, E interface{ type int, int8, int16, int32, int64 }](s S) S {
+       r := make(S, len(s))
+       for i, v := range s {
+               r[i] = v + v
+       }
+       return r
+}
+
+type MySlice []int
+
+var _ = Double(MySlice{1})
+
+// From the draft design.
+
+type Setter[B any] interface {
+       Set(string)
+       type *B
+}
+
+func FromStrings[T interface{}, PT Setter[T]](s []string) []T {
+       result := make([]T, len(s))
+       for i, v := range s {
+               // The type of &result[i] is *T which is in the type list
+               // of Setter2, so we can convert it to PT.
+               p := PT(&result[i])
+               // PT has a Set method.
+               p.Set(v)
+       }
+       return result
+}
+
+type Settable int
+
+func (p *Settable) Set(s string) {
+       i, _ := strconv.Atoi(s) // real code should not ignore the error
+       *p = Settable(i)
+}
+
+var _ = FromStrings[Settable]([]string{"1", "2"})
diff --git a/libgo/go/go/types/testdata/check/tmp.go2 b/libgo/go/go/types/testdata/check/tmp.go2
new file mode 100644 (file)
index 0000000..dae78ca
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file is meant as "dumping ground" for debugging code.
+
+package p
+
+// fun test case
+type C[P interface{m()}] P
+
+func (r C[P]) m() { r.m() }
+
+func f[T interface{m(); n()}](x T) {
+       y := C[T](x)
+       y.m()
+}
diff --git a/libgo/go/go/types/testdata/check/todos.go2 b/libgo/go/go/types/testdata/check/todos.go2
new file mode 100644 (file)
index 0000000..09e9b4c
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file is meant as "dumping ground" for tests
+// of not yet implemented features. It will grow and
+// shrink over time.
+
+package p
+
+// When using []'s instead of ()'s for type parameters
+// we don't need extra parentheses for some composite
+// literal types.
+type T1[P any] struct{}
+type T2[P, Q any] struct{}
+
+func _() {
+   _ = []T1[int]{}            // ok if we use []'s
+   _ = [](T1[int]){}
+   _ = []T2[int, string]{}    // ok if we use []'s
+   _ = [](T2[int, string]){}
+}
diff --git a/libgo/go/go/types/testdata/check/typeinst.go2 b/libgo/go/go/types/testdata/check/typeinst.go2
new file mode 100644 (file)
index 0000000..3184a4b
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type myInt int
+
+// Parameterized type declarations
+
+type T1[P any] P
+
+type T2[P any] struct {
+        f P
+        g int // int should still be in scope chain
+}
+
+type List[P any] []P
+
+// Alias type declarations cannot have type parameters. Syntax error.
+type A1[P any] = /* ERROR cannot be alias */ P
+
+// But an alias may refer to a generic, uninstantiated type.
+type A2 = List
+var _ A2[int]
+var _ A2 /* ERROR without instantiation */
+
+type A3 = List[int]
+var _ A3
+
+// Parameterized type instantiations
+
+var x int
+type _ x /* ERROR not a type */ [int]
+
+type _ int /* ERROR not a generic type */ []
+type _ myInt /* ERROR not a generic type */ []
+
+// TODO(gri) better error messages
+type _ T1 /* ERROR got 0 arguments but 1 type parameters */ []
+type _ T1[x /* ERROR not a type */ ]
+type _ T1 /* ERROR got 2 arguments but 1 type parameters */ [int, float32]
+
+var _ T2[int] = T2[int]{}
+
+var _ List[int] = []int{1, 2, 3}
+var _ List[[]int] = [][]int{{1, 2, 3}}
+var _ List[List[List[int]]]
+
+// Parameterized types containing parameterized types
+
+type T3[P any] List[P]
+
+var _ T3[int] = T3[int](List[int]{1, 2, 3})
+
+// Self-recursive generic types are not permitted
+
+type self1[P any] self1 /* ERROR illegal cycle */ [P]
+type self2[P any] *self2[P] // this is ok
diff --git a/libgo/go/go/types/testdata/check/typeinst2.go2 b/libgo/go/go/types/testdata/check/typeinst2.go2
new file mode 100644 (file)
index 0000000..6e2104a
--- /dev/null
@@ -0,0 +1,256 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type List[E any] []E
+var _ List[List[List[int]]]
+var _ List[List[List[int]]] = []List[List[int]]{}
+
+type (
+       T1[P1 any] struct {
+               f1 T2[P1, float32]
+       }
+
+       T2[P2, P3 any] struct {
+               f2 P2
+               f3 P3
+       }
+)
+
+func _() {
+       var x1 T1[int]
+       var x2 T2[int, float32]
+
+       x1.f1.f2 = 0
+       x1.f1 = x2
+}
+
+type T3[P any] T1[T2[P, P]]
+
+func _() {
+       var x1 T3[int]
+       var x2 T2[int, int]
+       x1.f1.f2 = x2
+}
+
+func f[P any] (x P) List[P] {
+       return List[P]{x}
+}
+
+var (
+       _ []int = f(0)
+       _ []float32 = f[float32](10)
+       _ List[complex128] = f(1i)
+       _ []List[int] = f(List[int]{})
+        _ List[List[int]] = []List[int]{}
+        _ = []List[int]{}
+)
+
+// Parameterized types with methods
+
+func (l List[E]) Head() (_ E, _ bool) {
+       if len(l) > 0 {
+               return l[0], true
+       }
+       return
+}
+
+// A test case for instantiating types with other types (extracted from map.go2)
+
+type Pair[K any] struct {
+       key K
+}
+
+type Receiver[T any] struct {
+       values T
+}
+
+type Iterator[K any] struct {
+       r Receiver[Pair[K]]
+}
+
+func Values [T any] (r Receiver[T]) T {
+        return r.values
+}
+
+func (it Iterator[K]) Next() K {
+        return Values[Pair[K]](it.r).key
+}
+
+// A more complex test case testing type bounds (extracted from linalg.go2 and reduced to essence)
+
+type NumericAbs[T any] interface {
+       Abs() T
+}
+
+func AbsDifference[T NumericAbs[T]](x T)
+
+type OrderedAbs[T any] T
+
+func (a OrderedAbs[T]) Abs() OrderedAbs[T]
+
+func OrderedAbsDifference[T any](x T) {
+       AbsDifference(OrderedAbs[T](x))
+}
+
+// same code, reduced to essence
+
+func g[P interface{ m() P }](x P)
+
+type T4[P any] P
+
+func (_ T4[P]) m() T4[P]
+
+func _[Q any](x Q) {
+       g(T4[Q](x))
+}
+
+// Another test case that caused  problems in the past
+
+type T5[_ interface { a() }, _ interface{}] struct{}
+
+type A[P any] struct{ x P }
+
+func (_ A[P]) a() {}
+
+var _ T5[A[int], int]
+
+// Invoking methods with parameterized receiver types uses
+// type inference to determine the actual type arguments matching
+// the receiver type parameters from the actual receiver argument.
+// Go does implicit address-taking and dereferenciation depending
+// on the actual receiver and the method's receiver type. To make
+// type inference work, the type-checker matches "pointer-ness"
+// of the actual receiver and the method's receiver type.
+// The following code tests this mechanism.
+
+type R1[A any] struct{}
+func (_ R1[A]) vm()
+func (_ *R1[A]) pm()
+
+func _[T any](r R1[T], p *R1[T]) {
+       r.vm()
+       r.pm()
+       p.vm()
+       p.pm()
+}
+
+type R2[A, B any] struct{}
+func (_ R2[A, B]) vm()
+func (_ *R2[A, B]) pm()
+
+func _[T any](r R2[T, int], p *R2[string, T]) {
+       r.vm()
+       r.pm()
+       p.vm()
+       p.pm()
+}
+
+// An interface can (explicitly) declare at most one type list.
+type _ interface {
+       m0()
+       type int, string, bool
+       type /* ERROR multiple type lists */ float32, float64
+       m1()
+       m2()
+       type /* ERROR multiple type lists */ complex64, complex128
+       type /* ERROR multiple type lists */ rune
+}
+
+// Interface type lists may contain each type at most once.
+// (If there are multiple lists, we assume the author intended
+// for them to be all in a single list, and we report the error
+// as well.)
+type _ interface {
+       type int, int /* ERROR duplicate type int */
+       type /* ERROR multiple type lists */ int /* ERROR duplicate type int */
+}
+
+type _ interface {
+       type struct{f int}, struct{g int}, struct /* ERROR duplicate type */ {f int}
+}
+
+// Interface type lists can contain any type, incl. *Named types.
+// Verify that we use the underlying type to compute the operational type.
+type MyInt int
+func add1[T interface{type MyInt}](x T) T {
+       return x + 1
+}
+
+type MyString string
+func double[T interface{type MyInt, MyString}](x T) T {
+       return x + x
+}
+
+// Embedding of interfaces with type lists leads to interfaces
+// with type lists that are the intersection of the embedded
+// type lists.
+
+type E0 interface {
+       type int, bool, string
+}
+
+type E1 interface {
+       type int, float64, string
+}
+
+type E2 interface {
+       type float64
+}
+
+type I0 interface {
+       E0
+}
+
+func f0[T I0]()
+var _ = f0[int]
+var _ = f0[bool]
+var _ = f0[string]
+var _ = f0[float64 /* ERROR does not satisfy I0 */ ]
+
+type I01 interface {
+       E0
+       E1
+}
+
+func f01[T I01]()
+var _ = f01[int]
+var _ = f01[bool /* ERROR does not satisfy I0 */ ]
+var _ = f01[string]
+var _ = f01[float64 /* ERROR does not satisfy I0 */ ]
+
+type I012 interface {
+       E0
+       E1
+       E2
+}
+
+func f012[T I012]()
+var _ = f012[int /* ERROR does not satisfy I012 */ ]
+var _ = f012[bool /* ERROR does not satisfy I012 */ ]
+var _ = f012[string /* ERROR does not satisfy I012 */ ]
+var _ = f012[float64 /* ERROR does not satisfy I012 */ ]
+
+type I12 interface {
+       E1
+       E2
+}
+
+func f12[T I12]()
+var _ = f12[int /* ERROR does not satisfy I12 */ ]
+var _ = f12[bool /* ERROR does not satisfy I12 */ ]
+var _ = f12[string /* ERROR does not satisfy I12 */ ]
+var _ = f12[float64]
+
+type I0_ interface {
+       E0
+       type int
+}
+
+func f0_[T I0_]()
+var _ = f0_[int]
+var _ = f0_[bool /* ERROR does not satisfy I0_ */ ]
+var _ = f0_[string /* ERROR does not satisfy I0_ */ ]
+var _ = f0_[float64 /* ERROR does not satisfy I0_ */ ]
diff --git a/libgo/go/go/types/testdata/check/typeparams.go2 b/libgo/go/go/types/testdata/check/typeparams.go2
new file mode 100644 (file)
index 0000000..d95e02e
--- /dev/null
@@ -0,0 +1,433 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// import "io" // for type assertion tests
+
+// The predeclared identifier "any" is only visible as a constraint
+// in a type parameter list.
+var _ any // ERROR undeclared
+func _[_ any /* ok here */ , _ interface{any /* ERROR undeclared */ }](any /* ERROR undeclared */ ) {
+        var _ any /* ERROR undeclared */
+}
+
+func identity[T any](x T) T { return x }
+
+func _[_ any](x int) int
+func _[T any](T /* ERROR redeclared */ T)()
+func _[T, T /* ERROR redeclared */ any]()
+
+// Constraints (incl. any) may be parenthesized.
+func _[_ (any)]() {}
+func _[_ (interface{})]() {}
+
+func reverse[T any](list []T) []T {
+        rlist := make([]T, len(list))
+        i := len(list)
+        for _, x := range list {
+                i--
+                rlist[i] = x
+        }
+        return rlist
+}
+
+var _ = reverse /* ERROR cannot use generic function reverse */
+var _ = reverse[int, float32 /* ERROR got 2 type arguments */ ] ([]int{1, 2, 3})
+var _ = reverse[int]([ /* ERROR cannot use */ ]float32{1, 2, 3})
+var f = reverse[chan int]
+var _ = f(0 /* ERROR cannot use 0 .* as \[\]chan int */ )
+
+func swap[A, B any](a A, b B) (B, A) { return b, a }
+
+var _ = swap /* ERROR single value is expected */ [int, float32](1, 2)
+var f32, i = swap[int, float32](swap[float32, int](1, 2))
+var _ float32 = f32
+var _ int = i
+
+func swapswap[A, B any](a A, b B) (A, B) {
+        return swap[B, A](b, a)
+}
+
+type F[A, B any] func(A, B) (B, A)
+
+func min[T interface{ type int }](x, y T) T {
+        if x < y {
+                return x
+        }
+        return y
+}
+
+func _[T interface{type int, float32}](x, y T) bool { return x < y }
+func _[T any](x, y T) bool { return x /* ERROR cannot compare */ < y }
+func _[T interface{type int, float32, bool}](x, y T) bool { return x /* ERROR cannot compare */ < y }
+
+func _[T C1[T]](x, y T) bool { return x /* ERROR cannot compare */ < y }
+func _[T C2[T]](x, y T) bool { return x < y }
+
+type C1[T any] interface{}
+type C2[T any] interface{ type int, float32 }
+
+func new[T any]() *T {
+        var x T
+        return &x
+}
+
+var _ = new /* ERROR cannot use generic function new */
+var _ *int = new[int]()
+
+func _[T any](map[T /* ERROR incomparable map key type T \(missing comparable constraint\) */]int) // w/o constraint we don't know if T is comparable
+
+func f1[T1 any](struct{T1}) int
+var _ = f1[int](struct{T1}{})
+type T1 = int
+
+func f2[t1 any](struct{t1; x float32}) int
+var _ = f2[t1](struct{t1; x float32}{})
+type t1 = int
+
+
+func f3[A, B, C any](A, struct{x B}, func(A, struct{x B}, *C)) int
+
+var _ = f3[int, rune, bool](1, struct{x rune}{}, nil)
+
+// indexing
+
+func _[T any] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] }
+func _[T interface{ type int }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] }
+func _[T interface{ type string }] (x T, i int) { _ = x[i] }
+func _[T interface{ type []int }] (x T, i int) { _ = x[i] }
+func _[T interface{ type [10]int, *[20]int, map[int]int }] (x T, i int) { _ = x[i] }
+func _[T interface{ type string, []byte }] (x T, i int) { _ = x[i] }
+func _[T interface{ type []int, [1]rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] }
+func _[T interface{ type string, []rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] }
+
+// indexing with various combinations of map types in type lists (see issue #42616)
+func _[T interface{ type []E, map[int]E }, E any](x T, i int) { _ = x[i] }
+func _[T interface{ type []E }, E any](x T, i int) { _ = &x[i] }
+func _[T interface{ type map[int]E }, E any](x T, i int) { _, _ = x[i] } // comma-ok permitted
+func _[T interface{ type []E, map[int]E }, E any](x T, i int) { _ = &x /* ERROR cannot take address */ [i] }
+func _[T interface{ type []E, map[int]E, map[uint]E }, E any](x T, i int) { _ = x /* ERROR cannot index */ [i] } // different map element types
+func _[T interface{ type []E, map[string]E }, E any](x T, i int) { _ = x[i /* ERROR cannot use i */ ] }
+
+// slicing
+// TODO(gri) implement this
+
+func _[T interface{ type string }] (x T, i, j, k int) { _ = x /* ERROR invalid operation */ [i:j:k] }
+
+// len/cap built-ins
+
+func _[T any](x T) { _ = len(x /* ERROR invalid argument */ ) }
+func _[T interface{ type int }](x T) { _ = len(x /* ERROR invalid argument */ ) }
+func _[T interface{ type string, []byte, int }](x T) { _ = len(x /* ERROR invalid argument */ ) }
+func _[T interface{ type string }](x T) { _ = len(x) }
+func _[T interface{ type [10]int }](x T) { _ = len(x) }
+func _[T interface{ type []byte }](x T) { _ = len(x) }
+func _[T interface{ type map[int]int }](x T) { _ = len(x) }
+func _[T interface{ type chan int }](x T) { _ = len(x) }
+func _[T interface{ type string, []byte, chan int }](x T) { _ = len(x) }
+
+func _[T any](x T) { _ = cap(x /* ERROR invalid argument */ ) }
+func _[T interface{ type int }](x T) { _ = cap(x /* ERROR invalid argument */ ) }
+func _[T interface{ type string, []byte, int }](x T) { _ = cap(x /* ERROR invalid argument */ ) }
+func _[T interface{ type string }](x T) { _ = cap(x /* ERROR invalid argument */ ) }
+func _[T interface{ type [10]int }](x T) { _ = cap(x) }
+func _[T interface{ type []byte }](x T) { _ = cap(x) }
+func _[T interface{ type map[int]int }](x T) { _ = cap(x /* ERROR invalid argument */ ) }
+func _[T interface{ type chan int }](x T) { _ = cap(x) }
+func _[T interface{ type []byte, chan int }](x T) { _ = cap(x) }
+
+// range iteration
+
+func _[T interface{}](x T) {
+        for range x /* ERROR cannot range */ {}
+}
+
+func _[T interface{ type string, []string }](x T) {
+        for range x {}
+        for i := range x { _ = i }
+        for i, _ := range x { _ = i }
+        for i, e := range x /* ERROR must have the same element type */ { _ = i }
+        for _, e := range x /* ERROR must have the same element type */ {}
+        var e rune
+        _ = e
+        for _, (e) = range x /* ERROR must have the same element type */ {}
+}
+
+
+func _[T interface{ type string, []rune, map[int]rune }](x T) {
+        for _, e := range x { _ = e }
+        for i, e := range x { _ = i; _ = e }
+}
+
+func _[T interface{ type string, []rune, map[string]rune }](x T) {
+        for _, e := range x { _ = e }
+        for i, e := range x /* ERROR must have the same key type */ { _ = e }
+}
+
+func _[T interface{ type string, chan int }](x T) {
+        for range x {}
+        for i := range x { _ = i }
+        for i, _ := range x { _ = i } // TODO(gri) should get an error here: channels only return one value
+}
+
+func _[T interface{ type string, chan<-int }](x T) {
+        for i := range x /* ERROR send-only channel */ { _ = i }
+}
+
+// type inference checks
+
+var _ = new /* ERROR cannot infer T */ ()
+
+func f4[A, B, C any](A, B) C
+
+var _ = f4 /* ERROR cannot infer C */ (1, 2)
+var _ = f4[int, float32, complex128](1, 2)
+
+func f5[A, B, C any](A, []*B, struct{f []C}) int
+
+var _ = f5[int, float32, complex128](0, nil, struct{f []complex128}{})
+var _ = f5 /* ERROR cannot infer */ (0, nil, struct{f []complex128}{})
+var _ = f5(0, []*float32{new[float32]()}, struct{f []complex128}{})
+
+func f6[A any](A, []A) int
+
+var _ = f6(0, nil)
+
+func f6nil[A any](A) int
+
+var _ = f6nil /* ERROR cannot infer */ (nil)
+
+// type inference with variadic functions
+
+func f7[T any](...T) T
+
+var _ int = f7 /* ERROR cannot infer T */ ()
+var _ int = f7(1)
+var _ int = f7(1, 2)
+var _ int = f7([]int{}...)
+var _ int = f7 /* ERROR cannot use */ ([]float64{}...)
+var _ float64 = f7([]float64{}...)
+var _ = f7[float64](1, 2.3)
+var _ = f7(float64(1), 2.3)
+var _ = f7(1, 2.3 /* ERROR does not match */ )
+var _ = f7(1.2, 3 /* ERROR does not match */ )
+
+func f8[A, B any](A, B, ...B) int
+
+var _ = f8(1) /* ERROR not enough arguments */
+var _ = f8(1, 2.3)
+var _ = f8(1, 2.3, 3.4, 4.5)
+var _ = f8(1, 2.3, 3.4, 4 /* ERROR does not match */ )
+var _ = f8[int, float64](1, 2.3, 3.4, 4)
+
+var _ = f8[int, float64](0, 0, nil...) // test case for #18268
+
+// init functions cannot have type parameters
+
+func init() {}
+func init[/* ERROR func init must have no type parameters */ _ any]() {}
+func init[/* ERROR func init must have no type parameters */ P any]() {}
+
+type T struct {}
+
+func (T) m1() {}
+func (T) m2[ /* ERROR methods cannot have type parameters */ _ any]() {}
+func (T) m3[ /* ERROR methods cannot have type parameters */ P any]() {}
+
+// type inference across parameterized types
+
+type S1[P any] struct { f P }
+
+func f9[P any](x S1[P])
+
+func _() {
+        f9[int](S1[int]{42})
+       f9(S1[int]{42})
+}
+
+type S2[A, B, C any] struct{}
+
+func f10[X, Y, Z any](a S2[X, int, Z], b S2[X, Y, bool])
+
+func _[P any]() {
+        f10[int, float32, string](S2[int, int, string]{}, S2[int, float32, bool]{})
+        f10(S2[int, int, string]{}, S2[int, float32, bool]{})
+        f10(S2[P, int, P]{}, S2[P, float32, bool]{})
+}
+
+// corner case for type inference
+// (was bug: after instanting f11, the type-checker didn't mark f11 as non-generic)
+
+func f11[T any]()
+
+func _() {
+       f11[int]()
+}
+
+// the previous example was extracted from
+
+func f12[T interface{m() T}]()
+
+type A[T any] T
+
+func (a A[T]) m() A[T]
+
+func _[T any]() {
+       f12[A[T]]()
+}
+
+// method expressions
+
+func (_ S1[P]) m()
+
+func _() {
+       m := S1[int].m
+       m(struct { f int }{42})
+}
+
+func _[T any] (x T) {
+        m := S1[T].m
+        m(S1[T]{x})
+}
+
+// type parameters in methods (generalization)
+
+type R0 struct{}
+
+func (R0) _[ /* ERROR methods cannot have type parameters */ T any](x T)
+func (R0 /* ERROR invalid receiver */ ) _[ /* ERROR methods cannot have type parameters */ R0 any]() // scope of type parameters starts at "func"
+
+type R1[A, B any] struct{}
+
+func (_ R1[A, B]) m0(A, B)
+func (_ R1[A, B]) m1[ /* ERROR methods cannot have type parameters */ T any](A, B, T) T
+func (_ R1 /* ERROR not a generic type */ [R1, _]) _()
+func (_ R1[A, B]) _[ /* ERROR methods cannot have type parameters */ A /* ERROR redeclared */ any](B)
+
+func _() {
+        var r R1[int, string]
+        r.m1[rune](42, "foo", 'a')
+        r.m1[rune](42, "foo", 1.2 /* ERROR cannot use .* as rune .* \(truncated\) */)
+        r.m1(42, "foo", 1.2) // using type inference
+        var _ float64 = r.m1(42, "foo", 1.2)
+}
+
+type I1[A any] interface {
+        m1(A)
+}
+
+var _ I1[int] = r1[int]{}
+
+type r1[T any] struct{}
+
+func (_ r1[T]) m1(T)
+
+type I2[A, B any] interface {
+        m1(A)
+        m2(A) B
+}
+
+var _ I2[int, float32] = R2[int, float32]{}
+
+type R2[P, Q any] struct{}
+
+func (_ R2[X, Y]) m1(X)
+func (_ R2[X, Y]) m2(X) Y
+
+// type assertions and type switches over generic types
+// NOTE: These are currently disabled because it's unclear what the correct
+// approach is, and one can always work around by assigning the variable to
+// an interface first.
+
+// // ReadByte1 corresponds to the ReadByte example in the draft design.
+// func ReadByte1[T io.Reader](r T) (byte, error) {
+//     if br, ok := r.(io.ByteReader); ok {
+//             return br.ReadByte()
+//     }
+//     var b [1]byte
+//     _, err := r.Read(b[:])
+//     return b[0], err
+// }
+//
+// // ReadBytes2 is like ReadByte1 but uses a type switch instead.
+// func ReadByte2[T io.Reader](r T) (byte, error) {
+//         switch br := r.(type) {
+//         case io.ByteReader:
+//                 return br.ReadByte()
+//         }
+//     var b [1]byte
+//     _, err := r.Read(b[:])
+//     return b[0], err
+// }
+//
+// // type assertions and type switches over generic types are strict
+// type I3 interface {
+//         m(int)
+// }
+//
+// type I4 interface {
+//         m() int // different signature from I3.m
+// }
+//
+// func _[T I3](x I3, p T) {
+//         // type assertions and type switches over interfaces are not strict
+//         _ = x.(I4)
+//         switch x.(type) {
+//         case I4:
+//         }
+// 
+//         // type assertions and type switches over generic types are strict
+//         _ = p /* ERROR cannot have dynamic type I4 */.(I4)
+//         switch p.(type) {
+//         case I4 /* ERROR cannot have dynamic type I4 */ :
+//         }
+// }
+
+// type assertions and type switches over generic types lead to errors for now
+
+func _[T any](x T) {
+       _ = x /* ERROR not an interface */ .(int)
+       switch x /* ERROR not an interface */ .(type) {
+       }
+
+       // work-around
+       var t interface{} = x
+       _ = t.(int)
+       switch t.(type) {
+       }
+}
+
+func _[T interface{type int}](x T) {
+       _ = x /* ERROR not an interface */ .(int)
+       switch x /* ERROR not an interface */ .(type) {
+       }
+
+       // work-around
+       var t interface{} = x
+       _ = t.(int)
+       switch t.(type) {
+       }
+}
+
+// error messages related to type bounds mention those bounds
+type C[P any] interface{}
+
+func _[P C[P]] (x P) {
+       x.m /* ERROR x.m undefined */ ()
+}
+
+type I interface {}
+
+func _[P I] (x P) {
+       x.m /* ERROR interface I has no method m */ ()
+}
+
+func _[P interface{}] (x P) {
+       x.m /* ERROR type bound for P has no method m */ ()
+}
+
+func _[P any] (x P) {
+       x.m /* ERROR type bound for P has no method m */ ()
+}
diff --git a/libgo/go/go/types/testdata/examples/functions.go2 b/libgo/go/go/types/testdata/examples/functions.go2
new file mode 100644 (file)
index 0000000..a053471
--- /dev/null
@@ -0,0 +1,214 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file shows some examples of type-parameterized functions.
+
+package p
+
+// Reverse is a generic function that takes a []T argument and
+// reverses that slice in place.
+func Reverse[T any](list []T) {
+       i := 0
+       j := len(list)-1
+       for i < j {
+               list[i], list[j] = list[j], list[i]
+               i++
+               j--
+       }
+}
+
+func _() {
+       // Reverse can be called with an explicit type argument.
+       Reverse[int](nil)
+       Reverse[string]([]string{"foo", "bar"})
+       Reverse[struct{x, y int}]([]struct{x, y int}{{1, 2}, {2, 3}, {3, 4}})
+
+       // Since the type parameter is used for an incoming argument,
+       // it can be inferred from the provided argument's type.
+       Reverse([]string{"foo", "bar"})
+       Reverse([]struct{x, y int}{{1, 2}, {2, 3}, {3, 4}})
+
+       // But the incoming argument must have a type, even if it's a
+       // default type. An untyped nil won't work.
+       // Reverse(nil) // this won't type-check
+
+       // A typed nil will work, though.
+       Reverse([]int(nil))
+}
+
+// Certain functions, such as the built-in `new` could be written using
+// type parameters.
+func new[T any]() *T {
+       var x T
+       return &x
+}
+
+// When calling our own `new`, we need to pass the type parameter
+// explicitly since there is no (value) argument from which the
+// result type could be inferred. We don't try to infer the
+// result type from the assignment to keep things simple and
+// easy to understand.
+var _ = new[int]()
+var _ *float64 = new[float64]() // the result type is indeed *float64
+
+// A function may have multiple type parameters, of course.
+func foo[A, B, C any](a A, b []B, c *C) B {
+       // do something here
+       return b[0]
+}
+
+// As before, we can pass type parameters explicitly.
+var s = foo[int, string, float64](1, []string{"first"}, new[float64]())
+
+// Or we can use type inference.
+var _ float64 = foo(42, []float64{1.0}, &s)
+
+// Type inference works in a straight-forward manner even
+// for variadic functions.
+func variadic[A, B any](A, B, ...B) int
+
+// var _ = variadic(1) // ERROR not enough arguments
+var _ = variadic(1, 2.3)
+var _ = variadic(1, 2.3, 3.4, 4.5)
+var _ = variadic[int, float64](1, 2.3, 3.4, 4)
+
+// Type inference also works in recursive function calls where
+// the inferred type is the type parameter of the caller.
+func f1[T any](x T) {
+       f1(x)
+}
+
+func f2a[T any](x, y T) {
+       f2a(x, y)
+}
+
+func f2b[T any](x, y T) {
+       f2b(y, x)
+}
+
+func g2a[P, Q any](x P, y Q) {
+       g2a(x, y)
+}
+
+func g2b[P, Q any](x P, y Q) {
+       g2b(y, x)
+}
+
+// Here's an example of a recursive function call with variadic
+// arguments and type inference inferring the type parameter of
+// the caller (i.e., itself).
+func max[T interface{ type int }](x ...T) T {
+       var x0 T
+       if len(x) > 0 {
+               x0 = x[0]
+       }
+       if len(x) > 1 {
+               x1 := max(x[1:]...)
+               if x1 > x0 {
+                       return x1
+               }
+       }
+       return x0
+}
+
+// When inferring channel types, the channel direction is ignored
+// for the purpose of type inference. Once the type has been in-
+// fered, the usual parameter passing rules are applied.
+// Thus even if a type can be inferred successfully, the function
+// call may not be valid.
+
+func fboth[T any](chan T)
+func frecv[T any](<-chan T)
+func fsend[T any](chan<- T)
+
+func _() {
+       var both chan int
+       var recv <-chan int
+       var send chan<-int
+
+       fboth(both)
+       fboth(recv /* ERROR cannot use */ )
+       fboth(send /* ERROR cannot use */ )
+
+       frecv(both)
+       frecv(recv)
+       frecv(send /* ERROR cannot use */ )
+
+       fsend(both)
+       fsend(recv /* ERROR cannot use */)
+       fsend(send)
+}
+
+func ffboth[T any](func(chan T))
+func ffrecv[T any](func(<-chan T))
+func ffsend[T any](func(chan<- T))
+
+func _() {
+       var both func(chan int)
+       var recv func(<-chan int)
+       var send func(chan<- int)
+
+       ffboth(both)
+       ffboth(recv /* ERROR cannot use */ )
+       ffboth(send /* ERROR cannot use */ )
+
+       ffrecv(both /* ERROR cannot use */ )
+       ffrecv(recv)
+       ffrecv(send /* ERROR cannot use */ )
+
+       ffsend(both /* ERROR cannot use */ )
+       ffsend(recv /* ERROR cannot use */ )
+       ffsend(send)
+}
+
+// When inferring elements of unnamed composite parameter types,
+// if the arguments are defined types, use their underlying types.
+// Even though the matching types are not exactly structurally the
+// same (one is a type literal, the other a named type), because
+// assignment is permitted, parameter passing is permitted as well,
+// so type inference should be able to handle these cases well.
+
+func g1[T any]([]T)
+func g2[T any]([]T, T)
+func g3[T any](*T, ...T)
+
+func _() {
+       type intSlize []int
+       g1([]int{})
+       g1(intSlize{})
+       g2(nil, 0)
+
+       type myString string
+       var s1 string
+       g3(nil, "1", myString("2"), "3")
+       g3(&s1, "1", myString /* ERROR does not match */ ("2"), "3")
+
+       type myStruct struct{x int}
+       var s2 myStruct
+       g3(nil, struct{x int}{}, myStruct{})
+       g3(&s2, struct{x int}{}, myStruct{})
+       g3(nil, myStruct{}, struct{x int}{})
+       g3(&s2, myStruct{}, struct{x int}{})
+}
+
+// Here's a realistic example.
+
+func append[T any](s []T, t ...T) []T
+
+func _() {
+       var f func()
+       type Funcs []func()
+       var funcs Funcs
+       _ = append(funcs, f)
+}
+
+// Generic type declarations cannot have empty type parameter lists
+// (that would indicate a slice type). Thus, generic functions cannot
+// have empty type parameter lists, either. This is a syntax error.
+
+func h[] /* ERROR empty type parameter list */ ()
+
+func _() {
+       h /* ERROR cannot index */ [] /* ERROR operand */ ()
+}
diff --git a/libgo/go/go/types/testdata/examples/inference.go2 b/libgo/go/go/types/testdata/examples/inference.go2
new file mode 100644 (file)
index 0000000..b4f3369
--- /dev/null
@@ -0,0 +1,101 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file shows some examples of type inference.
+
+package p
+
+type Ordered interface {
+       type int, float64, string
+}
+
+func min[T Ordered](x, y T) T
+
+func _() {
+       // min can be called with explicit instantiation.
+       _ = min[int](1, 2)
+
+       // Alternatively, the type argument can be inferred from
+       // one of the arguments. Untyped arguments will be considered
+       // last.
+       var x int
+       _ = min(x, x)
+       _ = min(x, 1)
+       _ = min(x, 1.0)
+       _ = min(1, 2)
+       _ = min(1, 2.3 /* ERROR default type float64 .* does not match */ )
+
+       var y float64
+       _ = min(1, y)
+       _ = min(1.2, y)
+       _ = min(1.2, 3.4)
+       _ = min(1.2, 3 /* ERROR default type int .* does not match */ )
+
+       var s string
+       _ = min(s, "foo")
+       _ = min("foo", "bar")
+}
+
+func mixed[T1, T2, T3 any](T1, T2, T3)
+
+func _() {
+       // mixed can be called with explicit instantiation.
+       mixed[int, string, bool](0, "", false)
+
+       // Alternatively, partial type arguments may be provided
+       // (from left to right), and the other may be inferred.
+       mixed[int, string](0, "", false)
+       mixed[int](0, "", false)
+       mixed(0, "", false)
+
+       // Provided type arguments always take precedence over
+       // inferred types.
+       mixed[int, string](1.1 /* ERROR cannot use 1.1 */ , "", false)
+}
+
+func related1[Slice interface{type []Elem}, Elem any](s Slice, e Elem)
+
+func _() {
+       // related1 can be called with explicit instantiation.
+       var si []int
+       related1[[]int, int](si, 0)
+
+       // Alternatively, the 2nd type argument can be inferred
+       // from the first one through constraint type inference.
+       var ss []string
+       _ = related1[[]string]
+       related1[[]string](ss, "foo")
+
+       // A type argument inferred from another explicitly provided
+       // type argument overrides whatever value argument type is given.
+       related1[[]string](ss, 0 /* ERROR cannot use 0 */ )
+
+       // A type argument may be inferred from a value argument
+       // and then help infer another type argument via constraint
+       // type inference.
+       related1(si, 0)
+       related1(si, "foo" /* ERROR cannot use "foo" */ )
+}
+
+func related2[Elem any, Slice interface{type []Elem}](e Elem, s Slice)
+
+func _() {
+       // related2 can be called with explicit instantiation.
+       var si []int
+       related2[int, []int](0, si)
+
+       // Alternatively, the 2nd type argument can be inferred
+       // from the first one through constraint type inference.
+       var ss []string
+       _ = related2[string]
+       related2[string]("foo", ss)
+
+       // A type argument may be inferred from a value argument
+       // and then help infer another type argument via constraint
+       // type inference. Untyped arguments are always considered
+       // last.
+       related2(1.2, []float64{})
+       related2(1.0, []int{})
+       related2 /* ERROR does not satisfy */ (float64(1.0), []int{})
+}
diff --git a/libgo/go/go/types/testdata/examples/methods.go2 b/libgo/go/go/types/testdata/examples/methods.go2
new file mode 100644 (file)
index 0000000..76c6539
--- /dev/null
@@ -0,0 +1,96 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file shows some examples of methods on type-parameterized types.
+
+package p
+
+// Parameterized types may have methods.
+type T1[A any] struct{ a A }
+
+// When declaring a method for a parameterized type, the "instantiated"
+// receiver type acts as an implicit declaration of the type parameters
+// for the receiver type. In the example below, method m1 on type T1 has
+// the receiver type T1[A] which declares the type parameter A for use
+// with this method. That is, within the method m1, A stands for the
+// actual type argument provided to an instantiated T1.
+func (t T1[A]) m1() A { return t.a }
+
+// For instance, if T1 is instantiated with the type int, the type
+// parameter A in m1 assumes that type (int) as well and we can write
+// code like this:
+var x T1[int]
+var _ int = x.m1()
+
+// Because the type parameter provided to a parameterized receiver type
+// is declared through that receiver declaration, it must be an identifier.
+// It cannot possibly be some other type because the receiver type is not
+// instantiated with concrete types, it is standing for the parameterized
+// receiver type.
+func (t T1[[ /* ERROR must be an identifier */ ]int]) m2() {}
+
+// Note that using what looks like a predeclared identifier, say int,
+// as type parameter in this situation is deceptive and considered bad
+// style. In m3 below, int is the name of the local receiver type parameter
+// and it shadows the predeclared identifier int which then cannot be used
+// anymore as expected.
+// This is no different from locally redelaring a predeclared identifier
+// and usually should be avoided. There are some notable exceptions; e.g.,
+// sometimes it makes sense to use the identifier "copy" which happens to
+// also be the name of a predeclared built-in function.
+func (t T1[int]) m3() { var _ int = 42 /* ERROR cannot use 42 .* as int */ }
+
+// The names of the type parameters used in a parameterized receiver
+// type don't have to match the type parameter names in the declaration
+// of the type used for the receiver. In our example, even though T1 is
+// declared with type parameter named A, methods using that receiver type
+// are free to use their own name for that type parameter. That is, the
+// name of type parameters is always local to the declaration where they
+// are introduced. In our example we can write a method m2 and use the
+// name X instead of A for the type parameter w/o any difference.
+func (t T1[X]) m4() X { return t.a }
+
+// If the receiver type is parameterized, type parameters must always be
+// provided: this simply follows from the general rule that a parameterized
+// type must be instantiated before it can be used. A method receiver
+// declaration using a parameterized receiver type is no exception. It is
+// simply that such receiver type expressions perform two tasks simultaneously:
+// they declare the (local) type parameters and then use them to instantiate
+// the receiver type. Forgetting to provide a type parameter leads to an error.
+func (t T1 /* ERROR generic type .* without instantiation */ ) m5() {}
+
+// However, sometimes we don't need the type parameter, and thus it is
+// inconvenient to have to choose a name. Since the receiver type expression
+// serves as a declaration for its type parameters, we are free to choose the
+// blank identifier:
+func (t T1[_]) m6() {}
+
+// Naturally, these rules apply to any number of type parameters on the receiver
+// type. Here are some more complex examples.
+type T2[A, B, C any] struct {
+        a A
+        b B
+        c C
+}
+
+// Naming of the type parameters is local and has no semantic impact:
+func (t T2[A, B, C]) m1() (A, B, C) { return t.a, t.b, t.c }
+func (t T2[C, B, A]) m2() (C, B, A) { return t.a, t.b, t.c }
+func (t T2[X, Y, Z]) m3() (X, Y, Z) { return t.a, t.b, t.c }
+
+// Type parameters may be left blank if they are not needed:
+func (t T2[A, _, C]) m4() (A, C) { return t.a, t.c }
+func (t T2[_, _, X]) m5() X { return t.c }
+func (t T2[_, _, _]) m6() {}
+
+// As usual, blank names may be used for any object which we don't care about
+// using later. For instance, we may write an unnamed method with a receiver
+// that cannot be accessed:
+func (_ T2[_, _, _]) _() int { return 42 }
+
+// Because a receiver parameter list is simply a parameter list, we can
+// leave the receiver argument away for receiver types.
+type T0 struct{}
+func (T0) _() {}
+func (T1[A]) _() {}
diff --git a/libgo/go/go/types/testdata/examples/types.go2 b/libgo/go/go/types/testdata/examples/types.go2
new file mode 100644 (file)
index 0000000..59c8804
--- /dev/null
@@ -0,0 +1,286 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file shows some examples of generic types.
+
+package p
+
+// List is just what it says - a slice of E elements.
+type List[E any] []E
+
+// A generic (parameterized) type must always be instantiated
+// before it can be used to designate the type of a variable
+// (including a struct field, or function parameter); though
+// for the latter cases, the provided type may be another type
+// parameter. So:
+var _ List[byte] = []byte{}
+
+// A generic binary tree might be declared as follows.
+type Tree[E any] struct {
+       left, right *Tree[E]
+       payload E
+}
+
+// A simple instantiation of Tree:
+var root1 Tree[int]
+
+// The actual type parameter provided may be a generic type itself:
+var root2 Tree[List[int]]
+
+// A couple of more complex examples.
+// We don't need extra parentheses around the element type of the slices on
+// the right (unlike when we use ()'s rather than []'s for type parameters).
+var _ List[List[int]] = []List[int]{}
+var _ List[List[List[Tree[int]]]] = []List[List[Tree[int]]]{}
+
+// Type parameters act like type aliases when used in generic types
+// in the sense that we can "emulate" a specific type instantiation
+// with type aliases.
+type T1[P any] struct {
+       f P
+}
+
+type T2[P any] struct {
+       f struct {
+               g P
+       }
+}
+
+var x1 T1[struct{ g int }]
+var x2 T2[int]
+
+func _() {
+       // This assignment is invalid because the types of x1, x2 are T1(...)
+       // and T2(...) respectively, which are two different defined types.
+       x1 = x2 // ERROR assignment
+
+       // This assignment is valid because the types of x1.f and x2.f are
+       // both struct { g int }; the type parameters act like type aliases
+       // and their actual names don't come into play here.
+       x1.f = x2.f
+}
+
+// We can verify this behavior using type aliases instead:
+type T1a struct {
+       f A1
+}
+type A1 = struct { g int }
+
+type T2a struct {
+       f struct {
+               g A2
+       }
+}
+type A2 = int
+
+var x1a T1a
+var x2a T2a
+
+func _() {
+       x1a = x2a // ERROR assignment
+       x1a.f = x2a.f
+}
+
+// Another interesting corner case are generic types that don't use
+// their type arguments. For instance:
+type T[P any] struct{}
+
+var xint T[int]
+var xbool T[bool]
+
+// Are these two variables of the same type? After all, their underlying
+// types are identical. We consider them to be different because each type
+// instantiation creates a new named type, in this case T<int> and T<bool>
+// even if their underlying types are identical. This is sensible because
+// we might still have methods that have different signatures or behave
+// differently depending on the type arguments, and thus we can't possibly
+// consider such types identical. Consequently:
+func _() {
+       xint = xbool // ERROR assignment
+}
+
+// Generic types cannot be used without instantiation.
+var _ T // ERROR cannot use generic type T
+
+// In type context, generic (parameterized) types cannot be parenthesized before
+// being instantiated. See also NOTES entry from 12/4/2019.
+var _ (T /* ERROR cannot use generic type T */ )[ /* ERROR expected ';' */ int]
+
+// All types may be parameterized, including interfaces.
+type I1[T any] interface{
+       m1(T)
+}
+
+// There is no such thing as a variadic generic type.
+type _[T ... /* ERROR invalid use of ... */ interface{}] struct{}
+
+// Generic interfaces may be embedded as one would expect.
+type I2 interface {
+       I1(int)     // method!
+       I1[string]  // embedded I1
+}
+
+func _() {
+       var x I2
+       x.I1(0)
+       x.m1("foo")
+}
+
+type I0 interface {
+       m0()
+}
+
+type I3 interface {
+       I0
+       I1[bool]
+       m(string)
+}
+
+func _() {
+       var x I3
+       x.m0()
+       x.m1(true)
+       x.m("foo")
+}
+
+// We accept parenthesized embedded struct fields so we can distinguish between
+// a named field with a parenthesized type foo (T) and an embedded parameterized
+// type (foo(T)), similarly to interface embedding.
+// They still need to be valid embedded types after the parentheses are stripped
+// (i.e., in contrast to interfaces, we cannot embed a struct literal). The name
+// of the embedded field is derived as before, after stripping parentheses.
+// (7/14/2020: See comment above. We probably will revert this generalized ability
+// if we go with [] for type parameters.)
+type _ struct {
+       int8
+       *int16
+       *List[int]
+
+       int8 /* ERROR int8 redeclared */
+       * /* ERROR List redeclared */ List[int]
+}
+
+// It's possible to declare local types whose underlying types
+// are type parameters. As with ordinary type definitions, the
+// types underlying properties are "inherited" but the methods
+// are not.
+func _[T interface{ m(); type int }]() {
+       type L T
+       var x L
+
+       // m is not defined on L (it is not "inherited" from
+       // its underlying type).
+       x.m /* ERROR x.m undefined */ ()
+
+       // But the properties of T, such that as that it supports
+       // the operations of the types given by its type bound,
+       // are also the properties of L.
+       x++
+       _ = x - x
+
+       // On the other hand, if we define a local alias for T,
+       // that alias stands for T as expected.
+       type A = T
+       var y A
+       y.m()
+       _ = y < 0
+}
+
+// As a special case, an explicit type argument may be omitted
+// from a type parameter bound if the type bound expects exactly
+// one type argument. In that case, the type argument is the
+// respective type parameter to which the type bound applies.
+// Note: We may not permit this syntactic sugar at first.
+// Note: This is now disabled. All examples below are adjusted.
+type Adder[T any] interface {
+       Add(T) T
+}
+
+// We don't need to explicitly instantiate the Adder bound
+// if we have exactly one type parameter.
+func Sum[T Adder[T]](list []T) T {
+       var sum T
+       for _, x := range list {
+               sum = sum.Add(x)
+       }
+       return sum
+}
+
+// Valid and invalid variations.
+type B0 interface {}
+type B1[_ any] interface{}
+type B2[_, _ any] interface{}
+
+func _[T1 B0]()
+func _[T1 B1[T1]]()
+func _[T1 B2 /* ERROR cannot use generic type .* without instantiation */ ]()
+
+func _[T1, T2 B0]()
+func _[T1 B1[T1], T2 B1[T2]]()
+func _[T1, T2 B2 /* ERROR cannot use generic type .* without instantiation */ ]()
+
+func _[T1 B0, T2 B1[T2]]() // here B1 applies to T2
+
+// When the type argument is left away, the type bound is
+// instantiated for each type parameter with that type
+// parameter.
+// Note: We may not permit this syntactic sugar at first.
+func _[A Adder[A], B Adder[B], C Adder[A]]() {
+       var a A // A's type bound is Adder[A]
+       a = a.Add(a)
+       var b B // B's type bound is Adder[B]
+       b = b.Add(b)
+       var c C // C's type bound is Adder[A]
+       a = c.Add(a)
+}
+
+// The type of variables (incl. parameters and return values) cannot
+// be an interface with type constraints or be/embed comparable.
+type I interface {
+       type int
+}
+
+var (
+       _ interface /* ERROR contains type constraints */ {type int}
+       _ I /* ERROR contains type constraints */
+)
+
+func _(I /* ERROR contains type constraints */ )
+func _(x, y, z I /* ERROR contains type constraints */ )
+func _() I /* ERROR contains type constraints */
+
+func _() {
+       var _ I /* ERROR contains type constraints */
+}
+
+type C interface {
+       comparable
+}
+
+var _ comparable /* ERROR comparable */
+var _ C /* ERROR comparable */
+
+func _(_ comparable /* ERROR comparable */ , _ C /* ERROR comparable */ )
+
+func _() {
+       var _ comparable /* ERROR comparable */
+       var _ C /* ERROR comparable */
+}
+
+// Type parameters are never const types, i.e., it's
+// not possible to declare a constant of type parameter type.
+// (If a type list contains just a single const type, we could
+// allow it, but such type lists don't make much sense in the
+// first place.)
+func _[T interface { type int, float64 }]() {
+       // not valid
+       const _ = T /* ERROR not constant */ (0)
+       const _ T /* ERROR invalid constant type T */ = 1
+
+       // valid
+       var _ = T(0)
+       var _ T = 1
+       _ = T(0)
+}
+
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue20583.src b/libgo/go/go/types/testdata/fixedbugs/issue20583.src
new file mode 100644 (file)
index 0000000..d26dbad
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package issue20583
+
+const (
+       _ = 6e886451608 /* ERROR malformed constant */ /2
+       _ = 6e886451608i /* ERROR malformed constant */ /2
+       _ = 0 * 1e+1000000000 // ERROR malformed constant
+
+       x = 1e100000000
+       _ = x*x*x*x*x*x* /* ERROR not representable */ x
+)
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue23203a.src b/libgo/go/go/types/testdata/fixedbugs/issue23203a.src
new file mode 100644 (file)
index 0000000..48cb588
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "unsafe"
+
+type T struct{}
+
+func (T) m1()                         {}
+func (T) m2([unsafe.Sizeof(T.m1)]int) {}
+
+func main() {}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue23203b.src b/libgo/go/go/types/testdata/fixedbugs/issue23203b.src
new file mode 100644 (file)
index 0000000..638ec6c
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "unsafe"
+
+type T struct{}
+
+func (T) m2([unsafe.Sizeof(T.m1)]int) {}
+func (T) m1()                         {}
+
+func main() {}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue26390.src b/libgo/go/go/types/testdata/fixedbugs/issue26390.src
new file mode 100644 (file)
index 0000000..9e0101f
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// stand-alone test to ensure case is triggered
+
+package issue26390
+
+type A = T
+
+func (t *T) m() *A { return t }
+
+type T struct{}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue28251.src b/libgo/go/go/types/testdata/fixedbugs/issue28251.src
new file mode 100644 (file)
index 0000000..cd79e0e
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains test cases for various forms of
+// method receiver declarations, per the spec clarification
+// https://golang.org/cl/142757.
+
+package issue28251
+
+// test case from issue28251
+type T struct{}
+
+type T0 = *T
+
+func (T0) m() {}
+
+func _() { (&T{}).m() }
+
+// various alternative forms
+type (
+        T1 = (((T)))
+)
+
+func ((*(T1))) m1() {}
+func _() { (T{}).m2() }
+func _() { (&T{}).m2() }
+
+type (
+        T2 = (((T3)))
+        T3 = T
+)
+
+func (T2) m2() {}
+func _() { (T{}).m2() }
+func _() { (&T{}).m2() }
+
+type (
+        T4 = ((*(T5)))
+        T5 = T
+)
+
+func (T4) m4() {}
+func _() { (T{}).m4 /* ERROR "cannot call pointer method m4 on T" */ () }
+func _() { (&T{}).m4() }
+
+type (
+        T6 = (((T7)))
+        T7 = (*(T8))
+        T8 = T
+)
+
+func (T6) m6() {}
+func _() { (T{}).m6 /* ERROR "cannot call pointer method m6 on T" */ () }
+func _() { (&T{}).m6() }
+
+type (
+        T9 = *T10
+        T10 = *T11
+        T11 = T
+)
+
+func (T9 /* ERROR invalid receiver \*\*T */ ) m9() {}
+func _() { (T{}).m9 /* ERROR has no field or method m9 */ () }
+func _() { (&T{}).m9 /* ERROR has no field or method m9 */ () }
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39634.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39634.go2
new file mode 100644 (file)
index 0000000..a13ed13
--- /dev/null
@@ -0,0 +1,91 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Examples adjusted to match new [T any] syntax for type parameters.
+// Also, previously permitted empty type parameter lists and instantiations
+// are now syntax errors.
+
+package p
+
+// crash 1
+type nt1[_ any]interface{g /* ERROR undeclared name */ }
+type ph1[e nt1[e],g(d /* ERROR undeclared name */ )]s /* ERROR undeclared name */
+func(*ph1[e,e /* ERROR redeclared */ ])h(d /* ERROR undeclared name */ )
+
+// crash 2
+// Disabled: empty []'s are now syntax errors. This example leads to too many follow-on errors.
+// type Numeric2 interface{t2 /* ERROR not a type */ }
+// func t2[T Numeric2](s[]T){0 /* ERROR not a type */ []{s /* ERROR cannot index */ [0][0]}}
+
+// crash 3
+type t3 *interface{ t3.p /* ERROR no field or method p */ }
+
+// crash 4
+type Numeric4 interface{t4 /* ERROR not a type */ }
+func t4[T Numeric4](s[]T){if( /* ERROR non-boolean */ 0){*s /* ERROR cannot indirect */ [0]}}
+
+// crash 7
+type foo7 interface { bar() }
+type x7[A any] struct{ foo7 }
+func main7() { var _ foo7 = x7[int]{} }
+
+// crash 8
+type foo8[A any] interface { type A }
+func bar8[A foo8[A]](a A) {}
+func main8() {}
+
+// crash 9
+type foo9[A any] interface { type foo9 /* ERROR interface contains type constraints */ [A] }
+func _() { var _ = new(foo9 /* ERROR interface contains type constraints */ [int]) }
+
+// crash 12
+var u /* ERROR cycle */ , i [func /* ERROR used as value */ /* ERROR used as value */ (u, c /* ERROR undeclared */ /* ERROR undeclared */ ) {}(0, len /* ERROR must be called */ /* ERROR must be called */ )]c /* ERROR undeclared */ /* ERROR undeclared */
+
+// crash 15
+func y15() { var a /* ERROR declared but not used */ interface{ p() } = G15[string]{} }
+type G15[X any] s /* ERROR undeclared name */
+func (G15 /* ERROR generic type .* without instantiation */ ) p()
+
+// crash 16
+type Foo16[T any] r16 /* ERROR not a type */
+func r16[T any]() Foo16[Foo16[T]]
+
+// crash 17
+type Y17 interface{ c() }
+type Z17 interface {
+       c() Y17
+       Y17 /* ERROR duplicate method */
+}
+func F17[T Z17](T)
+
+// crash 18
+type o18[T any] []func(_ o18[[]_ /* ERROR cannot use _ */ ])
+
+// crash 19
+type Z19 [][[]Z19{}[0][0]]c19 /* ERROR undeclared */
+
+// crash 20
+type Z20 /* ERROR illegal cycle */ interface{ Z20 }
+func F20[t Z20]() { F20(t /* ERROR invalid composite literal type */ {}) }
+
+// crash 21
+type Z21 /* ERROR illegal cycle */ interface{ Z21 }
+func F21[T Z21]() { ( /* ERROR not used */ F21[Z21]) }
+
+// crash 24
+type T24[P any] P
+func (r T24[P]) m() { T24 /* ERROR without instantiation */ .m() }
+
+// crash 25
+type T25[A any] int
+func (t T25[A]) m1() {}
+var x T25 /* ERROR without instantiation */ .m1
+
+// crash 26
+type T26 = interface{ F26[ /* ERROR methods cannot have type parameters */ Z any]() }
+func F26[Z any]() T26 { return F26[] /* ERROR operand */ }
+
+// crash 27
+func e27[T any]() interface{ x27 /* ERROR not a type */ }
+func x27() { e27 /* ERROR cannot infer T */ () }
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39664.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39664.go2
new file mode 100644 (file)
index 0000000..3b3ec56
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T[_ any] struct {}
+
+func (T /* ERROR instantiation */ ) m()
+
+func _() {
+       var x interface { m() }
+       x = T[int]{}
+       _ = x
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39680.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39680.go2
new file mode 100644 (file)
index 0000000..9bc26f3
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+import "fmt"
+
+// Minimal test case.
+func _[T interface{type T}](x T) T{
+       return x
+}
+
+// Test case from issue.
+type constr[T any] interface {
+       type T
+}
+
+func Print[T constr[T]](s []T) {
+       for _, v := range s {
+               fmt.Print(v)
+       }
+}
+
+func f() {
+       Print([]string{"Hello, ", "playground\n"})
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39693.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39693.go2
new file mode 100644 (file)
index 0000000..316ab19
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type Number interface {
+       int     /* ERROR int is not an interface */
+       float64 /* ERROR float64 is not an interface */
+}
+
+func Add[T Number](a, b T) T {
+       return a /* ERROR not defined */ + b
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39699.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39699.go2
new file mode 100644 (file)
index 0000000..75491e7
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T0 interface{
+}
+
+type T1 interface{
+       type int
+}
+
+type T2 interface{
+       comparable
+}
+
+type T3 interface {
+       T0
+       T1
+       T2
+}
+
+func _() {
+       _ = T0(0)
+       _ = T1 /* ERROR cannot use interface T1 in conversion */ (1)
+       _ = T2 /* ERROR cannot use interface T2 in conversion */ (2)
+       _ = T3 /* ERROR cannot use interface T3 in conversion */ (3)
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39711.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39711.go2
new file mode 100644 (file)
index 0000000..df621a4
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// Do not report a duplicate type error for this type list.
+// (Check types after interfaces have been completed.)
+type _ interface {
+       type interface{ Error() string }, interface{ String() string }
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39723.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39723.go2
new file mode 100644 (file)
index 0000000..55464e6
--- /dev/null
@@ -0,0 +1,9 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// A constraint must be an interface; it cannot
+// be a type parameter, for instance.
+func _[A interface{ type interface{} }, B A /* ERROR not an interface */ ]()
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39725.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39725.go2
new file mode 100644 (file)
index 0000000..e19b677
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f1[T1, T2 any](T1, T2, struct{a T1; b T2})
+func _() {
+       f1(42, string("foo"), struct /* ERROR does not match inferred type struct\{a int; b string\} */ {a, b int}{})
+}
+
+// simplified test case from issue
+func f2[T any](_ []T, _ func(T))
+func _() {
+       f2([]string{}, func /* ERROR does not match inferred type func\(string\) */ (f []byte) {})
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39754.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39754.go2
new file mode 100644 (file)
index 0000000..b2ba9de
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type Optional[T any] struct {}
+
+func (_ Optional[T]) Val() (T, bool)
+
+type Box[T any] interface {
+       Val() (T, bool)
+}
+
+func f[V interface{}, A, B Box[V]]() {}
+
+func _() {
+       f[int, Optional[int], Optional[int]]()
+       _ = f[int, Optional[int], Optional /* ERROR does not satisfy Box */ [string]]
+       // TODO(gri) Provide better position information here.
+       //           See TODO in call.go, Checker.arguments.
+       // TODO(rFindley) Reconcile this error position with types2.
+       f /* ERROR does not satisfy Box */ [int, Optional[int], Optional[string]]()
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39755.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39755.go2
new file mode 100644 (file)
index 0000000..b7ab688
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _[T interface{type map[string]int}](x T) {
+       _ = x == nil
+}
+
+// simplified test case from issue
+
+type PathParamsConstraint interface {
+        type map[string]string, []struct{key, value string}
+}
+
+type PathParams[T PathParamsConstraint] struct {
+       t T
+}
+
+func (pp *PathParams[T]) IsNil() bool {
+       return pp.t == nil // this must succeed
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39768.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39768.go2
new file mode 100644 (file)
index 0000000..abac141
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T[P any] P
+type A = T
+var x A[int]
+var _ A /* ERROR cannot use generic type */
+
+type B = T[int]
+var y B = x
+var _ B /* ERROR not a generic type */ [int]
+
+// test case from issue
+
+type Vector[T any] []T
+type VectorAlias = Vector
+var v Vector[int]
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39938.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39938.go2
new file mode 100644 (file)
index 0000000..76e7e36
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check "infinite expansion" cycle errors across instantiated types.
+
+package p
+
+type E0[P any] P
+type E1[P any] *P
+type E2[P any] struct{ P }
+type E3[P any] struct{ *P }
+
+type T0 /* ERROR illegal cycle */ struct {
+        _ E0[T0]
+}
+
+type T0_ /* ERROR illegal cycle */ struct {
+        E0[T0_]
+}
+
+type T1 struct {
+        _ E1[T1]
+}
+
+type T2 /* ERROR illegal cycle */ struct {
+        _ E2[T2]
+}
+
+type T3 struct {
+        _ E3[T3]
+}
+
+// some more complex cases
+
+type T4 /* ERROR illegal cycle */ struct {
+       _ E0[E2[T4]]
+}
+
+type T5 struct {
+       _ E0[E2[E0[E1[E2[[10]T5]]]]]
+}
+
+type T6 /* ERROR illegal cycle */ struct {
+       _ E0[[10]E2[E0[E2[E2[T6]]]]]
+}
+
+type T7 struct {
+       _ E0[[]E2[E0[E2[E2[T6]]]]]
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39948.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39948.go2
new file mode 100644 (file)
index 0000000..c2b4609
--- /dev/null
@@ -0,0 +1,9 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T[P any] interface{
+       P // ERROR P is a type parameter, not an interface
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39976.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39976.go2
new file mode 100644 (file)
index 0000000..3db4eae
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type policy[K, V any] interface{}
+type LRU[K, V any] struct{}
+
+func NewCache[K, V any](p policy[K, V])
+
+func _() {
+       var lru LRU[int, string]
+       NewCache[int, string](&lru)
+       NewCache(& /* ERROR does not match policy\[K, V\] \(cannot infer K and V\) */ lru)
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39982.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39982.go2
new file mode 100644 (file)
index 0000000..9810b63
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type (
+       T[_ any] struct{}
+       S[_ any] struct {
+               data T[*T[int]]
+       }
+)
+
+func _() {
+       _ = S[int]{
+               data: T[*T[int]]{},
+       }
+}
+
+// full test case from issue
+
+type (
+       Element[TElem any] struct{}
+
+       entry[K comparable] struct{}
+
+       Cache[K comparable] struct {
+               data map[K]*Element[*entry[K]]
+       }
+)
+
+func _() {
+       _ = Cache[int]{
+               data: make(map[int](*Element[*entry[int]])),
+       }
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue40038.go2 b/libgo/go/go/types/testdata/fixedbugs/issue40038.go2
new file mode 100644 (file)
index 0000000..8948d61
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type A[T any] int
+
+func (A[T]) m(A[T])
+
+func f[P interface{m(P)}]()
+
+func _() {
+       _ = f[A[int]]
+}
\ No newline at end of file
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue40056.go2 b/libgo/go/go/types/testdata/fixedbugs/issue40056.go2
new file mode 100644 (file)
index 0000000..f587691
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _() {
+       NewS /* ERROR cannot infer T */ ().M()
+}
+
+type S struct {}
+
+func NewS[T any]() *S
+
+func (_ *S /* ERROR S is not a generic type */ [T]) M()
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue40057.go2 b/libgo/go/go/types/testdata/fixedbugs/issue40057.go2
new file mode 100644 (file)
index 0000000..fdc8fb1
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _() {
+       var x interface{}
+       switch t := x.(type) {
+       case S /* ERROR cannot use generic type */ :
+               t.m()
+       }
+}
+
+type S[T any] struct {}
+
+func (_ S[T]) m()
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue40301.go2 b/libgo/go/go/types/testdata/fixedbugs/issue40301.go2
new file mode 100644 (file)
index 0000000..5d97855
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+import "unsafe"
+
+func _[T any](x T) {
+       _ = unsafe /* ERROR undefined */ .Alignof(x)
+       _ = unsafe /* ERROR undefined */ .Sizeof(x)
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue40684.go2 b/libgo/go/go/types/testdata/fixedbugs/issue40684.go2
new file mode 100644 (file)
index 0000000..0269c3a
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T[_ any] int
+
+func f[_ any]()
+func g[_, _ any]()
+
+func _() {
+       _ = f[T /* ERROR without instantiation */ ]
+       _ = g[T /* ERROR without instantiation */ , T /* ERROR without instantiation */ ]
+}
\ No newline at end of file
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue41124.go2 b/libgo/go/go/types/testdata/fixedbugs/issue41124.go2
new file mode 100644 (file)
index 0000000..61f766b
--- /dev/null
@@ -0,0 +1,91 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// Test case from issue.
+
+type Nat interface {
+       type Zero, Succ
+}
+
+type Zero struct{}
+type Succ struct{
+       Nat // ERROR interface contains type constraints
+}
+
+// Struct tests.
+
+type I1 interface {
+       comparable
+}
+
+type I2 interface {
+       type int
+}
+
+type I3 interface {
+       I1
+       I2
+}
+
+type _ struct {
+       f I1 // ERROR interface is .* comparable
+}
+
+type _ struct {
+       comparable // ERROR interface is .* comparable
+}
+
+type _ struct{
+       I1 // ERROR interface is .* comparable
+}
+
+type _ struct{
+       I2 // ERROR interface contains type constraints
+}
+
+type _ struct{
+       I3 // ERROR interface contains type constraints
+}
+
+// General composite types.
+
+type (
+       _ [10]I1 // ERROR interface is .* comparable
+       _ [10]I2 // ERROR interface contains type constraints
+
+       _ []I1 // ERROR interface is .* comparable
+       _ []I2 // ERROR interface contains type constraints
+
+       _ *I3 // ERROR interface contains type constraints
+       _ map[I1 /* ERROR interface is .* comparable */ ]I2 // ERROR interface contains type constraints
+       _ chan I3 // ERROR interface contains type constraints
+       _ func(I1 /* ERROR interface is .* comparable */ )
+       _ func() I2 // ERROR interface contains type constraints
+)
+
+// Other cases.
+
+var _ = [...]I3 /* ERROR interface contains type constraints */ {}
+
+func _(x interface{}) {
+       _ = x.(I3 /* ERROR interface contains type constraints */ )
+}
+
+type T1[_ any] struct{}
+type T3[_, _, _ any] struct{}
+var _ T1[I2 /* ERROR interface contains type constraints */ ]
+var _ T3[int, I2 /* ERROR interface contains type constraints */ , float32]
+
+func f1[_ any]() int
+var _ = f1[I2 /* ERROR interface contains type constraints */ ]()
+func f3[_, _, _ any]() int
+var _ = f3[int, I2 /* ERROR interface contains type constraints */ , float32]()
+
+func _(x interface{}) {
+       switch x.(type) {
+       case I2 /* ERROR interface contains type constraints */ :
+       }
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue42695.src b/libgo/go/go/types/testdata/fixedbugs/issue42695.src
new file mode 100644 (file)
index 0000000..d0d6200
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package issue42695
+
+const _ = 6e5518446744 // ERROR malformed constant
+const _ uint8 = 6e5518446744 // ERROR malformed constant
+
+var _ = 6e5518446744 // ERROR malformed constant
+var _ uint8 = 6e5518446744 // ERROR malformed constant
+
+func f(x int) int {
+        return x + 6e5518446744 // ERROR malformed constant
+}
+
+var _ = f(6e5518446744 /* ERROR malformed constant */ )
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue42758.go2 b/libgo/go/go/types/testdata/fixedbugs/issue42758.go2
new file mode 100644 (file)
index 0000000..698cb8a
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _[T any](x interface{}){
+       switch x.(type) {
+       case T: // ok to use a type parameter
+       case int:
+       }
+
+       switch x.(type) {
+       case T:
+       case T /* ERROR duplicate case */ :
+       }
+}
+
+type constraint interface {
+       type int
+}
+
+func _[T constraint](x interface{}){
+       switch x.(type) {
+       case T: // ok to use a type parameter even if type list contains int
+       case int:
+       }
+}
+
+func _(x constraint /* ERROR contains type constraints */ ) {
+       switch x /* ERROR contains type constraints */ .(type) {
+       }
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue42987.src b/libgo/go/go/types/testdata/fixedbugs/issue42987.src
new file mode 100644 (file)
index 0000000..6060ec8
--- /dev/null
@@ -0,0 +1,10 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check that there is only one error (no follow-on errors).
+
+package p
+// TODO(rFindley) This is a parser error, but in types2 it is a type checking
+//                error. We could probably do without this check in the parser.
+var _ = [... /* ERROR expected array length, found '...' */ ]byte("foo")
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue43087.src b/libgo/go/go/types/testdata/fixedbugs/issue43087.src
new file mode 100644 (file)
index 0000000..ef37b4a
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func _() {
+       a, b, b /* ERROR b repeated on left side of := */ := 1, 2, 3
+       _ = a
+       _ = b
+}
+
+func _() {
+       a, _, _ := 1, 2, 3 // multiple _'s ok
+       _ = a
+}
+
+func _() {
+       var b int
+       a, b, b /* ERROR b repeated on left side of := */ := 1, 2, 3
+       _ = a
+       _ = b
+}
+
+func _() {
+       var a []int
+       a /* ERROR expected identifier */ /* ERROR non-name .* on left side of := */ [0], b := 1, 2
+       _ = a
+       _ = b
+}
+
+func _() {
+       var a int
+       a, a /* ERROR a repeated on left side of := */ := 1, 2
+       _ = a
+}
+
+func _() {
+       var a, b int
+       a, b := /* ERROR no new variables on left side of := */ 1, 2
+       _ = a
+       _ = b
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue43110.src b/libgo/go/go/types/testdata/fixedbugs/issue43110.src
new file mode 100644 (file)
index 0000000..4a46945
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type P *struct{}
+
+func _() {
+       // want an error even if the switch is empty
+       var a struct{ _ func() }
+       switch a /* ERROR cannot switch on a */ {
+       }
+
+       switch a /* ERROR cannot switch on a */ {
+       case a: // no follow-on error here
+       }
+
+       // this is ok because f can be compared to nil
+       var f func()
+       switch f {
+       }
+
+       switch f {
+       case nil:
+       }
+
+       switch (func())(nil) {
+       case nil:
+       }
+
+       switch (func())(nil) {
+       case f /* ERROR cannot compare */ :
+       }
+
+       switch nil /* ERROR use of untyped nil in switch expression */ {
+       }
+
+       // this is ok
+       switch P(nil) {
+       case P(nil):
+       }
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue43124.src b/libgo/go/go/types/testdata/fixedbugs/issue43124.src
new file mode 100644 (file)
index 0000000..f429f74
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var _ = int(0 /* ERROR invalid use of \.\.\. in conversion to int */ ...)
+
+// test case from issue
+
+type M []string
+
+var (
+       x = []string{"a", "b"}
+       _ = M(x /* ERROR invalid use of \.\.\. in conversion to M */ ...)
+)
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue43125.src b/libgo/go/go/types/testdata/fixedbugs/issue43125.src
new file mode 100644 (file)
index 0000000..456888d
--- /dev/null
@@ -0,0 +1,8 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var _ = new(- /* ERROR not a type */ 1)
+var _ = new(1 /* ERROR not a type */ + 1)
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue43190.src b/libgo/go/go/types/testdata/fixedbugs/issue43190.src
new file mode 100644 (file)
index 0000000..96acb3a
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Most of the errors below are actually produced by the parser, but we check
+// them here for consistency with the types2 tests.
+
+package p
+
+import ; /* ERROR invalid import path */ /* ERROR expected 'STRING' */
+import // ERROR expected ';'
+var _ int
+import /* ERROR expected declaration */ .;
+
+import ()
+import (.)
+import (
+       "fmt"
+       .
+)
+
+var _ = fmt /* ERROR "undeclared name" */ .Println
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue44688.go2 b/libgo/go/go/types/testdata/fixedbugs/issue44688.go2
new file mode 100644 (file)
index 0000000..512bfcc
--- /dev/null
@@ -0,0 +1,83 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package P
+
+type A1[T any] struct{}
+
+func (*A1[T]) m1(T) {}
+
+type A2[T any] interface {
+       m2(T)
+}
+
+type B1[T any] struct {
+       filler int
+       *A1[T]
+       A2[T]
+}
+
+type B2[T any] interface {
+       A2[T]
+}
+
+type C[T any] struct {
+       filler1 int
+       filler2 int
+       B1[T]
+}
+
+type D[T any] struct {
+       filler1 int
+       filler2 int
+       filler3 int
+       C[T]
+}
+
+func _() {
+       // calling embedded methods
+       var b1 B1[string]
+
+       b1.A1.m1("")
+       b1.m1("")
+
+       b1.A2.m2("")
+       b1.m2("")
+
+       var b2 B2[string]
+       b2.m2("")
+
+       // a deeper nesting
+       var d D[string]
+       d.m1("")
+       d.m2("")
+
+       // calling method expressions
+       m1x := B1[string].m1
+       m1x(b1, "")
+       m2x := B2[string].m2
+       m2x(b2, "")
+
+       // calling method values
+       m1v := b1.m1
+       m1v("")
+       m2v := b1.m2
+       m2v("")
+       b2v := b2.m2
+       b2v("")
+}
+
+// actual test case from issue
+
+type A[T any] struct{}
+
+func (*A[T]) f(T) {}
+
+type B[T any] struct{ A[T] }
+
+func _() {
+       var b B[string]
+       b.A.f("")
+       b.f("")
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue44799.go2 b/libgo/go/go/types/testdata/fixedbugs/issue44799.go2
new file mode 100644 (file)
index 0000000..9e528a7
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func Map[F, T any](s []F, f func(F) T) []T { return nil }
+
+func Reduce[Elem1, Elem2 any](s []Elem1, initializer Elem2, f func(Elem2, Elem1) Elem2) Elem2 { var x Elem2; return x }
+
+func main() {
+       var s []int
+       var f1 func(int) float64
+       var f2 func(float64, int) float64
+       _ = Map[int](s, f1)
+       _ = Map(s, f1)
+       _ = Reduce[int](s, 0, f2)
+       _ = Reduce(s, 0, f2)
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue45548.go2 b/libgo/go/go/types/testdata/fixedbugs/issue45548.go2
new file mode 100644 (file)
index 0000000..b1e4249
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f[F interface{type *Q}, G interface{type *R}, Q, R any](q Q, r R) {}
+
+func _() {
+       f[*float64, *int](1, 2)
+       f[*float64](1, 2)
+       f(1, 2)
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue45635.go2 b/libgo/go/go/types/testdata/fixedbugs/issue45635.go2
new file mode 100644 (file)
index 0000000..3e2ccec
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+       some /* ERROR "undeclared name" */ [int, int]()
+}
+
+type N[T any] struct{}
+
+var _ N /* ERROR "0 arguments but 1 type parameters" */ []
+
+type I interface {
+       type map[int]int, []int
+}
+
+func _[T I](i, j int) {
+       var m map[int]int
+       _ = m[i, j /* ERROR "more than one index" */ ]
+
+       var a [3]int
+       _ = a[i, j /* ERROR "more than one index" */ ]
+
+       var s []int
+       _ = s[i, j /* ERROR "more than one index" */ ]
+
+       var t T
+       // TODO(rFindley) Fix the duplicate error below.
+       _ = t[i, j /* ERROR "more than one index" */ /* ERROR "more than one index" */ ]
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue45985.go2 b/libgo/go/go/types/testdata/fixedbugs/issue45985.go2
new file mode 100644 (file)
index 0000000..550b9c6
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package issue45985
+
+// TODO(rFindley): this error should be on app[int] below.
+func app[S /* ERROR "type S = S does not match" */ interface{ type []T }, T any](s S, e T) S {
+    return append(s, e)
+}
+
+func _() {
+       _ = app[int]
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue46403.src b/libgo/go/go/types/testdata/fixedbugs/issue46403.src
new file mode 100644 (file)
index 0000000..9d47522
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package issue46403
+
+func _() {
+       // a should be used, despite the parser error below.
+       var a []int
+       var _ = a[] // ERROR expected operand
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue46404.go1 b/libgo/go/go/types/testdata/fixedbugs/issue46404.go1
new file mode 100644 (file)
index 0000000..db604bc
--- /dev/null
@@ -0,0 +1,8 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package issue46404
+
+// Check that we don't type check t[_] as an instantiation.
+type t [t /* ERROR not a type */ [_]]_ // ERROR cannot use
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue6977.src b/libgo/go/go/types/testdata/fixedbugs/issue6977.src
new file mode 100644 (file)
index 0000000..8f4e9ba
--- /dev/null
@@ -0,0 +1,82 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+import "io"
+
+// Alan's initial report.
+
+type I interface { f(); String() string }
+type J interface { g(); String() string }
+
+type IJ1 = interface { I; J }
+type IJ2 = interface { f(); g(); String() string }
+
+var _ = (*IJ1)(nil) == (*IJ2)(nil) // static assert that IJ1 and IJ2 are identical types
+
+// The canonical example.
+
+type ReadWriteCloser interface { io.ReadCloser; io.WriteCloser }
+
+// Some more cases.
+
+type M interface { m() }
+type M32 interface { m() int32 }
+type M64 interface { m() int64 }
+
+type U1 interface { m() }
+type U2 interface { m(); M }
+type U3 interface { M; m() }
+type U4 interface { M; M; M }
+type U5 interface { U1; U2; U3; U4 }
+
+type U6 interface { m(); m /* ERROR duplicate method */ () }
+type U7 interface { M32 /* ERROR duplicate method */ ; m() }
+type U8 interface { m(); M32 /* ERROR duplicate method */ }
+type U9 interface { M32; M64 /* ERROR duplicate method */ }
+
+// Verify that repeated embedding of the same interface(s)
+// eliminates duplicate methods early (rather than at the
+// end) to prevent exponential memory and time use.
+// Without early elimination, computing T29 may take dozens
+// of minutes.
+type (
+        T0 interface { m() }
+        T1 interface { T0; T0 }
+        T2 interface { T1; T1 }
+        T3 interface { T2; T2 }
+        T4 interface { T3; T3 }
+        T5 interface { T4; T4 }
+        T6 interface { T5; T5 }
+        T7 interface { T6; T6 }
+        T8 interface { T7; T7 }
+        T9 interface { T8; T8 }
+
+        T10 interface { T9; T9 }
+        T11 interface { T10; T10 }
+        T12 interface { T11; T11 }
+        T13 interface { T12; T12 }
+        T14 interface { T13; T13 }
+        T15 interface { T14; T14 }
+        T16 interface { T15; T15 }
+        T17 interface { T16; T16 }
+        T18 interface { T17; T17 }
+        T19 interface { T18; T18 }
+
+        T20 interface { T19; T19 }
+        T21 interface { T20; T20 }
+        T22 interface { T21; T21 }
+        T23 interface { T22; T22 }
+        T24 interface { T23; T23 }
+        T25 interface { T24; T24 }
+        T26 interface { T25; T25 }
+        T27 interface { T26; T26 }
+        T28 interface { T27; T27 }
+        T29 interface { T28; T28 }
+)
+
+// Verify that m is present.
+var x T29
+var _ = x.m
index 087cda429d689ab83c714a5f18caef0fdd442e16..2660ce4408c1b640f67bf517ca72d3819055907e 100644 (file)
@@ -4,12 +4,18 @@
 
 package types
 
-import "sort"
+import (
+       "fmt"
+       "go/token"
+       "sync/atomic"
+)
 
 // A Type represents a type of Go.
 // All types implement the Type interface.
 type Type interface {
-       // Underlying returns the underlying type of a type.
+       // Underlying returns the underlying type of a type
+       // w/o following forwarding chains. Only used by
+       // client packages (here for backward-compatibility).
        Underlying() Type
 
        // String returns a string representation of a type.
@@ -98,7 +104,7 @@ type Array struct {
 
 // NewArray returns a new array type for the given element type and length.
 // A negative length indicates an unknown length.
-func NewArray(elem Type, len int64) *Array { return &Array{len, elem} }
+func NewArray(elem Type, len int64) *Array { return &Array{len: len, elem: elem} }
 
 // Len returns the length of array a.
 // A negative result indicates an unknown length.
@@ -113,7 +119,7 @@ type Slice struct {
 }
 
 // NewSlice returns a new slice type for the given element type.
-func NewSlice(elem Type) *Slice { return &Slice{elem} }
+func NewSlice(elem Type) *Slice { return &Slice{elem: elem} }
 
 // Elem returns the element type of slice s.
 func (s *Slice) Elem() Type { return s.elem }
@@ -176,8 +182,10 @@ type Tuple struct {
 // NewTuple returns a new tuple for the given variables.
 func NewTuple(x ...*Var) *Tuple {
        if len(x) > 0 {
-               return &Tuple{x}
+               return &Tuple{vars: x}
        }
+       // TODO(gri) Don't represent empty tuples with a (*Tuple)(nil) pointer;
+       //           it's too subtle and causes problems.
        return nil
 }
 
@@ -199,11 +207,13 @@ type Signature struct {
        // and store it in the Func Object) because when type-checking a function
        // literal we call the general type checker which returns a general Type.
        // We then unpack the *Signature and use the scope for the literal body.
-       scope    *Scope // function scope, present for package-local signatures
-       recv     *Var   // nil if not a method
-       params   *Tuple // (incoming) parameters from left to right; or nil
-       results  *Tuple // (outgoing) results from left to right; or nil
-       variadic bool   // true if the last parameter's type is of the form ...T (or string, for append built-in only)
+       rparams  []*TypeName // receiver type parameters from left to right, or nil
+       tparams  []*TypeName // type parameters from left to right, or nil
+       scope    *Scope      // function scope, present for package-local signatures
+       recv     *Var        // nil if not a method
+       params   *Tuple      // (incoming) parameters from left to right; or nil
+       results  *Tuple      // (outgoing) results from left to right; or nil
+       variadic bool        // true if the last parameter's type is of the form ...T (or string, for append built-in only)
 }
 
 // NewSignature returns a new function type for the given receiver, parameters,
@@ -220,7 +230,7 @@ func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature {
                        panic("types.NewSignature: variadic parameter must be of unnamed slice type")
                }
        }
-       return &Signature{nil, recv, params, results, variadic}
+       return &Signature{recv: recv, params: params, results: results, variadic: variadic}
 }
 
 // Recv returns the receiver of signature s (if a method), or nil if a
@@ -231,6 +241,12 @@ func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature {
 // contain methods whose receiver type is a different interface.
 func (s *Signature) Recv() *Var { return s.recv }
 
+// _TParams returns the type parameters of signature s, or nil.
+func (s *Signature) _TParams() []*TypeName { return s.tparams }
+
+// _SetTParams sets the type parameters of signature s.
+func (s *Signature) _SetTParams(tparams []*TypeName) { s.tparams = tparams }
+
 // Params returns the parameters of signature s, or nil.
 func (s *Signature) Params() *Tuple { return s.params }
 
@@ -240,12 +256,88 @@ func (s *Signature) Results() *Tuple { return s.results }
 // Variadic reports whether the signature s is variadic.
 func (s *Signature) Variadic() bool { return s.variadic }
 
+// A _Sum represents a set of possible types.
+// Sums are currently used to represent type lists of interfaces
+// and thus the underlying types of type parameters; they are not
+// first class types of Go.
+type _Sum struct {
+       types []Type // types are unique
+}
+
+// _NewSum returns a new Sum type consisting of the provided
+// types if there are more than one. If there is exactly one
+// type, it returns that type. If the list of types is empty
+// the result is nil.
+func _NewSum(types []Type) Type {
+       if len(types) == 0 {
+               return nil
+       }
+
+       // What should happen if types contains a sum type?
+       // Do we flatten the types list? For now we check
+       // and panic. This should not be possible for the
+       // current use case of type lists.
+       // TODO(gri) Come up with the rules for sum types.
+       for _, t := range types {
+               if _, ok := t.(*_Sum); ok {
+                       panic("sum type contains sum type - unimplemented")
+               }
+       }
+
+       if len(types) == 1 {
+               return types[0]
+       }
+       return &_Sum{types: types}
+}
+
+// is reports whether all types in t satisfy pred.
+func (s *_Sum) is(pred func(Type) bool) bool {
+       if s == nil {
+               return false
+       }
+       for _, t := range s.types {
+               if !pred(t) {
+                       return false
+               }
+       }
+       return true
+}
+
 // An Interface represents an interface type.
 type Interface struct {
        methods   []*Func // ordered list of explicitly declared methods
+       types     Type    // (possibly a Sum) type declared with a type list (TODO(gri) need better field name)
        embeddeds []Type  // ordered list of explicitly embedded types
 
        allMethods []*Func // ordered list of methods declared with or embedded in this interface (TODO(gri): replace with mset)
+       allTypes   Type    // intersection of all embedded and locally declared types  (TODO(gri) need better field name)
+
+       obj Object // type declaration defining this interface; or nil (for better error messages)
+}
+
+// unpack unpacks a type into a list of types.
+// TODO(gri) Try to eliminate the need for this function.
+func unpackType(typ Type) []Type {
+       if typ == nil {
+               return nil
+       }
+       if sum := asSum(typ); sum != nil {
+               return sum.types
+       }
+       return []Type{typ}
+}
+
+// is reports whether interface t represents types that all satisfy pred.
+func (t *Interface) is(pred func(Type) bool) bool {
+       if t.allTypes == nil {
+               return false // we must have at least one type! (was bug)
+       }
+       for _, t := range unpackType(t.allTypes) {
+               if !pred(t) {
+                       return false
+               }
+       }
+       return true
 }
 
 // emptyInterface represents the empty (completed) interface
@@ -301,8 +393,8 @@ func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface {
        }
 
        // sort for API stability
-       sort.Sort(byUniqueMethodName(methods))
-       sort.Stable(byUniqueTypeName(embeddeds))
+       sortMethods(methods)
+       sortTypes(embeddeds)
 
        typ.methods = methods
        typ.embeddeds = embeddeds
@@ -344,8 +436,101 @@ func (t *Interface) assertCompleteness() {
 func (t *Interface) Method(i int) *Func { t.assertCompleteness(); return t.allMethods[i] }
 
 // Empty reports whether t is the empty interface.
-// The interface must have been completed.
-func (t *Interface) Empty() bool { t.assertCompleteness(); return len(t.allMethods) == 0 }
+func (t *Interface) Empty() bool {
+       if t.allMethods != nil {
+               // interface is complete - quick test
+               // A non-nil allTypes may still be empty and represents the bottom type.
+               return len(t.allMethods) == 0 && t.allTypes == nil
+       }
+       return !t.iterate(func(t *Interface) bool {
+               return len(t.methods) > 0 || t.types != nil
+       }, nil)
+}
+
+// _HasTypeList reports whether interface t has a type list, possibly from an embedded type.
+func (t *Interface) _HasTypeList() bool {
+       if t.allMethods != nil {
+               // interface is complete - quick test
+               return t.allTypes != nil
+       }
+
+       return t.iterate(func(t *Interface) bool {
+               return t.types != nil
+       }, nil)
+}
+
+// _IsComparable reports whether interface t is or embeds the predeclared interface "comparable".
+func (t *Interface) _IsComparable() bool {
+       if t.allMethods != nil {
+               // interface is complete - quick test
+               _, m := lookupMethod(t.allMethods, nil, "==")
+               return m != nil
+       }
+
+       return t.iterate(func(t *Interface) bool {
+               _, m := lookupMethod(t.methods, nil, "==")
+               return m != nil
+       }, nil)
+}
+
+// _IsConstraint reports t.HasTypeList() || t.IsComparable().
+func (t *Interface) _IsConstraint() bool {
+       if t.allMethods != nil {
+               // interface is complete - quick test
+               if t.allTypes != nil {
+                       return true
+               }
+               _, m := lookupMethod(t.allMethods, nil, "==")
+               return m != nil
+       }
+
+       return t.iterate(func(t *Interface) bool {
+               if t.types != nil {
+                       return true
+               }
+               _, m := lookupMethod(t.methods, nil, "==")
+               return m != nil
+       }, nil)
+}
+
+// iterate calls f with t and then with any embedded interface of t, recursively, until f returns true.
+// iterate reports whether any call to f returned true.
+func (t *Interface) iterate(f func(*Interface) bool, seen map[*Interface]bool) bool {
+       if f(t) {
+               return true
+       }
+       for _, e := range t.embeddeds {
+               // e should be an interface but be careful (it may be invalid)
+               if e := asInterface(e); e != nil {
+                       // Cyclic interfaces such as "type E interface { E }" are not permitted
+                       // but they are still constructed and we need to detect such cycles.
+                       if seen[e] {
+                               continue
+                       }
+                       if seen == nil {
+                               seen = make(map[*Interface]bool)
+                       }
+                       seen[e] = true
+                       if e.iterate(f, seen) {
+                               return true
+                       }
+               }
+       }
+       return false
+}
+
+// isSatisfiedBy reports whether interface t's type list is satisfied by the type typ.
+// If the type list is empty (absent), typ trivially satisfies the interface.
+// TODO(gri) This is not a great name. Eventually, we should have a more comprehensive
+//           "implements" predicate.
+func (t *Interface) isSatisfiedBy(typ Type) bool {
+       t.Complete()
+       if t.allTypes == nil {
+               return true
+       }
+       types := unpackType(t.allTypes)
+       return includes(types, typ) || includes(types, under(typ))
+}
 
 // Complete computes the interface's method set. It must be called by users of
 // NewInterfaceType and NewInterface after the interface's embedded types are
@@ -379,12 +564,22 @@ func (t *Interface) Complete() *Interface {
                addMethod(m, true)
        }
 
+       allTypes := t.types
+
        for _, typ := range t.embeddeds {
-               typ := typ.Underlying().(*Interface)
-               typ.Complete()
-               for _, m := range typ.allMethods {
+               utyp := under(typ)
+               etyp := asInterface(utyp)
+               if etyp == nil {
+                       if utyp != Typ[Invalid] {
+                               panic(fmt.Sprintf("%s is not an interface", typ))
+                       }
+                       continue
+               }
+               etyp.Complete()
+               for _, m := range etyp.allMethods {
                        addMethod(m, false)
                }
+               allTypes = intersect(allTypes, etyp.allTypes)
        }
 
        for i := 0; i < len(todo); i += 2 {
@@ -396,9 +591,10 @@ func (t *Interface) Complete() *Interface {
        }
 
        if methods != nil {
-               sort.Sort(byUniqueMethodName(methods))
+               sortMethods(methods)
                t.allMethods = methods
        }
+       t.allTypes = allTypes
 
        return t
 }
@@ -410,7 +606,7 @@ type Map struct {
 
 // NewMap returns a new map for the given key and element types.
 func NewMap(key, elem Type) *Map {
-       return &Map{key, elem}
+       return &Map{key: key, elem: elem}
 }
 
 // Key returns the key type of map m.
@@ -437,7 +633,7 @@ const (
 
 // NewChan returns a new channel type for the given direction and element type.
 func NewChan(dir ChanDir, elem Type) *Chan {
-       return &Chan{dir, elem}
+       return &Chan{dir: dir, elem: elem}
 }
 
 // Dir returns the direction of channel c.
@@ -446,13 +642,16 @@ func (c *Chan) Dir() ChanDir { return c.dir }
 // Elem returns the element type of channel c.
 func (c *Chan) Elem() Type { return c.elem }
 
-// A Named represents a named type.
+// A Named represents a named (defined) type.
 type Named struct {
-       info       typeInfo  // for cycle detection
-       obj        *TypeName // corresponding declared object
-       orig       Type      // type (on RHS of declaration) this *Named type is derived of (for cycle reporting)
-       underlying Type      // possibly a *Named during setup; never a *Named once set up completely
-       methods    []*Func   // methods declared for this type (not the method set of this type); signatures are type-checked lazily
+       check      *Checker    // for Named.under implementation; nilled once under has been called
+       info       typeInfo    // for cycle detection
+       obj        *TypeName   // corresponding declared object
+       orig       Type        // type (on RHS of declaration) this *Named type is derived of (for cycle reporting)
+       underlying Type        // possibly a *Named during setup; never a *Named once set up completely
+       tparams    []*TypeName // type parameters, or nil
+       targs      []Type      // type arguments (after instantiation), or nil
+       methods    []*Func     // methods declared for this type (not the method set of this type); signatures are type-checked lazily
 }
 
 // NewNamed returns a new named type for the given type name, underlying type, and associated methods.
@@ -462,16 +661,50 @@ func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named {
        if _, ok := underlying.(*Named); ok {
                panic("types.NewNamed: underlying type must not be *Named")
        }
-       typ := &Named{obj: obj, orig: underlying, underlying: underlying, methods: methods}
+       return (*Checker)(nil).newNamed(obj, underlying, methods)
+}
+
+func (check *Checker) newNamed(obj *TypeName, underlying Type, methods []*Func) *Named {
+       typ := &Named{check: check, obj: obj, orig: underlying, underlying: underlying, methods: methods}
        if obj.typ == nil {
                obj.typ = typ
        }
+       // Ensure that typ is always expanded, at which point the check field can be
+       // nilled out.
+       //
+       // Note that currently we cannot nil out check inside typ.under(), because
+       // it's possible that typ is expanded multiple times.
+       //
+       // TODO(rFindley): clean this up so that under is the only function mutating
+       //                 named types.
+       if check != nil {
+               check.later(func() {
+                       switch typ.under().(type) {
+                       case *Named, *instance:
+                               panic("internal error: unexpanded underlying type")
+                       }
+                       typ.check = nil
+               })
+       }
        return typ
 }
 
 // Obj returns the type name for the named type t.
 func (t *Named) Obj() *TypeName { return t.obj }
 
+// TODO(gri) Come up with a better representation and API to distinguish
+//           between parameterized instantiated and non-instantiated types.
+
+// _TParams returns the type parameters of the named type t, or nil.
+// The result is non-nil for an (originally) parameterized type even if it is instantiated.
+func (t *Named) _TParams() []*TypeName { return t.tparams }
+
+// _TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated.
+func (t *Named) _TArgs() []Type { return t.targs }
+
+// _SetTArgs sets the type arguments of Named.
+func (t *Named) _SetTArgs(args []Type) { t.targs = args }
+
 // NumMethods returns the number of explicit methods whose receiver is named type t.
 func (t *Named) NumMethods() int { return len(t.methods) }
 
@@ -496,28 +729,258 @@ func (t *Named) AddMethod(m *Func) {
        }
 }
 
-// Implementations for Type methods.
-
-func (b *Basic) Underlying() Type     { return b }
-func (a *Array) Underlying() Type     { return a }
-func (s *Slice) Underlying() Type     { return s }
-func (s *Struct) Underlying() Type    { return s }
-func (p *Pointer) Underlying() Type   { return p }
-func (t *Tuple) Underlying() Type     { return t }
-func (s *Signature) Underlying() Type { return s }
-func (t *Interface) Underlying() Type { return t }
-func (m *Map) Underlying() Type       { return m }
-func (c *Chan) Underlying() Type      { return c }
-func (t *Named) Underlying() Type     { return t.underlying }
-
-func (b *Basic) String() string     { return TypeString(b, nil) }
-func (a *Array) String() string     { return TypeString(a, nil) }
-func (s *Slice) String() string     { return TypeString(s, nil) }
-func (s *Struct) String() string    { return TypeString(s, nil) }
-func (p *Pointer) String() string   { return TypeString(p, nil) }
-func (t *Tuple) String() string     { return TypeString(t, nil) }
-func (s *Signature) String() string { return TypeString(s, nil) }
-func (t *Interface) String() string { return TypeString(t, nil) }
-func (m *Map) String() string       { return TypeString(m, nil) }
-func (c *Chan) String() string      { return TypeString(c, nil) }
-func (t *Named) String() string     { return TypeString(t, nil) }
+// Note: This is a uint32 rather than a uint64 because the
+// respective 64 bit atomic instructions are not available
+// on all platforms.
+var lastId uint32
+
+// nextId returns a value increasing monotonically by 1 with
+// each call, starting with 1. It may be called concurrently.
+func nextId() uint64 { return uint64(atomic.AddUint32(&lastId, 1)) }
+
+// A _TypeParam represents a type parameter type.
+type _TypeParam struct {
+       check *Checker  // for lazy type bound completion
+       id    uint64    // unique id
+       obj   *TypeName // corresponding type name
+       index int       // parameter index
+       bound Type      // *Named or *Interface; underlying type is always *Interface
+}
+
+// newTypeParam returns a new TypeParam.
+func (check *Checker) newTypeParam(obj *TypeName, index int, bound Type) *_TypeParam {
+       assert(bound != nil)
+       typ := &_TypeParam{check: check, id: nextId(), obj: obj, index: index, bound: bound}
+       if obj.typ == nil {
+               obj.typ = typ
+       }
+       return typ
+}
+
+func (t *_TypeParam) Bound() *Interface {
+       iface := asInterface(t.bound)
+       // use the type bound position if we have one
+       pos := token.NoPos
+       if n, _ := t.bound.(*Named); n != nil {
+               pos = n.obj.pos
+       }
+       // TODO(rFindley) switch this to an unexported method on Checker.
+       t.check.completeInterface(pos, iface)
+       return iface
+}
+
+// optype returns a type's operational type. Except for
+// type parameters, the operational type is the same
+// as the underlying type (as returned by under). For
+// Type parameters, the operational type is determined
+// by the corresponding type bound's type list. The
+// result may be the bottom or top type, but it is never
+// the incoming type parameter.
+func optype(typ Type) Type {
+       if t := asTypeParam(typ); t != nil {
+               // If the optype is typ, return the top type as we have
+               // no information. It also prevents infinite recursion
+               // via the asTypeParam converter function. This can happen
+               // for a type parameter list of the form:
+               // (type T interface { type T }).
+               // See also issue #39680.
+               if u := t.Bound().allTypes; u != nil && u != typ {
+                       // u != typ and u is a type parameter => under(u) != typ, so this is ok
+                       return under(u)
+               }
+               return theTop
+       }
+       return under(typ)
+}
+
+// An instance represents an instantiated generic type syntactically
+// (without expanding the instantiation). Type instances appear only
+// during type-checking and are replaced by their fully instantiated
+// (expanded) types before the end of type-checking.
+type instance struct {
+       check   *Checker    // for lazy instantiation
+       pos     token.Pos   // position of type instantiation; for error reporting only
+       base    *Named      // parameterized type to be instantiated
+       targs   []Type      // type arguments
+       poslist []token.Pos // position of each targ; for error reporting only
+       value   Type        // base(targs...) after instantiation or Typ[Invalid]; nil if not yet set
+}
+
+// expand returns the instantiated (= expanded) type of t.
+// The result is either an instantiated *Named type, or
+// Typ[Invalid] if there was an error.
+func (t *instance) expand() Type {
+       v := t.value
+       if v == nil {
+               v = t.check.instantiate(t.pos, t.base, t.targs, t.poslist)
+               if v == nil {
+                       v = Typ[Invalid]
+               }
+               t.value = v
+       }
+       // After instantiation we must have an invalid or a *Named type.
+       if debug && v != Typ[Invalid] {
+               _ = v.(*Named)
+       }
+       return v
+}
+
+// expand expands a type instance into its instantiated
+// type and leaves all other types alone. expand does
+// not recurse.
+func expand(typ Type) Type {
+       if t, _ := typ.(*instance); t != nil {
+               return t.expand()
+       }
+       return typ
+}
+
+// expandf is set to expand.
+// Call expandf when calling expand causes compile-time cycle error.
+var expandf func(Type) Type
+
+func init() { expandf = expand }
+
+// bottom represents the bottom of the type lattice.
+// It is the underlying type of a type parameter that
+// cannot be satisfied by any type, usually because
+// the intersection of type constraints left nothing).
+type bottom struct{}
+
+// theBottom is the singleton bottom type.
+var theBottom = &bottom{}
+
+// top represents the top of the type lattice.
+// It is the underlying type of a type parameter that
+// can be satisfied by any type (ignoring methods),
+// usually because the type constraint has no type
+// list.
+type top struct{}
+
+// theTop is the singleton top type.
+var theTop = &top{}
+
+// Type-specific implementations of Underlying.
+func (t *Basic) Underlying() Type      { return t }
+func (t *Array) Underlying() Type      { return t }
+func (t *Slice) Underlying() Type      { return t }
+func (t *Struct) Underlying() Type     { return t }
+func (t *Pointer) Underlying() Type    { return t }
+func (t *Tuple) Underlying() Type      { return t }
+func (t *Signature) Underlying() Type  { return t }
+func (t *_Sum) Underlying() Type       { return t }
+func (t *Interface) Underlying() Type  { return t }
+func (t *Map) Underlying() Type        { return t }
+func (t *Chan) Underlying() Type       { return t }
+func (t *Named) Underlying() Type      { return t.underlying }
+func (t *_TypeParam) Underlying() Type { return t }
+func (t *instance) Underlying() Type   { return t }
+func (t *bottom) Underlying() Type     { return t }
+func (t *top) Underlying() Type        { return t }
+
+// Type-specific implementations of String.
+func (t *Basic) String() string      { return TypeString(t, nil) }
+func (t *Array) String() string      { return TypeString(t, nil) }
+func (t *Slice) String() string      { return TypeString(t, nil) }
+func (t *Struct) String() string     { return TypeString(t, nil) }
+func (t *Pointer) String() string    { return TypeString(t, nil) }
+func (t *Tuple) String() string      { return TypeString(t, nil) }
+func (t *Signature) String() string  { return TypeString(t, nil) }
+func (t *_Sum) String() string       { return TypeString(t, nil) }
+func (t *Interface) String() string  { return TypeString(t, nil) }
+func (t *Map) String() string        { return TypeString(t, nil) }
+func (t *Chan) String() string       { return TypeString(t, nil) }
+func (t *Named) String() string      { return TypeString(t, nil) }
+func (t *_TypeParam) String() string { return TypeString(t, nil) }
+func (t *instance) String() string   { return TypeString(t, nil) }
+func (t *bottom) String() string     { return TypeString(t, nil) }
+func (t *top) String() string        { return TypeString(t, nil) }
+
+// under returns the true expanded underlying type.
+// If it doesn't exist, the result is Typ[Invalid].
+// under must only be called when a type is known
+// to be fully set up.
+func under(t Type) Type {
+       // TODO(gri) is this correct for *Sum?
+       if n := asNamed(t); n != nil {
+               return n.under()
+       }
+       return t
+}
+
+// Converters
+//
+// A converter must only be called when a type is
+// known to be fully set up. A converter returns
+// a type's operational type (see comment for optype)
+// or nil if the type argument is not of the
+// respective type.
+
+func asBasic(t Type) *Basic {
+       op, _ := optype(t).(*Basic)
+       return op
+}
+
+func asArray(t Type) *Array {
+       op, _ := optype(t).(*Array)
+       return op
+}
+
+func asSlice(t Type) *Slice {
+       op, _ := optype(t).(*Slice)
+       return op
+}
+
+func asStruct(t Type) *Struct {
+       op, _ := optype(t).(*Struct)
+       return op
+}
+
+func asPointer(t Type) *Pointer {
+       op, _ := optype(t).(*Pointer)
+       return op
+}
+
+func asTuple(t Type) *Tuple {
+       op, _ := optype(t).(*Tuple)
+       return op
+}
+
+func asSignature(t Type) *Signature {
+       op, _ := optype(t).(*Signature)
+       return op
+}
+
+func asSum(t Type) *_Sum {
+       op, _ := optype(t).(*_Sum)
+       return op
+}
+
+func asInterface(t Type) *Interface {
+       op, _ := optype(t).(*Interface)
+       return op
+}
+
+func asMap(t Type) *Map {
+       op, _ := optype(t).(*Map)
+       return op
+}
+
+func asChan(t Type) *Chan {
+       op, _ := optype(t).(*Chan)
+       return op
+}
+
+// If the argument to asNamed and asTypeParam is of the respective types
+// (possibly after expanding an instance type), these methods return that type.
+// Otherwise the result is nil.
+
+func asNamed(t Type) *Named {
+       e, _ := expand(t).(*Named)
+       return e
+}
+
+func asTypeParam(t Type) *_TypeParam {
+       u, _ := under(t).(*_TypeParam)
+       return u
+}
diff --git a/libgo/go/go/types/types_test.go b/libgo/go/go/types/types_test.go
new file mode 100644 (file)
index 0000000..25cd996
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types
+
+import "sync/atomic"
+
+// Upon calling ResetId, nextId starts with 1 again.
+// It may be called concurrently. This is only needed
+// for tests where we may want to have a consistent
+// numbering for each individual test case.
+func ResetId() { atomic.StoreUint32(&lastId, 0) }
+
+// SetGoVersion sets the unexported goVersion field on config, so that tests
+// which assert on behavior for older Go versions can set it.
+func SetGoVersion(config *Config, goVersion string) {
+       config.goVersion = goVersion
+}
index 31c572f83b1234f8c48ad83a8d26513bce8343f0..fe27f0f276c30e5127b2a0d61c1145b56b1105cf 100644 (file)
@@ -9,6 +9,8 @@ package types
 import (
        "bytes"
        "fmt"
+       "go/token"
+       "unicode/utf8"
 )
 
 // A Qualifier controls how named package-level objects are printed in
@@ -75,6 +77,10 @@ func WriteType(buf *bytes.Buffer, typ Type, qf Qualifier) {
        writeType(buf, typ, qf, make([]Type, 0, 8))
 }
 
+// instanceMarker is the prefix for an instantiated type
+// in "non-evaluated" instance form.
+const instanceMarker = '#'
+
 func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) {
        // Theoretically, this is a quadratic lookup algorithm, but in
        // practice deeply nested composite types with unnamed component
@@ -82,7 +88,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) {
        // using a map.
        for _, t := range visited {
                if t == typ {
-                       fmt.Fprintf(buf, "○%T", typ) // cycle to typ
+                       fmt.Fprintf(buf, "○%T", goTypeName(typ)) // cycle to typ
                        return
                }
        }
@@ -93,9 +99,15 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) {
                buf.WriteString("<nil>")
 
        case *Basic:
-               if t.kind == UnsafePointer {
-                       buf.WriteString("unsafe.")
+               // exported basic types go into package unsafe
+               // (currently this is just unsafe.Pointer)
+               if token.IsExported(t.name) {
+                       if obj, _ := Unsafe.scope.Lookup(t.name).(*TypeName); obj != nil {
+                               writeTypeName(buf, obj, qf)
+                               break
+                       }
                }
+
                if gcCompatibilityMode {
                        // forget the alias names
                        switch t.kind {
@@ -121,6 +133,9 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) {
                        if i > 0 {
                                buf.WriteString("; ")
                        }
+                       // This doesn't do the right thing for embedded type
+                       // aliases where we should print the alias name, not
+                       // the aliased type (see issue #44410).
                        if !f.embedded {
                                buf.WriteString(f.name)
                                buf.WriteByte(' ')
@@ -143,6 +158,14 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) {
                buf.WriteString("func")
                writeSignature(buf, t, qf, visited)
 
+       case *_Sum:
+               for i, t := range t.types {
+                       if i > 0 {
+                               buf.WriteString(", ")
+                       }
+                       writeType(buf, t, qf, visited)
+               }
+
        case *Interface:
                // We write the source-level methods and embedded types rather
                // than the actual method set since resolved method signatures
@@ -168,6 +191,13 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) {
                                writeSignature(buf, m.typ.(*Signature), qf, visited)
                                empty = false
                        }
+                       if !empty && t.allTypes != nil {
+                               buf.WriteString("; ")
+                       }
+                       if t.allTypes != nil {
+                               buf.WriteString("type ")
+                               writeType(buf, t.allTypes, qf, visited)
+                       }
                } else {
                        // print explicit interface methods and embedded types
                        for i, m := range t.methods {
@@ -178,8 +208,19 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) {
                                writeSignature(buf, m.typ.(*Signature), qf, visited)
                                empty = false
                        }
+                       if !empty && t.types != nil {
+                               buf.WriteString("; ")
+                       }
+                       if t.types != nil {
+                               buf.WriteString("type ")
+                               writeType(buf, t.types, qf, visited)
+                               empty = false
+                       }
+                       if !empty && len(t.embeddeds) > 0 {
+                               buf.WriteString("; ")
+                       }
                        for i, typ := range t.embeddeds {
-                               if i > 0 || len(t.methods) > 0 {
+                               if i > 0 {
                                        buf.WriteString("; ")
                                }
                                writeType(buf, typ, qf, visited)
@@ -227,17 +268,36 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) {
                }
 
        case *Named:
-               s := "<Named w/o object>"
-               if obj := t.obj; obj != nil {
-                       if obj.pkg != nil {
-                               writePackage(buf, obj.pkg, qf)
-                       }
-                       // TODO(gri): function-local named types should be displayed
-                       // differently from named types at package level to avoid
-                       // ambiguity.
-                       s = obj.name
+               writeTypeName(buf, t.obj, qf)
+               if t.targs != nil {
+                       // instantiated type
+                       buf.WriteByte('[')
+                       writeTypeList(buf, t.targs, qf, visited)
+                       buf.WriteByte(']')
+               } else if t.tparams != nil {
+                       // parameterized type
+                       writeTParamList(buf, t.tparams, qf, visited)
                }
-               buf.WriteString(s)
+
+       case *_TypeParam:
+               s := "?"
+               if t.obj != nil {
+                       s = t.obj.name
+               }
+               buf.WriteString(s + subscript(t.id))
+
+       case *instance:
+               buf.WriteByte(instanceMarker) // indicate "non-evaluated" syntactic instance
+               writeTypeName(buf, t.base.obj, qf)
+               buf.WriteByte('[')
+               writeTypeList(buf, t.targs, qf, visited)
+               buf.WriteByte(']')
+
+       case *bottom:
+               buf.WriteString("⊥")
+
+       case *top:
+               buf.WriteString("⊤")
 
        default:
                // For externally defined implementations of Type.
@@ -245,6 +305,62 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) {
        }
 }
 
+func writeTypeList(buf *bytes.Buffer, list []Type, qf Qualifier, visited []Type) {
+       for i, typ := range list {
+               if i > 0 {
+                       buf.WriteString(", ")
+               }
+               writeType(buf, typ, qf, visited)
+       }
+}
+
+func writeTParamList(buf *bytes.Buffer, list []*TypeName, qf Qualifier, visited []Type) {
+       // TODO(rFindley) compare this with the corresponding implementation in types2
+       buf.WriteString("[")
+       var prev Type
+       for i, p := range list {
+               // TODO(rFindley) support 'any' sugar here.
+               var b Type = &emptyInterface
+               if t, _ := p.typ.(*_TypeParam); t != nil && t.bound != nil {
+                       b = t.bound
+               }
+               if i > 0 {
+                       if b != prev {
+                               // type bound changed - write previous one before advancing
+                               buf.WriteByte(' ')
+                               writeType(buf, prev, qf, visited)
+                       }
+                       buf.WriteString(", ")
+               }
+               prev = b
+
+               if t, _ := p.typ.(*_TypeParam); t != nil {
+                       writeType(buf, t, qf, visited)
+               } else {
+                       buf.WriteString(p.name)
+               }
+       }
+       if prev != nil {
+               buf.WriteByte(' ')
+               writeType(buf, prev, qf, visited)
+       }
+       buf.WriteByte(']')
+}
+
+func writeTypeName(buf *bytes.Buffer, obj *TypeName, qf Qualifier) {
+       s := "<Named w/o object>"
+       if obj != nil {
+               if obj.pkg != nil {
+                       writePackage(buf, obj.pkg, qf)
+               }
+               // TODO(gri): function-local named types should be displayed
+               // differently from named types at package level to avoid
+               // ambiguity.
+               s = obj.name
+       }
+       buf.WriteString(s)
+}
+
 func writeTuple(buf *bytes.Buffer, tup *Tuple, variadic bool, qf Qualifier, visited []Type) {
        buf.WriteByte('(')
        if tup != nil {
@@ -264,7 +380,7 @@ func writeTuple(buf *bytes.Buffer, tup *Tuple, variadic bool, qf Qualifier, visi
                                } else {
                                        // special case:
                                        // append(s, "foo"...) leads to signature func([]byte, string...)
-                                       if t, ok := typ.Underlying().(*Basic); !ok || t.kind != String {
+                                       if t := asBasic(typ); t == nil || t.kind != String {
                                                panic("internal error: string type expected")
                                        }
                                        writeType(buf, typ, qf, visited)
@@ -287,6 +403,10 @@ func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) {
 }
 
 func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []Type) {
+       if sig.tparams != nil {
+               writeTParamList(buf, sig.tparams, qf, visited)
+       }
+
        writeTuple(buf, sig.params, sig.variadic, qf, visited)
 
        n := sig.results.Len()
@@ -305,3 +425,19 @@ func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []T
        // multiple or named result(s)
        writeTuple(buf, sig.results, false, qf, visited)
 }
+
+// subscript returns the decimal (utf8) representation of x using subscript digits.
+func subscript(x uint64) string {
+       const w = len("₀") // all digits 0...9 have the same utf8 width
+       var buf [32 * w]byte
+       i := len(buf)
+       for {
+               i -= w
+               utf8.EncodeRune(buf[i:], '₀'+rune(x%10)) // '₀' == U+2080
+               x /= 10
+               if x == 0 {
+                       break
+               }
+       }
+       return string(buf[i:])
+}
index a2241ca9eb81f317aced41e37ad683cb496f1ac4..07ed73529ca64df3df01ee87773d01db3209e6ee 100644 (file)
@@ -96,6 +96,10 @@ var independentTestTypes = []testEntry{
        dup("interface{m()}"),
        dup(`interface{String() string; m(int) float32}`),
 
+       // TODO(rFindley) uncomment this once this AST is accepted, and add more test
+       // cases.
+       // dup(`interface{type int, float32, complex128}`),
+
        // maps
        dup("map[string]int"),
        {"map[struct{x, y int}][]byte", "map[struct{x int; y int}][]byte"},
index 2b398010f4d0483f231c9c01b0862b2fbdcf5732..1738d864a6573965f9bf5cf626b9b9a48fdb60ec 100644 (file)
@@ -7,11 +7,14 @@
 package types
 
 import (
+       "fmt"
        "go/ast"
        "go/constant"
+       "go/internal/typeparams"
        "go/token"
        "sort"
        "strconv"
+       "strings"
 )
 
 // ident type-checks identifier e and initializes x with the value or type of e.
@@ -51,12 +54,12 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool)
        }
        assert(typ != nil)
 
-       // The object may be dot-imported: If so, remove its package from
-       // the map of unused dot imports for the respective file scope.
+       // The object may have been dot-imported.
+       // If so, mark the respective package as used.
        // (This code is only needed for dot-imports. Without them,
        // we only have to mark variables, see *Var case below).
-       if pkg := obj.Pkg(); pkg != check.pkg && pkg != nil {
-               delete(check.unusedDotImports[scope], pkg)
+       if pkgName := check.dotImportMap[dotImportKey{scope, obj}]; pkgName != nil {
+               pkgName.used = true
        }
 
        switch obj := obj.(type) {
@@ -116,41 +119,220 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool)
 }
 
 // typ type-checks the type expression e and returns its type, or Typ[Invalid].
+// The type must not be an (uninstantiated) generic type.
 func (check *Checker) typ(e ast.Expr) Type {
        return check.definedType(e, nil)
 }
 
+// varType type-checks the type expression e and returns its type, or Typ[Invalid].
+// The type must not be an (uninstantiated) generic type and it must be ordinary
+// (see ordinaryType).
+func (check *Checker) varType(e ast.Expr) Type {
+       typ := check.definedType(e, nil)
+       check.ordinaryType(e, typ)
+       return typ
+}
+
+// ordinaryType reports an error if typ is an interface type containing
+// type lists or is (or embeds) the predeclared type comparable.
+func (check *Checker) ordinaryType(pos positioner, typ Type) {
+       // We don't want to call under() (via asInterface) or complete interfaces
+       // while we are in the middle of type-checking parameter declarations that
+       // might belong to interface methods. Delay this check to the end of
+       // type-checking.
+       check.later(func() {
+               if t := asInterface(typ); t != nil {
+                       check.completeInterface(pos.Pos(), t) // TODO(gri) is this the correct position?
+                       if t.allTypes != nil {
+                               check.softErrorf(pos, _Todo, "interface contains type constraints (%s)", t.allTypes)
+                               return
+                       }
+                       if t._IsComparable() {
+                               check.softErrorf(pos, _Todo, "interface is (or embeds) comparable")
+                       }
+               }
+       })
+}
+
+// anyType type-checks the type expression e and returns its type, or Typ[Invalid].
+// The type may be generic or instantiated.
+func (check *Checker) anyType(e ast.Expr) Type {
+       typ := check.typInternal(e, nil)
+       assert(isTyped(typ))
+       check.recordTypeAndValue(e, typexpr, typ, nil)
+       return typ
+}
+
 // definedType is like typ but also accepts a type name def.
 // If def != nil, e is the type specification for the defined type def, declared
 // in a type declaration, and def.underlying will be set to the type of e before
 // any components of e are type-checked.
 //
-func (check *Checker) definedType(e ast.Expr, def *Named) (T Type) {
-       if trace {
-               check.trace(e.Pos(), "%s", e)
-               check.indent++
-               defer func() {
-                       check.indent--
-                       check.trace(e.Pos(), "=> %s", T)
-               }()
+func (check *Checker) definedType(e ast.Expr, def *Named) Type {
+       typ := check.typInternal(e, def)
+       assert(isTyped(typ))
+       if isGeneric(typ) {
+               check.errorf(e, _Todo, "cannot use generic type %s without instantiation", typ)
+               typ = Typ[Invalid]
        }
+       check.recordTypeAndValue(e, typexpr, typ, nil)
+       return typ
+}
 
-       T = check.typInternal(e, def)
-       assert(isTyped(T))
-       check.recordTypeAndValue(e, typexpr, T, nil)
+// genericType is like typ but the type must be an (uninstantiated) generic type.
+func (check *Checker) genericType(e ast.Expr, reportErr bool) Type {
+       typ := check.typInternal(e, nil)
+       assert(isTyped(typ))
+       if typ != Typ[Invalid] && !isGeneric(typ) {
+               if reportErr {
+                       check.errorf(e, _Todo, "%s is not a generic type", typ)
+               }
+               typ = Typ[Invalid]
+       }
+       // TODO(gri) what is the correct call below?
+       check.recordTypeAndValue(e, typexpr, typ, nil)
+       return typ
+}
 
-       return
+// isubst returns an x with identifiers substituted per the substitution map smap.
+// isubst only handles the case of (valid) method receiver type expressions correctly.
+func isubst(x ast.Expr, smap map[*ast.Ident]*ast.Ident) ast.Expr {
+       switch n := x.(type) {
+       case *ast.Ident:
+               if alt := smap[n]; alt != nil {
+                       return alt
+               }
+       case *ast.StarExpr:
+               X := isubst(n.X, smap)
+               if X != n.X {
+                       new := *n
+                       new.X = X
+                       return &new
+               }
+       case *ast.IndexExpr:
+               elems := typeparams.UnpackExpr(n.Index)
+               var newElems []ast.Expr
+               for i, elem := range elems {
+                       new := isubst(elem, smap)
+                       if new != elem {
+                               if newElems == nil {
+                                       newElems = make([]ast.Expr, len(elems))
+                                       copy(newElems, elems)
+                               }
+                               newElems[i] = new
+                       }
+               }
+               if newElems != nil {
+                       index := typeparams.PackExpr(newElems)
+                       new := *n
+                       new.Index = index
+                       return &new
+               }
+       case *ast.ParenExpr:
+               return isubst(n.X, smap) // no need to keep parentheses
+       default:
+               // Other receiver type expressions are invalid.
+               // It's fine to ignore those here as they will
+               // be checked elsewhere.
+       }
+       return x
 }
 
 // funcType type-checks a function or method type.
 func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast.FuncType) {
-       scope := NewScope(check.scope, token.NoPos, token.NoPos, "function")
-       scope.isFunc = true
-       check.recordScope(ftyp, scope)
+       check.openScope(ftyp, "function")
+       check.scope.isFunc = true
+       check.recordScope(ftyp, check.scope)
+       sig.scope = check.scope
+       defer check.closeScope()
+
+       var recvTyp ast.Expr // rewritten receiver type; valid if != nil
+       if recvPar != nil && len(recvPar.List) > 0 {
+               // collect generic receiver type parameters, if any
+               // - a receiver type parameter is like any other type parameter, except that it is declared implicitly
+               // - the receiver specification acts as local declaration for its type parameters, which may be blank
+               _, rname, rparams := check.unpackRecv(recvPar.List[0].Type, true)
+               if len(rparams) > 0 {
+                       // Blank identifiers don't get declared and regular type-checking of the instantiated
+                       // parameterized receiver type expression fails in Checker.collectParams of receiver.
+                       // Identify blank type parameters and substitute each with a unique new identifier named
+                       // "n_" (where n is the parameter index) and which cannot conflict with any user-defined
+                       // name.
+                       var smap map[*ast.Ident]*ast.Ident // substitution map from "_" to "n_" identifiers
+                       for i, p := range rparams {
+                               if p.Name == "_" {
+                                       new := *p
+                                       new.Name = fmt.Sprintf("%d_", i)
+                                       rparams[i] = &new // use n_ identifier instead of _ so it can be looked up
+                                       if smap == nil {
+                                               smap = make(map[*ast.Ident]*ast.Ident)
+                                       }
+                                       smap[p] = &new
+                               }
+                       }
+                       if smap != nil {
+                               // blank identifiers were found => use rewritten receiver type
+                               recvTyp = isubst(recvPar.List[0].Type, smap)
+                       }
+                       sig.rparams = check.declareTypeParams(nil, rparams)
+                       // determine receiver type to get its type parameters
+                       // and the respective type parameter bounds
+                       var recvTParams []*TypeName
+                       if rname != nil {
+                               // recv should be a Named type (otherwise an error is reported elsewhere)
+                               // Also: Don't report an error via genericType since it will be reported
+                               //       again when we type-check the signature.
+                               // TODO(gri) maybe the receiver should be marked as invalid instead?
+                               if recv := asNamed(check.genericType(rname, false)); recv != nil {
+                                       recvTParams = recv.tparams
+                               }
+                       }
+                       // provide type parameter bounds
+                       // - only do this if we have the right number (otherwise an error is reported elsewhere)
+                       if len(sig.rparams) == len(recvTParams) {
+                               // We have a list of *TypeNames but we need a list of Types.
+                               list := make([]Type, len(sig.rparams))
+                               for i, t := range sig.rparams {
+                                       list[i] = t.typ
+                               }
+                               smap := makeSubstMap(recvTParams, list)
+                               for i, tname := range sig.rparams {
+                                       bound := recvTParams[i].typ.(*_TypeParam).bound
+                                       // bound is (possibly) parameterized in the context of the
+                                       // receiver type declaration. Substitute parameters for the
+                                       // current context.
+                                       // TODO(gri) should we assume now that bounds always exist?
+                                       //           (no bound == empty interface)
+                                       if bound != nil {
+                                               bound = check.subst(tname.pos, bound, smap)
+                                               tname.typ.(*_TypeParam).bound = bound
+                                       }
+                               }
+                       }
+               }
+       }
 
-       recvList, _ := check.collectParams(scope, recvPar, false)
-       params, variadic := check.collectParams(scope, ftyp.Params, true)
-       results, _ := check.collectParams(scope, ftyp.Results, false)
+       if tparams := typeparams.Get(ftyp); tparams != nil {
+               sig.tparams = check.collectTypeParams(tparams)
+               // Always type-check method type parameters but complain that they are not allowed.
+               // (A separate check is needed when type-checking interface method signatures because
+               // they don't have a receiver specification.)
+               if recvPar != nil {
+                       check.errorf(tparams, _Todo, "methods cannot have type parameters")
+               }
+       }
+
+       // Value (non-type) parameters' scope starts in the function body. Use a temporary scope for their
+       // declarations and then squash that scope into the parent scope (and report any redeclarations at
+       // that time).
+       scope := NewScope(check.scope, token.NoPos, token.NoPos, "function body (temp. scope)")
+       recvList, _ := check.collectParams(scope, recvPar, recvTyp, false) // use rewritten receiver type, if any
+       params, variadic := check.collectParams(scope, ftyp.Params, nil, true)
+       results, _ := check.collectParams(scope, ftyp.Results, nil, false)
+       scope.squash(func(obj, alt Object) {
+               check.errorf(obj, _DuplicateDecl, "%s redeclared in this block", obj.Name())
+               check.reportAltDecl(alt)
+       })
 
        if recvPar != nil {
                // recv parameter list present (may be empty)
@@ -159,7 +341,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
                var recv *Var
                switch len(recvList) {
                case 0:
-                       check.error(recvPar, _BadRecv, "method is missing receiver")
+                       // error reported by resolver
                        recv = NewParam(0, nil, "", Typ[Invalid]) // ignore recv below
                default:
                        // more than one receiver
@@ -168,19 +350,24 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
                case 1:
                        recv = recvList[0]
                }
+
+               // TODO(gri) We should delay rtyp expansion to when we actually need the
+               //           receiver; thus all checks here should be delayed to later.
+               rtyp, _ := deref(recv.typ)
+               rtyp = expand(rtyp)
+
                // spec: "The receiver type must be of the form T or *T where T is a type name."
                // (ignore invalid types - error was reported before)
-               if t, _ := deref(recv.typ); t != Typ[Invalid] {
+               if t := rtyp; t != Typ[Invalid] {
                        var err string
-                       if T, _ := t.(*Named); T != nil {
+                       if T := asNamed(t); T != nil {
                                // spec: "The type denoted by T is called the receiver base type; it must not
                                // be a pointer or interface type and it must be declared in the same package
                                // as the method."
                                if T.obj.pkg != check.pkg {
                                        err = "type not defined in this package"
                                } else {
-                                       // TODO(gri) This is not correct if the underlying type is unknown yet.
-                                       switch u := T.underlying.(type) {
+                                       switch u := optype(T).(type) {
                                        case *Basic:
                                                // unsafe.Pointer is treated like a regular pointer
                                                if u.kind == UnsafePointer {
@@ -201,17 +388,43 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
                sig.recv = recv
        }
 
-       sig.scope = scope
        sig.params = NewTuple(params...)
        sig.results = NewTuple(results...)
        sig.variadic = variadic
 }
 
+// goTypeName returns the Go type name for typ and
+// removes any occurrences of "types." from that name.
+func goTypeName(typ Type) string {
+       return strings.ReplaceAll(fmt.Sprintf("%T", typ), "types.", "")
+}
+
 // typInternal drives type checking of types.
-// Must only be called by definedType.
+// Must only be called by definedType or genericType.
 //
-func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
-       switch e := e.(type) {
+func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
+       if trace {
+               check.trace(e0.Pos(), "type %s", e0)
+               check.indent++
+               defer func() {
+                       check.indent--
+                       var under Type
+                       if T != nil {
+                               // Calling under() here may lead to endless instantiations.
+                               // Test case: type T[P any] *T[P]
+                               // TODO(gri) investigate if that's a bug or to be expected
+                               // (see also analogous comment in Checker.instantiate).
+                               under = T.Underlying()
+                       }
+                       if T == under {
+                               check.trace(e0.Pos(), "=> %s // %s", T, goTypeName(T))
+                       } else {
+                               check.trace(e0.Pos(), "=> %s (under = %s) // %s", T, under, goTypeName(T))
+                       }
+               }()
+       }
+
+       switch e := e0.(type) {
        case *ast.BadExpr:
                // ignore - error reported before
 
@@ -249,7 +462,17 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
                        check.errorf(&x, _NotAType, "%s is not a type", &x)
                }
 
+       case *ast.IndexExpr:
+               if typeparams.Enabled {
+                       exprs := typeparams.UnpackExpr(e.Index)
+                       return check.instantiatedType(e.X, exprs, def)
+               }
+               check.errorf(e0, _NotAType, "%s is not a type", e0)
+               check.use(e.X)
+
        case *ast.ParenExpr:
+               // Generic types must be instantiated before they can be used in any form.
+               // Consequently, generic types cannot be parenthesized.
                return check.definedType(e.X, def)
 
        case *ast.ArrayType:
@@ -257,16 +480,21 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
                        typ := new(Array)
                        def.setUnderlying(typ)
                        typ.len = check.arrayLength(e.Len)
-                       typ.elem = check.typ(e.Elt)
-                       return typ
-
-               } else {
-                       typ := new(Slice)
-                       def.setUnderlying(typ)
-                       typ.elem = check.typ(e.Elt)
+                       typ.elem = check.varType(e.Elt)
                        return typ
                }
 
+               typ := new(Slice)
+               def.setUnderlying(typ)
+               typ.elem = check.varType(e.Elt)
+               return typ
+
+       case *ast.Ellipsis:
+               // dots are handled explicitly where they are legal
+               // (array composite literals and parameter lists)
+               check.error(e, _InvalidDotDotDot, "invalid use of '...'")
+               check.use(e.Elt)
+
        case *ast.StructType:
                typ := new(Struct)
                def.setUnderlying(typ)
@@ -276,7 +504,7 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
        case *ast.StarExpr:
                typ := new(Pointer)
                def.setUnderlying(typ)
-               typ.base = check.typ(e.X)
+               typ.base = check.varType(e.X)
                return typ
 
        case *ast.FuncType:
@@ -288,6 +516,9 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
        case *ast.InterfaceType:
                typ := new(Interface)
                def.setUnderlying(typ)
+               if def != nil {
+                       typ.obj = def.obj
+               }
                check.interfaceType(typ, e, def)
                return typ
 
@@ -295,8 +526,8 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
                typ := new(Map)
                def.setUnderlying(typ)
 
-               typ.key = check.typ(e.Key)
-               typ.elem = check.typ(e.Value)
+               typ.key = check.varType(e.Key)
+               typ.elem = check.varType(e.Value)
 
                // spec: "The comparison operators == and != must be fully defined
                // for operands of the key type; thus the key type must not be a
@@ -304,9 +535,13 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
                //
                // Delay this check because it requires fully setup types;
                // it is safe to continue in any case (was issue 6667).
-               check.atEnd(func() {
+               check.later(func() {
                        if !Comparable(typ.key) {
-                               check.errorf(e.Key, _IncomparableMapKey, "incomparable map key type %s", typ.key)
+                               var why string
+                               if asTypeParam(typ.key) != nil {
+                                       why = " (missing comparable constraint)"
+                               }
+                               check.errorf(e.Key, _IncomparableMapKey, "incomparable map key type %s%s", typ.key, why)
                        }
                })
 
@@ -330,11 +565,11 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
                }
 
                typ.dir = dir
-               typ.elem = check.typ(e.Value)
+               typ.elem = check.varType(e.Value)
                return typ
 
        default:
-               check.errorf(e, _NotAType, "%s is not a type", e)
+               check.errorf(e0, _NotAType, "%s is not a type", e0)
        }
 
        typ := Typ[Invalid]
@@ -343,10 +578,11 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
 }
 
 // typeOrNil type-checks the type expression (or nil value) e
-// and returns the typ of e, or nil.
-// If e is neither a type nor nil, typOrNil returns Typ[Invalid].
-//
-func (check *Checker) typOrNil(e ast.Expr) Type {
+// and returns the type of e, or nil. If e is a type, it must
+// not be an (uninstantiated) generic type.
+// If e is neither a type nor nil, typeOrNil returns Typ[Invalid].
+// TODO(gri) should we also disallow non-var types?
+func (check *Checker) typeOrNil(e ast.Expr) Type {
        var x operand
        check.rawExpr(&x, e, nil)
        switch x.mode {
@@ -355,6 +591,7 @@ func (check *Checker) typOrNil(e ast.Expr) Type {
        case novalue:
                check.errorf(&x, _NotAType, "%s used as type", &x)
        case typexpr:
+               check.instantiatedOperand(&x)
                return x.typ
        case value:
                if x.isNil() {
@@ -367,6 +604,49 @@ func (check *Checker) typOrNil(e ast.Expr) Type {
        return Typ[Invalid]
 }
 
+func (check *Checker) instantiatedType(x ast.Expr, targs []ast.Expr, def *Named) Type {
+       b := check.genericType(x, true) // TODO(gri) what about cycles?
+       if b == Typ[Invalid] {
+               return b // error already reported
+       }
+       base := asNamed(b)
+       if base == nil {
+               unreachable() // should have been caught by genericType
+       }
+
+       // create a new type instance rather than instantiate the type
+       // TODO(gri) should do argument number check here rather than
+       //           when instantiating the type?
+       typ := new(instance)
+       def.setUnderlying(typ)
+
+       typ.check = check
+       typ.pos = x.Pos()
+       typ.base = base
+
+       // evaluate arguments (always)
+       typ.targs = check.typeList(targs)
+       if typ.targs == nil {
+               def.setUnderlying(Typ[Invalid]) // avoid later errors due to lazy instantiation
+               return Typ[Invalid]
+       }
+
+       // determine argument positions (for error reporting)
+       typ.poslist = make([]token.Pos, len(targs))
+       for i, arg := range targs {
+               typ.poslist[i] = arg.Pos()
+       }
+
+       // make sure we check instantiation works at least once
+       // and that the resulting type is valid
+       check.later(func() {
+               t := typ.expand()
+               check.validType(t, nil)
+       })
+
+       return typ
+}
+
 // arrayLength type-checks the array length expression e
 // and returns the constant length >= 0, or a value < 0
 // to indicate an error (and thus an unknown length).
@@ -394,7 +674,25 @@ func (check *Checker) arrayLength(e ast.Expr) int64 {
        return -1
 }
 
-func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicOk bool) (params []*Var, variadic bool) {
+// typeList provides the list of types corresponding to the incoming expression list.
+// If an error occurred, the result is nil, but all list elements were type-checked.
+func (check *Checker) typeList(list []ast.Expr) []Type {
+       res := make([]Type, len(list)) // res != nil even if len(list) == 0
+       for i, x := range list {
+               t := check.varType(x)
+               if t == Typ[Invalid] {
+                       res = nil
+               }
+               if res != nil {
+                       res[i] = t
+               }
+       }
+       return res
+}
+
+// collectParams declares the parameters of list in scope and returns the corresponding
+// variable list. If type0 != nil, it is used instead of the first type in list.
+func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, type0 ast.Expr, variadicOk bool) (params []*Var, variadic bool) {
        if list == nil {
                return
        }
@@ -402,6 +700,9 @@ func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicO
        var named, anonymous bool
        for i, field := range list.List {
                ftype := field.Type
+               if i == 0 && type0 != nil {
+                       ftype = type0
+               }
                if t, _ := ftype.(*ast.Ellipsis); t != nil {
                        ftype = t.Elt
                        if variadicOk && i == len(list.List)-1 && len(field.Names) <= 1 {
@@ -411,7 +712,7 @@ func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicO
                                // ignore ... and continue
                        }
                }
-               typ := check.typ(ftype)
+               typ := check.varType(ftype)
                // The parser ensures that f.Tag is nil and we don't
                // care if a constructed AST contains a non-nil tag.
                if len(field.Names) > 0 {
@@ -462,9 +763,12 @@ func (check *Checker) declareInSet(oset *objset, pos token.Pos, obj Object) bool
 }
 
 func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *Named) {
+       var tlist *ast.Ident // "type" name of first entry in a type list declaration
+       var types []ast.Expr
        for _, f := range iface.Methods.List {
                if len(f.Names) > 0 {
-                       // We have a method with name f.Names[0].
+                       // We have a method with name f.Names[0], or a type
+                       // of a type list (name.Name == "type").
                        // (The parser ensures that there's only one method
                        // and we don't care if a constructed AST has more.)
                        name := f.Names[0]
@@ -473,6 +777,18 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
                                continue // ignore
                        }
 
+                       if name.Name == "type" {
+                               // Always collect all type list entries, even from
+                               // different type lists, under the assumption that
+                               // the author intended to include all types.
+                               types = append(types, f.Type)
+                               if tlist != nil && tlist != name {
+                                       check.errorf(name, _Todo, "cannot have multiple type lists in an interface")
+                               }
+                               tlist = name
+                               continue
+                       }
+
                        typ := check.typ(f.Type)
                        sig, _ := typ.(*Signature)
                        if sig == nil {
@@ -482,6 +798,17 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
                                continue // ignore
                        }
 
+                       // Always type-check method type parameters but complain if they are not enabled.
+                       // (This extra check is needed here because interface method signatures don't have
+                       // a receiver specification.)
+                       if sig.tparams != nil {
+                               var at positioner = f.Type
+                               if tparams := typeparams.Get(f.Type); tparams != nil {
+                                       at = tparams
+                               }
+                               check.errorf(at, _Todo, "methods cannot have type parameters")
+                       }
+
                        // use named receiver type if available (for better error messages)
                        var recvTyp Type = ityp
                        if def != nil {
@@ -493,38 +820,30 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
                        check.recordDef(name, m)
                        ityp.methods = append(ityp.methods, m)
                } else {
-                       // We have an embedded interface and f.Type is its
-                       // (possibly qualified) embedded type name. Collect
-                       // it if it's a valid interface.
-                       typ := check.typ(f.Type)
-
-                       utyp := check.underlying(typ)
-                       if _, ok := utyp.(*Interface); !ok {
-                               if utyp != Typ[Invalid] {
-                                       check.errorf(f.Type, _InvalidIfaceEmbed, "%s is not an interface", typ)
-                               }
-                               continue
-                       }
-
-                       ityp.embeddeds = append(ityp.embeddeds, typ)
+                       // We have an embedded type. completeInterface will
+                       // eventually verify that we have an interface.
+                       ityp.embeddeds = append(ityp.embeddeds, check.typ(f.Type))
                        check.posMap[ityp] = append(check.posMap[ityp], f.Type.Pos())
                }
        }
 
-       if len(ityp.methods) == 0 && len(ityp.embeddeds) == 0 {
+       // type constraints
+       ityp.types = _NewSum(check.collectTypeConstraints(iface.Pos(), types))
+
+       if len(ityp.methods) == 0 && ityp.types == nil && len(ityp.embeddeds) == 0 {
                // empty interface
                ityp.allMethods = markComplete
                return
        }
 
        // sort for API stability
-       sort.Sort(byUniqueMethodName(ityp.methods))
-       sort.Stable(byUniqueTypeName(ityp.embeddeds))
+       sortMethods(ityp.methods)
+       sortTypes(ityp.embeddeds)
 
-       check.later(func() { check.completeInterface(ityp) })
+       check.later(func() { check.completeInterface(iface.Pos(), ityp) })
 }
 
-func (check *Checker) completeInterface(ityp *Interface) {
+func (check *Checker) completeInterface(pos token.Pos, ityp *Interface) {
        if ityp.allMethods != nil {
                return
        }
@@ -538,11 +857,18 @@ func (check *Checker) completeInterface(ityp *Interface) {
        }
 
        if trace {
-               check.trace(token.NoPos, "complete %s", ityp)
+               // Types don't generally have position information.
+               // If we don't have a valid pos provided, try to use
+               // one close enough.
+               if !pos.IsValid() && len(ityp.methods) > 0 {
+                       pos = ityp.methods[0].pos
+               }
+
+               check.trace(pos, "complete %s", ityp)
                check.indent++
                defer func() {
                        check.indent--
-                       check.trace(token.NoPos, "=> %s", ityp)
+                       check.trace(pos, "=> %s (methods = %v, types = %v)", ityp, ityp.allMethods, ityp.allTypes)
                }()
        }
 
@@ -578,9 +904,13 @@ func (check *Checker) completeInterface(ityp *Interface) {
                        check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name)
                        check.errorf(atPos(mpos[other.(*Func)]), _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented
                default:
-                       // check method signatures after all types are computed (issue #33656)
-                       check.atEnd(func() {
-                               if !check.identical(m.typ, other.Type()) {
+                       // We have a duplicate method name in an embedded (not explicitly declared) method.
+                       // Check method signatures after all types are computed (issue #33656).
+                       // If we're pre-go1.14 (overlapping embeddings are not permitted), report that
+                       // error here as well (even though we could do it eagerly) because it's the same
+                       // error message.
+                       check.later(func() {
+                               if !check.allowVersion(m.pkg, 1, 14) || !check.identical(m.typ, other.Type()) {
                                        check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name)
                                        check.errorf(atPos(mpos[other.(*Func)]), _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented
                                }
@@ -592,25 +922,81 @@ func (check *Checker) completeInterface(ityp *Interface) {
                addMethod(m.pos, m, true)
        }
 
+       // collect types
+       allTypes := ityp.types
+
        posList := check.posMap[ityp]
        for i, typ := range ityp.embeddeds {
                pos := posList[i] // embedding position
-               typ, ok := check.underlying(typ).(*Interface)
-               if !ok {
-                       // An error was reported when collecting the embedded types.
-                       // Ignore it.
+               utyp := under(typ)
+               etyp := asInterface(utyp)
+               if etyp == nil {
+                       if utyp != Typ[Invalid] {
+                               var format string
+                               if _, ok := utyp.(*_TypeParam); ok {
+                                       format = "%s is a type parameter, not an interface"
+                               } else {
+                                       format = "%s is not an interface"
+                               }
+                               // TODO: correct error code.
+                               check.errorf(atPos(pos), _InvalidIfaceEmbed, format, typ)
+                       }
                        continue
                }
-               check.completeInterface(typ)
-               for _, m := range typ.allMethods {
+               check.completeInterface(pos, etyp)
+               for _, m := range etyp.allMethods {
                        addMethod(pos, m, false) // use embedding position pos rather than m.pos
                }
+               allTypes = intersect(allTypes, etyp.allTypes)
        }
 
        if methods != nil {
                sort.Sort(byUniqueMethodName(methods))
                ityp.allMethods = methods
        }
+       ityp.allTypes = allTypes
+}
+
+// intersect computes the intersection of the types x and y.
+// Note: A incomming nil type stands for the top type. A top
+// type result is returned as nil.
+func intersect(x, y Type) (r Type) {
+       defer func() {
+               if r == theTop {
+                       r = nil
+               }
+       }()
+
+       switch {
+       case x == theBottom || y == theBottom:
+               return theBottom
+       case x == nil || x == theTop:
+               return y
+       case y == nil || x == theTop:
+               return x
+       }
+
+       xtypes := unpackType(x)
+       ytypes := unpackType(y)
+       // Compute the list rtypes which includes only
+       // types that are in both xtypes and ytypes.
+       // Quadratic algorithm, but good enough for now.
+       // TODO(gri) fix this
+       var rtypes []Type
+       for _, x := range xtypes {
+               if includes(ytypes, x) {
+                       rtypes = append(rtypes, x)
+               }
+       }
+
+       if rtypes == nil {
+               return theBottom
+       }
+       return _NewSum(rtypes)
+}
+
+func sortTypes(list []Type) {
+       sort.Stable(byUniqueTypeName(list))
 }
 
 // byUniqueTypeName named type lists can be sorted by their unique type names.
@@ -621,12 +1007,25 @@ func (a byUniqueTypeName) Less(i, j int) bool { return sortName(a[i]) < sortName
 func (a byUniqueTypeName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
 
 func sortName(t Type) string {
-       if named, _ := t.(*Named); named != nil {
+       if named := asNamed(t); named != nil {
                return named.obj.Id()
        }
        return ""
 }
 
+func sortMethods(list []*Func) {
+       sort.Sort(byUniqueMethodName(list))
+}
+
+func assertSortedMethods(list []*Func) {
+       if !debug {
+               panic("internal error: assertSortedMethods called outside debug mode")
+       }
+       if !sort.IsSorted(byUniqueMethodName(list)) {
+               panic("internal error: methods not sorted")
+       }
+}
+
 // byUniqueMethodName method lists can be sorted by their unique method names.
 type byUniqueMethodName []*Func
 
@@ -690,7 +1089,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) {
        }
 
        for _, f := range list.List {
-               typ = check.typ(f.Type)
+               typ = check.varType(f.Type)
                tag = check.tag(f.Tag)
                if len(f.Names) > 0 {
                        // named fields
@@ -699,48 +1098,51 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) {
                        }
                } else {
                        // embedded field
-                       // spec: "An embedded type must be specified as a type name T or as a pointer
-                       // to a non-interface type name *T, and T itself may not be a pointer type."
+                       // spec: "An embedded type must be specified as a type name T or as a
+                       // pointer to a non-interface type name *T, and T itself may not be a
+                       // pointer type."
                        pos := f.Type.Pos()
                        name := embeddedFieldIdent(f.Type)
                        if name == nil {
-                               check.invalidAST(f.Type, "embedded field type %s has no name", f.Type)
+                               // TODO(rFindley): using invalidAST here causes test failures (all
+                               //                 errors should have codes). Clean this up.
+                               check.errorf(f.Type, _Todo, "invalid AST: embedded field type %s has no name", f.Type)
                                name = ast.NewIdent("_")
                                name.NamePos = pos
                                addInvalid(name, pos)
                                continue
                        }
-                       t, isPtr := deref(typ)
+                       add(name, true, pos)
+
                        // Because we have a name, typ must be of the form T or *T, where T is the name
                        // of a (named or alias) type, and t (= deref(typ)) must be the type of T.
-                       switch t := t.Underlying().(type) {
-                       case *Basic:
-                               if t == Typ[Invalid] {
-                                       // error was reported before
-                                       addInvalid(name, pos)
-                                       continue
-                               }
-
-                               // unsafe.Pointer is treated like a regular pointer
-                               if t.kind == UnsafePointer {
-                                       check.errorf(f.Type, _InvalidPtrEmbed, "embedded field type cannot be unsafe.Pointer")
-                                       addInvalid(name, pos)
-                                       continue
-                               }
-
-                       case *Pointer:
-                               check.errorf(f.Type, _InvalidPtrEmbed, "embedded field type cannot be a pointer")
-                               addInvalid(name, pos)
-                               continue
-
-                       case *Interface:
-                               if isPtr {
-                                       check.errorf(f.Type, _InvalidPtrEmbed, "embedded field type cannot be a pointer to an interface")
-                                       addInvalid(name, pos)
-                                       continue
+                       // We must delay this check to the end because we don't want to instantiate
+                       // (via under(t)) a possibly incomplete type.
+
+                       // for use in the closure below
+                       embeddedTyp := typ
+                       embeddedPos := f.Type
+
+                       check.later(func() {
+                               t, isPtr := deref(embeddedTyp)
+                               switch t := optype(t).(type) {
+                               case *Basic:
+                                       if t == Typ[Invalid] {
+                                               // error was reported before
+                                               return
+                                       }
+                                       // unsafe.Pointer is treated like a regular pointer
+                                       if t.kind == UnsafePointer {
+                                               check.errorf(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be unsafe.Pointer")
+                                       }
+                               case *Pointer:
+                                       check.errorf(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer")
+                               case *Interface:
+                                       if isPtr {
+                                               check.errorf(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer to an interface")
+                                       }
                                }
-                       }
-                       add(name, true, pos)
+                       })
                }
        }
 
@@ -759,6 +1161,46 @@ func embeddedFieldIdent(e ast.Expr) *ast.Ident {
                }
        case *ast.SelectorExpr:
                return e.Sel
+       case *ast.IndexExpr:
+               return embeddedFieldIdent(e.X)
        }
        return nil // invalid embedded field
 }
+
+func (check *Checker) collectTypeConstraints(pos token.Pos, types []ast.Expr) []Type {
+       list := make([]Type, 0, len(types)) // assume all types are correct
+       for _, texpr := range types {
+               if texpr == nil {
+                       check.invalidAST(atPos(pos), "missing type constraint")
+                       continue
+               }
+               list = append(list, check.varType(texpr))
+       }
+
+       // Ensure that each type is only present once in the type list.  Types may be
+       // interfaces, which may not be complete yet. It's ok to do this check at the
+       // end because it's not a requirement for correctness of the code.
+       // Note: This is a quadratic algorithm, but type lists tend to be short.
+       check.later(func() {
+               for i, t := range list {
+                       if t := asInterface(t); t != nil {
+                               check.completeInterface(types[i].Pos(), t)
+                       }
+                       if includes(list[:i], t) {
+                               check.softErrorf(types[i], _Todo, "duplicate type %s in type list", t)
+                       }
+               }
+       })
+
+       return list
+}
+
+// includes reports whether typ is in list.
+func includes(list []Type, typ Type) bool {
+       for _, e := range list {
+               if Identical(typ, e) {
+                       return true
+               }
+       }
+       return false
+}
diff --git a/libgo/go/go/types/unify.go b/libgo/go/go/types/unify.go
new file mode 100644 (file)
index 0000000..db06e21
--- /dev/null
@@ -0,0 +1,469 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements type unification.
+
+package types
+
+import (
+       "bytes"
+       "go/token"
+       "sort"
+)
+
+// The unifier maintains two separate sets of type parameters x and y
+// which are used to resolve type parameters in the x and y arguments
+// provided to the unify call. For unidirectional unification, only
+// one of these sets (say x) is provided, and then type parameters are
+// only resolved for the x argument passed to unify, not the y argument
+// (even if that also contains possibly the same type parameters). This
+// is crucial to infer the type parameters of self-recursive calls:
+//
+//     func f[P any](a P) { f(a) }
+//
+// For the call f(a) we want to infer that the type argument for P is P.
+// During unification, the parameter type P must be resolved to the type
+// parameter P ("x" side), but the argument type P must be left alone so
+// that unification resolves the type parameter P to P.
+//
+// For bidirection unification, both sets are provided. This enables
+// unification to go from argument to parameter type and vice versa.
+// For constraint type inference, we use bidirectional unification
+// where both the x and y type parameters are identical. This is done
+// by setting up one of them (using init) and then assigning its value
+// to the other.
+
+// A unifier maintains the current type parameters for x and y
+// and the respective types inferred for each type parameter.
+// A unifier is created by calling newUnifier.
+type unifier struct {
+       check *Checker
+       exact bool
+       x, y  tparamsList // x and y must initialized via tparamsList.init
+       types []Type      // inferred types, shared by x and y
+}
+
+// newUnifier returns a new unifier.
+// If exact is set, unification requires unified types to match
+// exactly. If exact is not set, a named type's underlying type
+// is considered if unification would fail otherwise, and the
+// direction of channels is ignored.
+func newUnifier(check *Checker, exact bool) *unifier {
+       u := &unifier{check: check, exact: exact}
+       u.x.unifier = u
+       u.y.unifier = u
+       return u
+}
+
+// unify attempts to unify x and y and reports whether it succeeded.
+func (u *unifier) unify(x, y Type) bool {
+       return u.nify(x, y, nil)
+}
+
+// A tparamsList describes a list of type parameters and the types inferred for them.
+type tparamsList struct {
+       unifier *unifier
+       tparams []*TypeName
+       // For each tparams element, there is a corresponding type slot index in indices.
+       // index  < 0: unifier.types[-index-1] == nil
+       // index == 0: no type slot allocated yet
+       // index  > 0: unifier.types[index-1] == typ
+       // Joined tparams elements share the same type slot and thus have the same index.
+       // By using a negative index for nil types we don't need to check unifier.types
+       // to see if we have a type or not.
+       indices []int // len(d.indices) == len(d.tparams)
+}
+
+// String returns a string representation for a tparamsList. For debugging.
+func (d *tparamsList) String() string {
+       var buf bytes.Buffer
+       buf.WriteByte('[')
+       for i, tname := range d.tparams {
+               if i > 0 {
+                       buf.WriteString(", ")
+               }
+               writeType(&buf, tname.typ, nil, nil)
+               buf.WriteString(": ")
+               writeType(&buf, d.at(i), nil, nil)
+       }
+       buf.WriteByte(']')
+       return buf.String()
+}
+
+// init initializes d with the given type parameters.
+// The type parameters must be in the order in which they appear in their declaration
+// (this ensures that the tparams indices match the respective type parameter index).
+func (d *tparamsList) init(tparams []*TypeName) {
+       if len(tparams) == 0 {
+               return
+       }
+       if debug {
+               for i, tpar := range tparams {
+                       assert(i == tpar.typ.(*_TypeParam).index)
+               }
+       }
+       d.tparams = tparams
+       d.indices = make([]int, len(tparams))
+}
+
+// join unifies the i'th type parameter of x with the j'th type parameter of y.
+// If both type parameters already have a type associated with them and they are
+// not joined, join fails and return false.
+func (u *unifier) join(i, j int) bool {
+       ti := u.x.indices[i]
+       tj := u.y.indices[j]
+       switch {
+       case ti == 0 && tj == 0:
+               // Neither type parameter has a type slot associated with them.
+               // Allocate a new joined nil type slot (negative index).
+               u.types = append(u.types, nil)
+               u.x.indices[i] = -len(u.types)
+               u.y.indices[j] = -len(u.types)
+       case ti == 0:
+               // The type parameter for x has no type slot yet. Use slot of y.
+               u.x.indices[i] = tj
+       case tj == 0:
+               // The type parameter for y has no type slot yet. Use slot of x.
+               u.y.indices[j] = ti
+
+       // Both type parameters have a slot: ti != 0 && tj != 0.
+       case ti == tj:
+               // Both type parameters already share the same slot. Nothing to do.
+               break
+       case ti > 0 && tj > 0:
+               // Both type parameters have (possibly different) inferred types. Cannot join.
+               return false
+       case ti > 0:
+               // Only the type parameter for x has an inferred type. Use x slot for y.
+               u.y.setIndex(j, ti)
+       default:
+               // Either the type parameter for y has an inferred type, or neither type
+               // parameter has an inferred type. In either case, use y slot for x.
+               u.x.setIndex(i, tj)
+       }
+       return true
+}
+
+// If typ is a type parameter of d, index returns the type parameter index.
+// Otherwise, the result is < 0.
+func (d *tparamsList) index(typ Type) int {
+       if t, ok := typ.(*_TypeParam); ok {
+               if i := t.index; i < len(d.tparams) && d.tparams[i].typ == t {
+                       return i
+               }
+       }
+       return -1
+}
+
+// setIndex sets the type slot index for the i'th type parameter
+// (and all its joined parameters) to tj. The type parameter
+// must have a (possibly nil) type slot associated with it.
+func (d *tparamsList) setIndex(i, tj int) {
+       ti := d.indices[i]
+       assert(ti != 0 && tj != 0)
+       for k, tk := range d.indices {
+               if tk == ti {
+                       d.indices[k] = tj
+               }
+       }
+}
+
+// at returns the type set for the i'th type parameter; or nil.
+func (d *tparamsList) at(i int) Type {
+       if ti := d.indices[i]; ti > 0 {
+               return d.unifier.types[ti-1]
+       }
+       return nil
+}
+
+// set sets the type typ for the i'th type parameter;
+// typ must not be nil and it must not have been set before.
+func (d *tparamsList) set(i int, typ Type) {
+       assert(typ != nil)
+       u := d.unifier
+       switch ti := d.indices[i]; {
+       case ti < 0:
+               u.types[-ti-1] = typ
+               d.setIndex(i, -ti)
+       case ti == 0:
+               u.types = append(u.types, typ)
+               d.indices[i] = len(u.types)
+       default:
+               panic("type already set")
+       }
+}
+
+// types returns the list of inferred types (via unification) for the type parameters
+// described by d, and an index. If all types were inferred, the returned index is < 0.
+// Otherwise, it is the index of the first type parameter which couldn't be inferred;
+// i.e., for which list[index] is nil.
+func (d *tparamsList) types() (list []Type, index int) {
+       list = make([]Type, len(d.tparams))
+       index = -1
+       for i := range d.tparams {
+               t := d.at(i)
+               list[i] = t
+               if index < 0 && t == nil {
+                       index = i
+               }
+       }
+       return
+}
+
+func (u *unifier) nifyEq(x, y Type, p *ifacePair) bool {
+       return x == y || u.nify(x, y, p)
+}
+
+// nify implements the core unification algorithm which is an
+// adapted version of Checker.identical0. For changes to that
+// code the corresponding changes should be made here.
+// Must not be called directly from outside the unifier.
+func (u *unifier) nify(x, y Type, p *ifacePair) bool {
+       // types must be expanded for comparison
+       x = expand(x)
+       y = expand(y)
+
+       if !u.exact {
+               // If exact unification is known to fail because we attempt to
+               // match a type name against an unnamed type literal, consider
+               // the underlying type of the named type.
+               // (Subtle: We use isNamed to include any type with a name (incl.
+               // basic types and type parameters. We use asNamed() because we only
+               // want *Named types.)
+               switch {
+               case !isNamed(x) && y != nil && asNamed(y) != nil:
+                       return u.nify(x, under(y), p)
+               case x != nil && asNamed(x) != nil && !isNamed(y):
+                       return u.nify(under(x), y, p)
+               }
+       }
+
+       // Cases where at least one of x or y is a type parameter.
+       switch i, j := u.x.index(x), u.y.index(y); {
+       case i >= 0 && j >= 0:
+               // both x and y are type parameters
+               if u.join(i, j) {
+                       return true
+               }
+               // both x and y have an inferred type - they must match
+               return u.nifyEq(u.x.at(i), u.y.at(j), p)
+
+       case i >= 0:
+               // x is a type parameter, y is not
+               if tx := u.x.at(i); tx != nil {
+                       return u.nifyEq(tx, y, p)
+               }
+               // otherwise, infer type from y
+               u.x.set(i, y)
+               return true
+
+       case j >= 0:
+               // y is a type parameter, x is not
+               if ty := u.y.at(j); ty != nil {
+                       return u.nifyEq(x, ty, p)
+               }
+               // otherwise, infer type from x
+               u.y.set(j, x)
+               return true
+       }
+
+       // For type unification, do not shortcut (x == y) for identical
+       // types. Instead keep comparing them element-wise to unify the
+       // matching (and equal type parameter types). A simple test case
+       // where this matters is: func f[P any](a P) { f(a) } .
+
+       switch x := x.(type) {
+       case *Basic:
+               // Basic types are singletons except for the rune and byte
+               // aliases, thus we cannot solely rely on the x == y check
+               // above. See also comment in TypeName.IsAlias.
+               if y, ok := y.(*Basic); ok {
+                       return x.kind == y.kind
+               }
+
+       case *Array:
+               // Two array types are identical if they have identical element types
+               // and the same array length.
+               if y, ok := y.(*Array); ok {
+                       // If one or both array lengths are unknown (< 0) due to some error,
+                       // assume they are the same to avoid spurious follow-on errors.
+                       return (x.len < 0 || y.len < 0 || x.len == y.len) && u.nify(x.elem, y.elem, p)
+               }
+
+       case *Slice:
+               // Two slice types are identical if they have identical element types.
+               if y, ok := y.(*Slice); ok {
+                       return u.nify(x.elem, y.elem, p)
+               }
+
+       case *Struct:
+               // Two struct types are identical if they have the same sequence of fields,
+               // and if corresponding fields have the same names, and identical types,
+               // and identical tags. Two embedded fields are considered to have the same
+               // name. Lower-case field names from different packages are always different.
+               if y, ok := y.(*Struct); ok {
+                       if x.NumFields() == y.NumFields() {
+                               for i, f := range x.fields {
+                                       g := y.fields[i]
+                                       if f.embedded != g.embedded ||
+                                               x.Tag(i) != y.Tag(i) ||
+                                               !f.sameId(g.pkg, g.name) ||
+                                               !u.nify(f.typ, g.typ, p) {
+                                               return false
+                                       }
+                               }
+                               return true
+                       }
+               }
+
+       case *Pointer:
+               // Two pointer types are identical if they have identical base types.
+               if y, ok := y.(*Pointer); ok {
+                       return u.nify(x.base, y.base, p)
+               }
+
+       case *Tuple:
+               // Two tuples types are identical if they have the same number of elements
+               // and corresponding elements have identical types.
+               if y, ok := y.(*Tuple); ok {
+                       if x.Len() == y.Len() {
+                               if x != nil {
+                                       for i, v := range x.vars {
+                                               w := y.vars[i]
+                                               if !u.nify(v.typ, w.typ, p) {
+                                                       return false
+                                               }
+                                       }
+                               }
+                               return true
+                       }
+               }
+
+       case *Signature:
+               // Two function types are identical if they have the same number of parameters
+               // and result values, corresponding parameter and result types are identical,
+               // and either both functions are variadic or neither is. Parameter and result
+               // names are not required to match.
+               // TODO(gri) handle type parameters or document why we can ignore them.
+               if y, ok := y.(*Signature); ok {
+                       return x.variadic == y.variadic &&
+                               u.nify(x.params, y.params, p) &&
+                               u.nify(x.results, y.results, p)
+               }
+
+       case *_Sum:
+               // This should not happen with the current internal use of sum types.
+               panic("type inference across sum types not implemented")
+
+       case *Interface:
+               // Two interface types are identical if they have the same set of methods with
+               // the same names and identical function types. Lower-case method names from
+               // different packages are always different. The order of the methods is irrelevant.
+               if y, ok := y.(*Interface); ok {
+                       // If identical0 is called (indirectly) via an external API entry point
+                       // (such as Identical, IdenticalIgnoreTags, etc.), check is nil. But in
+                       // that case, interfaces are expected to be complete and lazy completion
+                       // here is not needed.
+                       if u.check != nil {
+                               u.check.completeInterface(token.NoPos, x)
+                               u.check.completeInterface(token.NoPos, y)
+                       }
+                       a := x.allMethods
+                       b := y.allMethods
+                       if len(a) == len(b) {
+                               // Interface types are the only types where cycles can occur
+                               // that are not "terminated" via named types; and such cycles
+                               // can only be created via method parameter types that are
+                               // anonymous interfaces (directly or indirectly) embedding
+                               // the current interface. Example:
+                               //
+                               //    type T interface {
+                               //        m() interface{T}
+                               //    }
+                               //
+                               // If two such (differently named) interfaces are compared,
+                               // endless recursion occurs if the cycle is not detected.
+                               //
+                               // If x and y were compared before, they must be equal
+                               // (if they were not, the recursion would have stopped);
+                               // search the ifacePair stack for the same pair.
+                               //
+                               // This is a quadratic algorithm, but in practice these stacks
+                               // are extremely short (bounded by the nesting depth of interface
+                               // type declarations that recur via parameter types, an extremely
+                               // rare occurrence). An alternative implementation might use a
+                               // "visited" map, but that is probably less efficient overall.
+                               q := &ifacePair{x, y, p}
+                               for p != nil {
+                                       if p.identical(q) {
+                                               return true // same pair was compared before
+                                       }
+                                       p = p.prev
+                               }
+                               if debug {
+                                       assert(sort.IsSorted(byUniqueMethodName(a)))
+                                       assert(sort.IsSorted(byUniqueMethodName(b)))
+                               }
+                               for i, f := range a {
+                                       g := b[i]
+                                       if f.Id() != g.Id() || !u.nify(f.typ, g.typ, q) {
+                                               return false
+                                       }
+                               }
+                               return true
+                       }
+               }
+
+       case *Map:
+               // Two map types are identical if they have identical key and value types.
+               if y, ok := y.(*Map); ok {
+                       return u.nify(x.key, y.key, p) && u.nify(x.elem, y.elem, p)
+               }
+
+       case *Chan:
+               // Two channel types are identical if they have identical value types.
+               if y, ok := y.(*Chan); ok {
+                       return (!u.exact || x.dir == y.dir) && u.nify(x.elem, y.elem, p)
+               }
+
+       case *Named:
+               // Two named types are identical if their type names originate
+               // in the same type declaration.
+               // if y, ok := y.(*Named); ok {
+               //      return x.obj == y.obj
+               // }
+               if y, ok := y.(*Named); ok {
+                       // TODO(gri) This is not always correct: two types may have the same names
+                       //           in the same package if one of them is nested in a function.
+                       //           Extremely unlikely but we need an always correct solution.
+                       if x.obj.pkg == y.obj.pkg && x.obj.name == y.obj.name {
+                               assert(len(x.targs) == len(y.targs))
+                               for i, x := range x.targs {
+                                       if !u.nify(x, y.targs[i], p) {
+                                               return false
+                                       }
+                               }
+                               return true
+                       }
+               }
+
+       case *_TypeParam:
+               // Two type parameters (which are not part of the type parameters of the
+               // enclosing type as those are handled in the beginning of this function)
+               // are identical if they originate in the same declaration.
+               return x == y
+
+       // case *instance:
+       //      unreachable since types are expanded
+
+       case nil:
+               // avoid a crash in case of nil type
+
+       default:
+               u.check.dump("### u.nify(%s, %s), u.x.tparams = %s", x, y, u.x.tparams)
+               unreachable()
+       }
+
+       return false
+}
index ff5b89118ad9ef940ae1fbe1e00276190e6f0476..d7feb2c609efa93829bc90bd9176d1d9a423bf94 100644 (file)
@@ -8,6 +8,7 @@ package types
 
 import (
        "go/constant"
+       "go/internal/typeparams"
        "go/token"
        "strings"
 )
@@ -24,6 +25,7 @@ var (
        universeIota  *Const
        universeByte  *Basic // uint8 alias, but has name "byte"
        universeRune  *Basic // int32 alias, but has name "rune"
+       universeAny   *Interface
        universeError *Named
 )
 
@@ -77,13 +79,21 @@ func defPredeclaredTypes() {
                def(NewTypeName(token.NoPos, nil, t.name, t))
        }
 
+       // any
+       // (Predeclared and entered into universe scope so we do all the
+       // usual checks; but removed again from scope later since it's
+       // only visible as constraint in a type parameter list.)
+       def(NewTypeName(token.NoPos, nil, "any", &emptyInterface))
+
        // Error has a nil package in its qualified name since it is in no package
-       res := NewVar(token.NoPos, nil, "", Typ[String])
-       sig := &Signature{results: NewTuple(res)}
-       err := NewFunc(token.NoPos, nil, "Error", sig)
-       typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil).Complete()}
-       sig.recv = NewVar(token.NoPos, nil, "", typ)
-       def(NewTypeName(token.NoPos, nil, "error", typ))
+       {
+               res := NewVar(token.NoPos, nil, "", Typ[String])
+               sig := &Signature{results: NewTuple(res)}
+               err := NewFunc(token.NoPos, nil, "Error", sig)
+               typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil).Complete()}
+               sig.recv = NewVar(token.NoPos, nil, "", typ)
+               def(NewTypeName(token.NoPos, nil, "error", typ))
+       }
 }
 
 var predeclaredConsts = [...]struct {
@@ -128,9 +138,11 @@ const (
        _Recover
 
        // package unsafe
+       _Add
        _Alignof
        _Offsetof
        _Sizeof
+       _Slice
 
        // testing support
        _Assert
@@ -159,9 +171,11 @@ var predeclaredFuncs = [...]struct {
        _Real:    {"real", 1, false, expression},
        _Recover: {"recover", 0, false, statement},
 
+       _Add:      {"Add", 2, false, expression},
        _Alignof:  {"Alignof", 1, false, expression},
        _Offsetof: {"Offsetof", 1, false, expression},
        _Sizeof:   {"Sizeof", 1, false, expression},
+       _Slice:    {"Slice", 2, false, expression},
 
        _Assert: {"assert", 1, false, statement},
        _Trace:  {"trace", 0, true, statement},
@@ -188,6 +202,33 @@ func DefPredeclaredTestFuncs() {
        def(newBuiltin(_Trace))
 }
 
+func defPredeclaredComparable() {
+       // The "comparable" interface can be imagined as defined like
+       //
+       // type comparable interface {
+       //         == () untyped bool
+       //         != () untyped bool
+       // }
+       //
+       // == and != cannot be user-declared but we can declare
+       // a magic method == and check for its presence when needed.
+
+       // Define interface { == () }. We don't care about the signature
+       // for == so leave it empty except for the receiver, which is
+       // set up later to match the usual interface method assumptions.
+       sig := new(Signature)
+       eql := NewFunc(token.NoPos, nil, "==", sig)
+       iface := NewInterfaceType([]*Func{eql}, nil).Complete()
+
+       // set up the defined type for the interface
+       obj := NewTypeName(token.NoPos, nil, "comparable", nil)
+       named := NewNamed(obj, iface, nil)
+       obj.color_ = black
+       sig.recv = NewVar(token.NoPos, nil, "", named) // complete == signature
+
+       def(obj)
+}
+
 func init() {
        Universe = NewScope(nil, token.NoPos, token.NoPos, "universe")
        Unsafe = NewPackage("unsafe", "unsafe")
@@ -197,11 +238,18 @@ func init() {
        defPredeclaredConsts()
        defPredeclaredNil()
        defPredeclaredFuncs()
+       if typeparams.Enabled {
+               defPredeclaredComparable()
+       }
 
        universeIota = Universe.Lookup("iota").(*Const)
        universeByte = Universe.Lookup("byte").(*TypeName).typ.(*Basic)
        universeRune = Universe.Lookup("rune").(*TypeName).typ.(*Basic)
+       universeAny = Universe.Lookup("any").(*TypeName).typ.(*Interface)
        universeError = Universe.Lookup("error").(*TypeName).typ.(*Named)
+
+       // "any" is only visible as constraint in a type parameter list
+       delete(Universe.elems, "any")
 }
 
 // Objects with names containing blanks are internal and not entered into
@@ -215,7 +263,7 @@ func def(obj Object) {
                return // nothing to do
        }
        // fix Obj link for named types
-       if typ, ok := obj.Type().(*Named); ok {
+       if typ := asNamed(obj.Type()); typ != nil {
                typ.obj = obj.(*TypeName)
        }
        // exported identifiers go into package unsafe
diff --git a/libgo/go/go/types/version.go b/libgo/go/go/types/version.go
new file mode 100644 (file)
index 0000000..1546941
--- /dev/null
@@ -0,0 +1,82 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types
+
+import (
+       "fmt"
+       "go/ast"
+       "go/token"
+       "regexp"
+       "strconv"
+       "strings"
+)
+
+// langCompat reports an error if the representation of a numeric
+// literal is not compatible with the current language version.
+func (check *Checker) langCompat(lit *ast.BasicLit) {
+       s := lit.Value
+       if len(s) <= 2 || check.allowVersion(check.pkg, 1, 13) {
+               return
+       }
+       // len(s) > 2
+       if strings.Contains(s, "_") {
+               check.errorf(lit, _InvalidLit, "underscores in numeric literals requires go1.13 or later")
+               return
+       }
+       if s[0] != '0' {
+               return
+       }
+       radix := s[1]
+       if radix == 'b' || radix == 'B' {
+               check.errorf(lit, _InvalidLit, "binary literals requires go1.13 or later")
+               return
+       }
+       if radix == 'o' || radix == 'O' {
+               check.errorf(lit, _InvalidLit, "0o/0O-style octal literals requires go1.13 or later")
+               return
+       }
+       if lit.Kind != token.INT && (radix == 'x' || radix == 'X') {
+               check.errorf(lit, _InvalidLit, "hexadecimal floating-point literals requires go1.13 or later")
+       }
+}
+
+// allowVersion reports whether the given package
+// is allowed to use version major.minor.
+func (check *Checker) allowVersion(pkg *Package, major, minor int) bool {
+       // We assume that imported packages have all been checked,
+       // so we only have to check for the local package.
+       if pkg != check.pkg {
+               return true
+       }
+       ma, mi := check.version.major, check.version.minor
+       return ma == 0 && mi == 0 || ma > major || ma == major && mi >= minor
+}
+
+type version struct {
+       major, minor int
+}
+
+// parseGoVersion parses a Go version string (such as "go1.12")
+// and returns the version, or an error. If s is the empty
+// string, the version is 0.0.
+func parseGoVersion(s string) (v version, err error) {
+       if s == "" {
+               return
+       }
+       matches := goVersionRx.FindStringSubmatch(s)
+       if matches == nil {
+               err = fmt.Errorf(`should be something like "go1.12"`)
+               return
+       }
+       v.major, err = strconv.Atoi(matches[1])
+       if err != nil {
+               return
+       }
+       v.minor, err = strconv.Atoi(matches[2])
+       return
+}
+
+// goVersionRx matches a Go version string, e.g. "go1.12".
+var goVersionRx = regexp.MustCompile(`^go([1-9][0-9]*)\.(0|[1-9][0-9]*)$`)
index b799e440b4a177e0644f5c372dd792140bd5cf99..94c71ac1ac863f7b7ae209a65bc273b095d50d9a 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build go1.11,!gccgo,!purego
+//go:build go1.11 && gc && !purego
+// +build go1.11,gc,!purego
 
 package chacha20
 
index 4635307b8f2990f82e67cfd4e665240948751d39..025b49897e32b21abc89d4d1533e1ade5e847194 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !arm64,!s390x,!ppc64le arm64,!go1.11 gccgo purego
+//go:build (!arm64 && !s390x && !ppc64le) || (arm64 && !go1.11) || !gc || purego
+// +build !arm64,!s390x,!ppc64le arm64,!go1.11 !gc purego
 
 package chacha20
 
index b7993303415662890c373e62a6fbd1ec411de043..da420b2e97b03c13318b66fc62eb45b418739579 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !gccgo,!purego
+//go:build gc && !purego
+// +build gc,!purego
 
 package chacha20
 
index a9244bdf4dbfd23dc6a3842a3100bc5d897a1d70..c5898db46584531f1b29d5338055e1c4c01e7fc7 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !gccgo,!purego
+//go:build gc && !purego
+// +build gc,!purego
 
 package chacha20
 
index cda77819b84a1ecf9b9bf5210f3fb01168ace767..25959b9a6efadab04e8909ab4462da7084ad1fab 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !gccgo,!purego
+//go:build gc && !purego
+// +build gc,!purego
 
 package chacha20poly1305
 
index 9ce4aa9fe65f51b0bfe85d187db2dd80315937b7..f832b33d45f208983ff50c1e6ef74a46935245e0 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !amd64 gccgo purego
+//go:build !amd64 || !gc || purego
+// +build !amd64 !gc purego
 
 package chacha20poly1305
 
index d3596ee66fdb2996eecaf0ada786b2a5a5ef3d08..83c776de083024663abe92276e7ffaa4ef7027b1 100644 (file)
@@ -117,6 +117,19 @@ func (b *Builder) AddASN1GeneralizedTime(t time.Time) {
        })
 }
 
+// AddASN1UTCTime appends a DER-encoded ASN.1 UTCTime.
+func (b *Builder) AddASN1UTCTime(t time.Time) {
+       b.AddASN1(asn1.UTCTime, func(c *Builder) {
+               // As utilized by the X.509 profile, UTCTime can only
+               // represent the years 1950 through 2049.
+               if t.Year() < 1950 || t.Year() >= 2050 {
+                       b.err = fmt.Errorf("cryptobyte: cannot represent %v as a UTCTime", t)
+                       return
+               }
+               c.AddBytes([]byte(t.Format(defaultUTCTimeFormatStr)))
+       })
+}
+
 // AddASN1BitString appends a DER-encoded ASN.1 BIT STRING. This does not
 // support BIT STRINGs that are not a whole number of bytes.
 func (b *Builder) AddASN1BitString(data []byte) {
@@ -466,6 +479,45 @@ func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool {
        return true
 }
 
+const defaultUTCTimeFormatStr = "060102150405Z0700"
+
+// ReadASN1UTCTime decodes an ASN.1 UTCTime into out and advances.
+// It reports whether the read was successful.
+func (s *String) ReadASN1UTCTime(out *time.Time) bool {
+       var bytes String
+       if !s.ReadASN1(&bytes, asn1.UTCTime) {
+               return false
+       }
+       t := string(bytes)
+
+       formatStr := defaultUTCTimeFormatStr
+       var err error
+       res, err := time.Parse(formatStr, t)
+       if err != nil {
+               // Fallback to minute precision if we can't parse second
+               // precision. If we are following X.509 or X.690 we shouldn't
+               // support this, but we do.
+               formatStr = "0601021504Z0700"
+               res, err = time.Parse(formatStr, t)
+       }
+       if err != nil {
+               return false
+       }
+
+       if serialized := res.Format(formatStr); serialized != t {
+               return false
+       }
+
+       if res.Year() >= 2050 {
+               // UTCTime interprets the low order digits 50-99 as 1950-99.
+               // This only applies to its use in the X.509 profile.
+               // See https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1
+               res = res.AddDate(-100, 0, 0)
+       }
+       *out = res
+       return true
+}
+
 // ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances.
 // It reports whether the read was successful.
 func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool {
index 5120b779b9b48ba3f1eba27d43091f62b4424cd2..84858480dff5fbd4c4f36503f5813146e68accf9 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build amd64,!gccgo,!appengine,!purego
+//go:build amd64 && gc && !purego
+// +build amd64,gc,!purego
 
 package curve25519
 
index 047d49afc27e3e05e8dad2557a07cf82d097b9bc..259728af7dad7bae4f74062ae2b1aa13c5c6f8ae 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !amd64 gccgo appengine purego
+//go:build !amd64 || !gc || purego
+// +build !amd64 !gc purego
 
 package curve25519
 
index f38797bfa1bfb1487f01489efa6911d3e1662515..4fad24f8dcde8189a34f7611bd81df0ef35d7004 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !appengine
+//go:build !purego
+// +build !purego
 
 // Package subtle implements functions that are often useful in cryptographic
 // code but require careful thought to use correctly.
diff --git a/libgo/go/golang.org/x/crypto/internal/subtle/aliasing_purego.go b/libgo/go/golang.org/x/crypto/internal/subtle/aliasing_purego.go
new file mode 100644 (file)
index 0000000..80ccbed
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build purego
+// +build purego
+
+// Package subtle implements functions that are often useful in cryptographic
+// code but require careful thought to use correctly.
+package subtle // import "golang.org/x/crypto/internal/subtle"
+
+// This is the Google App Engine standard variant based on reflect
+// because the unsafe package and cgo are disallowed.
+
+import "reflect"
+
+// AnyOverlap reports whether x and y share memory at any (not necessarily
+// corresponding) index. The memory beyond the slice length is ignored.
+func AnyOverlap(x, y []byte) bool {
+       return len(x) > 0 && len(y) > 0 &&
+               reflect.ValueOf(&x[0]).Pointer() <= reflect.ValueOf(&y[len(y)-1]).Pointer() &&
+               reflect.ValueOf(&y[0]).Pointer() <= reflect.ValueOf(&x[len(x)-1]).Pointer()
+}
+
+// InexactOverlap reports whether x and y share memory at any non-corresponding
+// index. The memory beyond the slice length is ignored. Note that x and y can
+// have different lengths and still not have any inexact overlap.
+//
+// InexactOverlap can be used to implement the requirements of the crypto/cipher
+// AEAD, Block, BlockMode and Stream interfaces.
+func InexactOverlap(x, y []byte) bool {
+       if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] {
+               return false
+       }
+       return AnyOverlap(x, y)
+}
index 157a69f61bd9a8c4344a944ab4dbbd1857452718..45b5c966b2be38e4e7a05bd9f454625d99d555d2 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !go1.13
 // +build !go1.13
 
 package poly1305
index a0a185f0fc77187616eda36f23d69a94fa0af0f2..ed52b3418ab537859539f0ed6ca1916e01a4ca61 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build go1.13
 // +build go1.13
 
 package poly1305
index d118f30ed56c0ff1017c7c18e5003f7766f7801f..f184b67d98db2903033de12f9f82dbe9ab35577e 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !amd64,!ppc64le,!s390x gccgo purego
+//go:build (!amd64 && !ppc64le && !s390x) || !gc || purego
+// +build !amd64,!ppc64le,!s390x !gc purego
 
 package poly1305
 
index 99e5a1d50efcc7502142be888b6e05cb58c95527..6d522333f29e86155e57ac4db1f6cdc6b77278fd 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !gccgo,!purego
+//go:build gc && !purego
+// +build gc,!purego
 
 package poly1305
 
index 2e7a120b1923ddb07131db975ce1aa8153145264..4a069941a6ef9bdda4ec4758f402f8e4973e13e2 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !gccgo,!purego
+//go:build gc && !purego
+// +build gc,!purego
 
 package poly1305
 
index 958fedc0790b1b7d945a9651bc6c3e7ffaa62a99..62cc9f84709e303c745030b088064d26ba8ed8e3 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !gccgo,!purego
+//go:build gc && !purego
+// +build gc,!purego
 
 package poly1305
 
index 2a961ca81c2588c62fe9680e29f03dc18b7925a5..956f30cbb399a558e2fc99f9ea8c4a113a0e2c2e 100644 (file)
@@ -194,12 +194,15 @@ func (x *FileSyntax) updateLine(line *Line, tokens ...string) {
        line.Token = tokens
 }
 
-func (x *FileSyntax) removeLine(line *Line) {
+// markRemoved modifies line so that it (and its end-of-line comment, if any)
+// will be dropped by (*FileSyntax).Cleanup.
+func (line *Line) markRemoved() {
        line.Token = nil
+       line.Comments.Suffix = nil
 }
 
 // Cleanup cleans up the file syntax x after any edit operations.
-// To avoid quadratic behavior, removeLine marks the line as dead
+// To avoid quadratic behavior, (*Line).markRemoved marks the line as dead
 // by setting line.Token = nil but does not remove it from the slice
 // in which it appears. After edits have all been indicated,
 // calling Cleanup cleans out the dead lines.
index f8c9384985985929e27cda4acba115db0381d64e..78f83fa7144f0318379ebb0c4797540959c7b511 100644 (file)
@@ -47,8 +47,9 @@ type File struct {
 
 // A Module is the module statement.
 type Module struct {
-       Mod    module.Version
-       Syntax *Line
+       Mod        module.Version
+       Deprecated string
+       Syntax     *Line
 }
 
 // A Go is the go statement.
@@ -57,13 +58,6 @@ type Go struct {
        Syntax  *Line
 }
 
-// A Require is a single require statement.
-type Require struct {
-       Mod      module.Version
-       Indirect bool // has "// indirect" comment
-       Syntax   *Line
-}
-
 // An Exclude is a single exclude statement.
 type Exclude struct {
        Mod    module.Version
@@ -92,6 +86,93 @@ type VersionInterval struct {
        Low, High string
 }
 
+// A Require is a single require statement.
+type Require struct {
+       Mod      module.Version
+       Indirect bool // has "// indirect" comment
+       Syntax   *Line
+}
+
+func (r *Require) markRemoved() {
+       r.Syntax.markRemoved()
+       *r = Require{}
+}
+
+func (r *Require) setVersion(v string) {
+       r.Mod.Version = v
+
+       if line := r.Syntax; len(line.Token) > 0 {
+               if line.InBlock {
+                       // If the line is preceded by an empty line, remove it; see
+                       // https://golang.org/issue/33779.
+                       if len(line.Comments.Before) == 1 && len(line.Comments.Before[0].Token) == 0 {
+                               line.Comments.Before = line.Comments.Before[:0]
+                       }
+                       if len(line.Token) >= 2 { // example.com v1.2.3
+                               line.Token[1] = v
+                       }
+               } else {
+                       if len(line.Token) >= 3 { // require example.com v1.2.3
+                               line.Token[2] = v
+                       }
+               }
+       }
+}
+
+// setIndirect sets line to have (or not have) a "// indirect" comment.
+func (r *Require) setIndirect(indirect bool) {
+       r.Indirect = indirect
+       line := r.Syntax
+       if isIndirect(line) == indirect {
+               return
+       }
+       if indirect {
+               // Adding comment.
+               if len(line.Suffix) == 0 {
+                       // New comment.
+                       line.Suffix = []Comment{{Token: "// indirect", Suffix: true}}
+                       return
+               }
+
+               com := &line.Suffix[0]
+               text := strings.TrimSpace(strings.TrimPrefix(com.Token, string(slashSlash)))
+               if text == "" {
+                       // Empty comment.
+                       com.Token = "// indirect"
+                       return
+               }
+
+               // Insert at beginning of existing comment.
+               com.Token = "// indirect; " + text
+               return
+       }
+
+       // Removing comment.
+       f := strings.TrimSpace(strings.TrimPrefix(line.Suffix[0].Token, string(slashSlash)))
+       if f == "indirect" {
+               // Remove whole comment.
+               line.Suffix = nil
+               return
+       }
+
+       // Remove comment prefix.
+       com := &line.Suffix[0]
+       i := strings.Index(com.Token, "indirect;")
+       com.Token = "//" + com.Token[i+len("indirect;"):]
+}
+
+// isIndirect reports whether line has a "// indirect" comment,
+// meaning it is in go.mod only for its effect on indirect dependencies,
+// so that it can be dropped entirely once the effective version of the
+// indirect dependency reaches the given minimum version.
+func isIndirect(line *Line) bool {
+       if len(line.Suffix) == 0 {
+               return false
+       }
+       f := strings.Fields(strings.TrimPrefix(line.Suffix[0].Token, string(slashSlash)))
+       return (len(f) == 1 && f[0] == "indirect" || len(f) > 1 && f[0] == "indirect;")
+}
+
 func (f *File) AddModuleStmt(path string) error {
        if f.Syntax == nil {
                f.Syntax = new(FileSyntax)
@@ -131,8 +212,15 @@ var dontFixRetract VersionFixer = func(_, vers string) (string, error) {
        return vers, nil
 }
 
-// Parse parses the data, reported in errors as being from file,
-// into a File struct. It applies fix, if non-nil, to canonicalize all module versions found.
+// Parse parses and returns a go.mod file.
+//
+// file is the name of the file, used in positions and errors.
+//
+// data is the content of the file.
+//
+// fix is an optional function that canonicalizes module versions.
+// If fix is nil, all module versions must be canonical (module.CanonicalVersion
+// must return the same string).
 func Parse(file string, data []byte, fix VersionFixer) (*File, error) {
        return parseToFile(file, data, fix, true)
 }
@@ -209,6 +297,7 @@ func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (parse
 }
 
 var GoVersionRE = lazyregexp.New(`^([1-9][0-9]*)\.(0|[1-9][0-9]*)$`)
+var laxGoVersionRE = lazyregexp.New(`^v?(([1-9][0-9]*)\.(0|[1-9][0-9]*))([^0-9].*)$`)
 
 func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, args []string, fix VersionFixer, strict bool) {
        // If strict is false, this module is a dependency.
@@ -259,8 +348,17 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a
                        errorf("go directive expects exactly one argument")
                        return
                } else if !GoVersionRE.MatchString(args[0]) {
-                       errorf("invalid go version '%s': must match format 1.23", args[0])
-                       return
+                       fixed := false
+                       if !strict {
+                               if m := laxGoVersionRE.FindStringSubmatch(args[0]); m != nil {
+                                       args[0] = m[1]
+                                       fixed = true
+                               }
+                       }
+                       if !fixed {
+                               errorf("invalid go version '%s': must match format 1.23", args[0])
+                               return
+                       }
                }
 
                f.Go = &Go{Syntax: line}
@@ -271,7 +369,11 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a
                        errorf("repeated module statement")
                        return
                }
-               f.Module = &Module{Syntax: line}
+               deprecated := parseDeprecation(block, line)
+               f.Module = &Module{
+                       Syntax:     line,
+                       Deprecated: deprecated,
+               }
                if len(args) != 1 {
                        errorf("usage: module module/path")
                        return
@@ -385,7 +487,7 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a
                })
 
        case "retract":
-               rationale := parseRetractRationale(block, line)
+               rationale := parseDirectiveComment(block, line)
                vi, err := parseVersionInterval(verb, "", &args, dontFixRetract)
                if err != nil {
                        if strict {
@@ -454,58 +556,6 @@ func (f *File) fixRetract(fix VersionFixer, errs *ErrorList) {
        }
 }
 
-// isIndirect reports whether line has a "// indirect" comment,
-// meaning it is in go.mod only for its effect on indirect dependencies,
-// so that it can be dropped entirely once the effective version of the
-// indirect dependency reaches the given minimum version.
-func isIndirect(line *Line) bool {
-       if len(line.Suffix) == 0 {
-               return false
-       }
-       f := strings.Fields(strings.TrimPrefix(line.Suffix[0].Token, string(slashSlash)))
-       return (len(f) == 1 && f[0] == "indirect" || len(f) > 1 && f[0] == "indirect;")
-}
-
-// setIndirect sets line to have (or not have) a "// indirect" comment.
-func setIndirect(line *Line, indirect bool) {
-       if isIndirect(line) == indirect {
-               return
-       }
-       if indirect {
-               // Adding comment.
-               if len(line.Suffix) == 0 {
-                       // New comment.
-                       line.Suffix = []Comment{{Token: "// indirect", Suffix: true}}
-                       return
-               }
-
-               com := &line.Suffix[0]
-               text := strings.TrimSpace(strings.TrimPrefix(com.Token, string(slashSlash)))
-               if text == "" {
-                       // Empty comment.
-                       com.Token = "// indirect"
-                       return
-               }
-
-               // Insert at beginning of existing comment.
-               com.Token = "// indirect; " + text
-               return
-       }
-
-       // Removing comment.
-       f := strings.Fields(line.Suffix[0].Token)
-       if len(f) == 2 {
-               // Remove whole comment.
-               line.Suffix = nil
-               return
-       }
-
-       // Remove comment prefix.
-       com := &line.Suffix[0]
-       i := strings.Index(com.Token, "indirect;")
-       com.Token = "//" + com.Token[i+len("indirect;"):]
-}
-
 // IsDirectoryPath reports whether the given path should be interpreted
 // as a directory path. Just like on the go command line, relative paths
 // and rooted paths are directory paths; the rest are module paths.
@@ -612,10 +662,29 @@ func parseString(s *string) (string, error) {
        return t, nil
 }
 
-// parseRetractRationale extracts the rationale for a retract directive from the
-// surrounding comments. If the line does not have comments and is part of a
-// block that does have comments, the block's comments are used.
-func parseRetractRationale(block *LineBlock, line *Line) string {
+var deprecatedRE = lazyregexp.New(`(?s)(?:^|\n\n)Deprecated: *(.*?)(?:$|\n\n)`)
+
+// parseDeprecation extracts the text of comments on a "module" directive and
+// extracts a deprecation message from that.
+//
+// A deprecation message is contained in a paragraph within a block of comments
+// that starts with "Deprecated:" (case sensitive). The message runs until the
+// end of the paragraph and does not include the "Deprecated:" prefix. If the
+// comment block has multiple paragraphs that start with "Deprecated:",
+// parseDeprecation returns the message from the first.
+func parseDeprecation(block *LineBlock, line *Line) string {
+       text := parseDirectiveComment(block, line)
+       m := deprecatedRE.FindStringSubmatch(text)
+       if m == nil {
+               return ""
+       }
+       return m[1]
+}
+
+// parseDirectiveComment extracts the text of comments on a directive.
+// If the directive's line does not have comments and is part of a block that
+// does have comments, the block's comments are used.
+func parseDirectiveComment(block *LineBlock, line *Line) string {
        comments := line.Comment()
        if block != nil && len(comments.Before) == 0 && len(comments.Suffix) == 0 {
                comments = block.Comment()
@@ -794,6 +863,12 @@ func (f *File) AddGoStmt(version string) error {
        return nil
 }
 
+// AddRequire sets the first require line for path to version vers,
+// preserving any existing comments for that line and removing all
+// other lines for path.
+//
+// If no line currently exists for path, AddRequire adds a new line
+// at the end of the last require block.
 func (f *File) AddRequire(path, vers string) error {
        need := true
        for _, r := range f.Require {
@@ -803,7 +878,7 @@ func (f *File) AddRequire(path, vers string) error {
                                f.Syntax.updateLine(r.Syntax, "require", AutoQuote(path), vers)
                                need = false
                        } else {
-                               f.Syntax.removeLine(r.Syntax)
+                               r.Syntax.markRemoved()
                                *r = Require{}
                        }
                }
@@ -815,69 +890,235 @@ func (f *File) AddRequire(path, vers string) error {
        return nil
 }
 
+// AddNewRequire adds a new require line for path at version vers at the end of
+// the last require block, regardless of any existing require lines for path.
 func (f *File) AddNewRequire(path, vers string, indirect bool) {
        line := f.Syntax.addLine(nil, "require", AutoQuote(path), vers)
-       setIndirect(line, indirect)
-       f.Require = append(f.Require, &Require{module.Version{Path: path, Version: vers}, indirect, line})
+       r := &Require{
+               Mod:    module.Version{Path: path, Version: vers},
+               Syntax: line,
+       }
+       r.setIndirect(indirect)
+       f.Require = append(f.Require, r)
 }
 
+// SetRequire updates the requirements of f to contain exactly req, preserving
+// the existing block structure and line comment contents (except for 'indirect'
+// markings) for the first requirement on each named module path.
+//
+// The Syntax field is ignored for the requirements in req.
+//
+// Any requirements not already present in the file are added to the block
+// containing the last require line.
+//
+// The requirements in req must specify at most one distinct version for each
+// module path.
+//
+// If any existing requirements may be removed, the caller should call Cleanup
+// after all edits are complete.
 func (f *File) SetRequire(req []*Require) {
-       need := make(map[string]string)
-       indirect := make(map[string]bool)
+       type elem struct {
+               version  string
+               indirect bool
+       }
+       need := make(map[string]elem)
        for _, r := range req {
-               need[r.Mod.Path] = r.Mod.Version
-               indirect[r.Mod.Path] = r.Indirect
+               if prev, dup := need[r.Mod.Path]; dup && prev.version != r.Mod.Version {
+                       panic(fmt.Errorf("SetRequire called with conflicting versions for path %s (%s and %s)", r.Mod.Path, prev.version, r.Mod.Version))
+               }
+               need[r.Mod.Path] = elem{r.Mod.Version, r.Indirect}
        }
 
+       // Update or delete the existing Require entries to preserve
+       // only the first for each module path in req.
        for _, r := range f.Require {
-               if v, ok := need[r.Mod.Path]; ok {
-                       r.Mod.Version = v
-                       r.Indirect = indirect[r.Mod.Path]
+               e, ok := need[r.Mod.Path]
+               if ok {
+                       r.setVersion(e.version)
+                       r.setIndirect(e.indirect)
                } else {
-                       *r = Require{}
+                       r.markRemoved()
+               }
+               delete(need, r.Mod.Path)
+       }
+
+       // Add new entries in the last block of the file for any paths that weren't
+       // already present.
+       //
+       // This step is nondeterministic, but the final result will be deterministic
+       // because we will sort the block.
+       for path, e := range need {
+               f.AddNewRequire(path, e.version, e.indirect)
+       }
+
+       f.SortBlocks()
+}
+
+// SetRequireSeparateIndirect updates the requirements of f to contain the given
+// requirements. Comment contents (except for 'indirect' markings) are retained
+// from the first existing requirement for each module path, and block structure
+// is maintained as long as the indirect markings match.
+//
+// Any requirements on paths not already present in the file are added. Direct
+// requirements are added to the last block containing *any* other direct
+// requirement. Indirect requirements are added to the last block containing
+// *only* other indirect requirements. If no suitable block exists, a new one is
+// added, with the last block containing a direct dependency (if any)
+// immediately before the first block containing only indirect dependencies.
+//
+// The Syntax field is ignored for requirements in the given blocks.
+func (f *File) SetRequireSeparateIndirect(req []*Require) {
+       type modKey struct {
+               path     string
+               indirect bool
+       }
+       need := make(map[modKey]string)
+       for _, r := range req {
+               need[modKey{r.Mod.Path, r.Indirect}] = r.Mod.Version
+       }
+
+       comments := make(map[string]Comments)
+       for _, r := range f.Require {
+               v, ok := need[modKey{r.Mod.Path, r.Indirect}]
+               if !ok {
+                       if _, ok := need[modKey{r.Mod.Path, !r.Indirect}]; ok {
+                               if _, dup := comments[r.Mod.Path]; !dup {
+                                       comments[r.Mod.Path] = r.Syntax.Comments
+                               }
+                       }
+                       r.markRemoved()
+                       continue
                }
+               r.setVersion(v)
+               delete(need, modKey{r.Mod.Path, r.Indirect})
        }
 
-       var newStmts []Expr
+       var (
+               lastDirectOrMixedBlock Expr
+               firstIndirectOnlyBlock Expr
+               lastIndirectOnlyBlock  Expr
+       )
        for _, stmt := range f.Syntax.Stmt {
                switch stmt := stmt.(type) {
+               case *Line:
+                       if len(stmt.Token) == 0 || stmt.Token[0] != "require" {
+                               continue
+                       }
+                       if isIndirect(stmt) {
+                               lastIndirectOnlyBlock = stmt
+                       } else {
+                               lastDirectOrMixedBlock = stmt
+                       }
                case *LineBlock:
-                       if len(stmt.Token) > 0 && stmt.Token[0] == "require" {
-                               var newLines []*Line
+                       if len(stmt.Token) == 0 || stmt.Token[0] != "require" {
+                               continue
+                       }
+                       indirectOnly := true
+                       for _, line := range stmt.Line {
+                               if len(line.Token) == 0 {
+                                       continue
+                               }
+                               if !isIndirect(line) {
+                                       indirectOnly = false
+                                       break
+                               }
+                       }
+                       if indirectOnly {
+                               lastIndirectOnlyBlock = stmt
+                               if firstIndirectOnlyBlock == nil {
+                                       firstIndirectOnlyBlock = stmt
+                               }
+                       } else {
+                               lastDirectOrMixedBlock = stmt
+                       }
+               }
+       }
+
+       isOrContainsStmt := func(stmt Expr, target Expr) bool {
+               if stmt == target {
+                       return true
+               }
+               if stmt, ok := stmt.(*LineBlock); ok {
+                       if target, ok := target.(*Line); ok {
                                for _, line := range stmt.Line {
-                                       if p, err := parseString(&line.Token[0]); err == nil && need[p] != "" {
-                                               if len(line.Comments.Before) == 1 && len(line.Comments.Before[0].Token) == 0 {
-                                                       line.Comments.Before = line.Comments.Before[:0]
-                                               }
-                                               line.Token[1] = need[p]
-                                               delete(need, p)
-                                               setIndirect(line, indirect[p])
-                                               newLines = append(newLines, line)
+                                       if line == target {
+                                               return true
                                        }
                                }
-                               if len(newLines) == 0 {
-                                       continue // drop stmt
-                               }
-                               stmt.Line = newLines
                        }
+               }
+               return false
+       }
 
-               case *Line:
-                       if len(stmt.Token) > 0 && stmt.Token[0] == "require" {
-                               if p, err := parseString(&stmt.Token[1]); err == nil && need[p] != "" {
-                                       stmt.Token[2] = need[p]
-                                       delete(need, p)
-                                       setIndirect(stmt, indirect[p])
+       addRequire := func(path, vers string, indirect bool, comments Comments) {
+               var line *Line
+               if indirect {
+                       if lastIndirectOnlyBlock != nil {
+                               line = f.Syntax.addLine(lastIndirectOnlyBlock, "require", path, vers)
+                       } else {
+                               // Add a new require block after the last direct-only or mixed "require"
+                               // block (if any).
+                               //
+                               // (f.Syntax.addLine would add the line to an existing "require" block if
+                               // present, but here the existing "require" blocks are all direct-only, so
+                               // we know we need to add a new block instead.)
+                               line = &Line{Token: []string{"require", path, vers}}
+                               lastIndirectOnlyBlock = line
+                               firstIndirectOnlyBlock = line // only block implies first block
+                               if lastDirectOrMixedBlock == nil {
+                                       f.Syntax.Stmt = append(f.Syntax.Stmt, line)
                                } else {
-                                       continue // drop stmt
+                                       for i, stmt := range f.Syntax.Stmt {
+                                               if isOrContainsStmt(stmt, lastDirectOrMixedBlock) {
+                                                       f.Syntax.Stmt = append(f.Syntax.Stmt, nil)     // increase size
+                                                       copy(f.Syntax.Stmt[i+2:], f.Syntax.Stmt[i+1:]) // shuffle elements up
+                                                       f.Syntax.Stmt[i+1] = line
+                                                       break
+                                               }
+                                       }
+                               }
+                       }
+               } else {
+                       if lastDirectOrMixedBlock != nil {
+                               line = f.Syntax.addLine(lastDirectOrMixedBlock, "require", path, vers)
+                       } else {
+                               // Add a new require block before the first indirect block (if any).
+                               //
+                               // That way if the file initially contains only indirect lines,
+                               // the direct lines still appear before it: we preserve existing
+                               // structure, but only to the extent that that structure already
+                               // reflects the direct/indirect split.
+                               line = &Line{Token: []string{"require", path, vers}}
+                               lastDirectOrMixedBlock = line
+                               if firstIndirectOnlyBlock == nil {
+                                       f.Syntax.Stmt = append(f.Syntax.Stmt, line)
+                               } else {
+                                       for i, stmt := range f.Syntax.Stmt {
+                                               if isOrContainsStmt(stmt, firstIndirectOnlyBlock) {
+                                                       f.Syntax.Stmt = append(f.Syntax.Stmt, nil)   // increase size
+                                                       copy(f.Syntax.Stmt[i+1:], f.Syntax.Stmt[i:]) // shuffle elements up
+                                                       f.Syntax.Stmt[i] = line
+                                                       break
+                                               }
+                                       }
                                }
                        }
                }
-               newStmts = append(newStmts, stmt)
+
+               line.Comments.Before = commentsAdd(line.Comments.Before, comments.Before)
+               line.Comments.Suffix = commentsAdd(line.Comments.Suffix, comments.Suffix)
+
+               r := &Require{
+                       Mod:      module.Version{Path: path, Version: vers},
+                       Indirect: indirect,
+                       Syntax:   line,
+               }
+               r.setIndirect(indirect)
+               f.Require = append(f.Require, r)
        }
-       f.Syntax.Stmt = newStmts
 
-       for path, vers := range need {
-               f.AddNewRequire(path, vers, indirect[path])
+       for k, vers := range need {
+               addRequire(k.path, vers, k.indirect, comments[k.path])
        }
        f.SortBlocks()
 }
@@ -885,7 +1126,7 @@ func (f *File) SetRequire(req []*Require) {
 func (f *File) DropRequire(path string) error {
        for _, r := range f.Require {
                if r.Mod.Path == path {
-                       f.Syntax.removeLine(r.Syntax)
+                       r.Syntax.markRemoved()
                        *r = Require{}
                }
        }
@@ -916,7 +1157,7 @@ func (f *File) AddExclude(path, vers string) error {
 func (f *File) DropExclude(path, vers string) error {
        for _, x := range f.Exclude {
                if x.Mod.Path == path && x.Mod.Version == vers {
-                       f.Syntax.removeLine(x.Syntax)
+                       x.Syntax.markRemoved()
                        *x = Exclude{}
                }
        }
@@ -947,7 +1188,7 @@ func (f *File) AddReplace(oldPath, oldVers, newPath, newVers string) error {
                                continue
                        }
                        // Already added; delete other replacements for same.
-                       f.Syntax.removeLine(r.Syntax)
+                       r.Syntax.markRemoved()
                        *r = Replace{}
                }
                if r.Old.Path == oldPath {
@@ -963,7 +1204,7 @@ func (f *File) AddReplace(oldPath, oldVers, newPath, newVers string) error {
 func (f *File) DropReplace(oldPath, oldVers string) error {
        for _, r := range f.Replace {
                if r.Old.Path == oldPath && r.Old.Version == oldVers {
-                       f.Syntax.removeLine(r.Syntax)
+                       r.Syntax.markRemoved()
                        *r = Replace{}
                }
        }
@@ -1004,7 +1245,7 @@ func (f *File) AddRetract(vi VersionInterval, rationale string) error {
 func (f *File) DropRetract(vi VersionInterval) error {
        for _, r := range f.Retract {
                if r.VersionInterval == vi {
-                       f.Syntax.removeLine(r.Syntax)
+                       r.Syntax.markRemoved()
                        *r = Retract{}
                }
        }
index 0e03014837cc8bb21df5ed1b30da70ef86d30bd9..ba97ac356e9cb34f73f6a756a9f65eedbdca25b0 100644 (file)
@@ -192,6 +192,21 @@ func (e *InvalidVersionError) Error() string {
 
 func (e *InvalidVersionError) Unwrap() error { return e.Err }
 
+// An InvalidPathError indicates a module, import, or file path doesn't
+// satisfy all naming constraints. See CheckPath, CheckImportPath,
+// and CheckFilePath for specific restrictions.
+type InvalidPathError struct {
+       Kind string // "module", "import", or "file"
+       Path string
+       Err  error
+}
+
+func (e *InvalidPathError) Error() string {
+       return fmt.Sprintf("malformed %s path %q: %v", e.Kind, e.Path, e.Err)
+}
+
+func (e *InvalidPathError) Unwrap() error { return e.Err }
+
 // Check checks that a given module path, version pair is valid.
 // In addition to the path being a valid module path
 // and the version being a valid semantic version,
@@ -296,30 +311,36 @@ func fileNameOK(r rune) bool {
 // this second requirement is replaced by a requirement that the path
 // follow the gopkg.in server's conventions.
 // Third, no path element may begin with a dot.
-func CheckPath(path string) error {
+func CheckPath(path string) (err error) {
+       defer func() {
+               if err != nil {
+                       err = &InvalidPathError{Kind: "module", Path: path, Err: err}
+               }
+       }()
+
        if err := checkPath(path, modulePath); err != nil {
-               return fmt.Errorf("malformed module path %q: %v", path, err)
+               return err
        }
        i := strings.Index(path, "/")
        if i < 0 {
                i = len(path)
        }
        if i == 0 {
-               return fmt.Errorf("malformed module path %q: leading slash", path)
+               return fmt.Errorf("leading slash")
        }
        if !strings.Contains(path[:i], ".") {
-               return fmt.Errorf("malformed module path %q: missing dot in first path element", path)
+               return fmt.Errorf("missing dot in first path element")
        }
        if path[0] == '-' {
-               return fmt.Errorf("malformed module path %q: leading dash in first path element", path)
+               return fmt.Errorf("leading dash in first path element")
        }
        for _, r := range path[:i] {
                if !firstPathOK(r) {
-                       return fmt.Errorf("malformed module path %q: invalid char %q in first path element", path, r)
+                       return fmt.Errorf("invalid char %q in first path element", r)
                }
        }
        if _, _, ok := SplitPathVersion(path); !ok {
-               return fmt.Errorf("malformed module path %q: invalid version", path)
+               return fmt.Errorf("invalid version")
        }
        return nil
 }
@@ -343,7 +364,7 @@ func CheckPath(path string) error {
 // subtleties of Unicode.
 func CheckImportPath(path string) error {
        if err := checkPath(path, importPath); err != nil {
-               return fmt.Errorf("malformed import path %q: %v", path, err)
+               return &InvalidPathError{Kind: "import", Path: path, Err: err}
        }
        return nil
 }
@@ -358,12 +379,13 @@ const (
        filePath
 )
 
-// checkPath checks that a general path is valid.
-// It returns an error describing why but not mentioning path.
-// Because these checks apply to both module paths and import paths,
-// the caller is expected to add the "malformed ___ path %q: " prefix.
-// fileName indicates whether the final element of the path is a file name
-// (as opposed to a directory name).
+// checkPath checks that a general path is valid. kind indicates what
+// specific constraints should be applied.
+//
+// checkPath returns an error describing why the path is not valid.
+// Because these checks apply to module, import, and file paths,
+// and because other checks may be applied, the caller is expected to wrap
+// this error with InvalidPathError.
 func checkPath(path string, kind pathKind) error {
        if !utf8.ValidString(path) {
                return fmt.Errorf("invalid UTF-8")
@@ -371,7 +393,7 @@ func checkPath(path string, kind pathKind) error {
        if path == "" {
                return fmt.Errorf("empty string")
        }
-       if path[0] == '-' {
+       if path[0] == '-' && kind != filePath {
                return fmt.Errorf("leading dash")
        }
        if strings.Contains(path, "//") {
@@ -477,7 +499,7 @@ func checkElem(elem string, kind pathKind) error {
 // subtleties of Unicode.
 func CheckFilePath(path string) error {
        if err := checkPath(path, filePath); err != nil {
-               return fmt.Errorf("malformed file path %q: %v", path, err)
+               return &InvalidPathError{Kind: "file", Path: path, Err: err}
        }
        return nil
 }
similarity index 95%
rename from libgo/go/cmd/go/internal/modfetch/pseudo.go
rename to libgo/go/golang.org/x/mod/module/pseudo.go
index 93eb0fad961b6663dd2c21246ccfc0fe8d19dcfe..f04ad3788694fc9eb4764fb4d8546d2faa01f4f8 100644 (file)
@@ -32,7 +32,7 @@
 // If the most recent tagged version before the target commit is vX.Y.Z-pre or vX.Y.Z-pre+incompatible,
 // then the pseudo-version uses form (4) or (5), making it a slightly later prerelease.
 
-package modfetch
+package module
 
 import (
        "errors"
@@ -40,15 +40,13 @@ import (
        "strings"
        "time"
 
-       "internal/lazyregexp"
-
-       "golang.org/x/mod/module"
+       "golang.org/x/mod/internal/lazyregexp"
        "golang.org/x/mod/semver"
 )
 
 var pseudoVersionRE = lazyregexp.New(`^v[0-9]+\.(0\.0-|\d+\.\d+-([^+]*\.)?0\.)\d{14}-[A-Za-z0-9]+(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$`)
 
-const pseudoVersionTimestampFormat = "20060102150405"
+const PseudoVersionTimestampFormat = "20060102150405"
 
 // PseudoVersion returns a pseudo-version for the given major version ("v1")
 // preexisting older tagged version ("" or "v1.2.3" or "v1.2.3-pre"), revision time,
@@ -57,7 +55,7 @@ func PseudoVersion(major, older string, t time.Time, rev string) string {
        if major == "" {
                major = "v0"
        }
-       segment := fmt.Sprintf("%s-%s", t.UTC().Format(pseudoVersionTimestampFormat), rev)
+       segment := fmt.Sprintf("%s-%s", t.UTC().Format(PseudoVersionTimestampFormat), rev)
        build := semver.Build(older)
        older = semver.Canonical(older)
        if older == "" {
@@ -142,7 +140,7 @@ func PseudoVersionTime(v string) (time.Time, error) {
        }
        t, err := time.Parse("20060102150405", timestamp)
        if err != nil {
-               return time.Time{}, &module.InvalidVersionError{
+               return time.Time{}, &InvalidVersionError{
                        Version: v,
                        Pseudo:  true,
                        Err:     fmt.Errorf("malformed time %q", timestamp),
@@ -180,7 +178,7 @@ func PseudoVersionBase(v string) (string, error) {
                        //
                        // There are a few such entries in the index generated by proxy.golang.org,
                        // but we believe those entries were generated by the proxy itself.
-                       return "", &module.InvalidVersionError{
+                       return "", &InvalidVersionError{
                                Version: v,
                                Pseudo:  true,
                                Err:     fmt.Errorf("lacks base version, but has build metadata %q", build),
@@ -208,7 +206,7 @@ func PseudoVersionBase(v string) (string, error) {
                        // treat them as equivalent to vX.0.0 (especially since the invalid
                        // pseudo-versions have lower precedence than the real ones). For now, we
                        // reject them.
-                       return "", &module.InvalidVersionError{
+                       return "", &InvalidVersionError{
                                Version: v,
                                Pseudo:  true,
                                Err:     fmt.Errorf("version before %s would have negative patch number", base),
@@ -230,7 +228,7 @@ var errPseudoSyntax = errors.New("syntax error")
 
 func parsePseudoVersion(v string) (base, timestamp, rev, build string, err error) {
        if !IsPseudoVersion(v) {
-               return "", "", "", "", &module.InvalidVersionError{
+               return "", "", "", "", &InvalidVersionError{
                        Version: v,
                        Pseudo:  true,
                        Err:     errPseudoSyntax,
index 4338f351774f86409b1b659f3e311e9bae1e354c..7be398f80d33e724ece45da019cb91132563c17b 100644 (file)
@@ -22,6 +22,8 @@
 // as shorthands for vMAJOR.0.0 and vMAJOR.MINOR.0.
 package semver
 
+import "sort"
+
 // parsed returns the parsed form of a semantic version string.
 type parsed struct {
        major      string
@@ -150,6 +152,24 @@ func Max(v, w string) string {
        return w
 }
 
+// ByVersion implements sort.Interface for sorting semantic version strings.
+type ByVersion []string
+
+func (vs ByVersion) Len() int      { return len(vs) }
+func (vs ByVersion) Swap(i, j int) { vs[i], vs[j] = vs[j], vs[i] }
+func (vs ByVersion) Less(i, j int) bool {
+       cmp := Compare(vs[i], vs[j])
+       if cmp != 0 {
+               return cmp < 0
+       }
+       return vs[i] < vs[j]
+}
+
+// Sort sorts a list of semantic version strings using ByVersion.
+func Sort(list []string) {
+       sort.Sort(ByVersion(list))
+}
+
 func parse(v string) (p parsed, ok bool) {
        if v == "" || v[0] != 'v' {
                p.err = "missing v prefix"
index 654f191f8a94136522615e9112ad6be468d149d8..1736fc5d12e2f95b7bd0643d1fbf90cd3168e200 100644 (file)
@@ -1023,6 +1023,24 @@ func (p *Parser) OPTResource() (OPTResource, error) {
        return r, nil
 }
 
+// UnknownResource parses a single UnknownResource.
+//
+// One of the XXXHeader methods must have been called before calling this
+// method.
+func (p *Parser) UnknownResource() (UnknownResource, error) {
+       if !p.resHeaderValid {
+               return UnknownResource{}, ErrNotStarted
+       }
+       r, err := unpackUnknownResource(p.resHeader.Type, p.msg, p.off, p.resHeader.Length)
+       if err != nil {
+               return UnknownResource{}, err
+       }
+       p.off += int(p.resHeader.Length)
+       p.resHeaderValid = false
+       p.index++
+       return r, nil
+}
+
 // Unpack parses a full Message.
 func (m *Message) Unpack(msg []byte) error {
        var p Parser
@@ -1557,6 +1575,30 @@ func (b *Builder) OPTResource(h ResourceHeader, r OPTResource) error {
        return nil
 }
 
+// UnknownResource adds a single UnknownResource.
+func (b *Builder) UnknownResource(h ResourceHeader, r UnknownResource) error {
+       if err := b.checkResourceSection(); err != nil {
+               return err
+       }
+       h.Type = r.realType()
+       msg, lenOff, err := h.pack(b.msg, b.compression, b.start)
+       if err != nil {
+               return &nestedError{"ResourceHeader", err}
+       }
+       preLen := len(msg)
+       if msg, err = r.pack(msg, b.compression, b.start); err != nil {
+               return &nestedError{"UnknownResource body", err}
+       }
+       if err := h.fixLen(msg, lenOff, preLen); err != nil {
+               return err
+       }
+       if err := b.incrementSectionCount(); err != nil {
+               return err
+       }
+       b.msg = msg
+       return nil
+}
+
 // Finish ends message building and generates a binary message.
 func (b *Builder) Finish() ([]byte, error) {
        if b.section < sectionHeader {
@@ -2135,13 +2177,15 @@ func unpackResourceBody(msg []byte, off int, hdr ResourceHeader) (ResourceBody,
                rb, err = unpackOPTResource(msg, off, hdr.Length)
                r = &rb
                name = "OPT"
+       default:
+               var rb UnknownResource
+               rb, err = unpackUnknownResource(hdr.Type, msg, off, hdr.Length)
+               r = &rb
+               name = "Unknown"
        }
        if err != nil {
                return nil, off, &nestedError{name + " record", err}
        }
-       if r == nil {
-               return nil, off, errors.New("invalid resource type: " + hdr.Type.String())
-       }
        return r, off + int(hdr.Length), nil
 }
 
@@ -2585,3 +2629,36 @@ func unpackOPTResource(msg []byte, off int, length uint16) (OPTResource, error)
        }
        return OPTResource{opts}, nil
 }
+
+// An UnknownResource is a catch-all container for unknown record types.
+type UnknownResource struct {
+       Type Type
+       Data []byte
+}
+
+func (r *UnknownResource) realType() Type {
+       return r.Type
+}
+
+// pack appends the wire format of the UnknownResource to msg.
+func (r *UnknownResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
+       return packBytes(msg, r.Data[:]), nil
+}
+
+// GoString implements fmt.GoStringer.GoString.
+func (r *UnknownResource) GoString() string {
+       return "dnsmessage.UnknownResource{" +
+               "Type: " + r.Type.GoString() + ", " +
+               "Data: []byte{" + printByteSlice(r.Data) + "}}"
+}
+
+func unpackUnknownResource(recordType Type, msg []byte, off int, length uint16) (UnknownResource, error) {
+       parsed := UnknownResource{
+               Type: recordType,
+               Data: make([]byte, length),
+       }
+       if _, err := unpackBytes(msg, off, parsed.Data); err != nil {
+               return UnknownResource{}, err
+       }
+       return parsed, nil
+}
index a98a31f40388894036a4122ef802465231b90149..5208ba6cb88424d7f2e8285ae1926cd24a4cad92 100644 (file)
@@ -4,6 +4,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build go1.10
 // +build go1.10
 
 // Package idna implements IDNA2008 using the compatibility processing
@@ -66,15 +67,14 @@ func Transitional(transitional bool) Option {
 
 // VerifyDNSLength sets whether a Profile should fail if any of the IDN parts
 // are longer than allowed by the RFC.
+//
+// This option corresponds to the VerifyDnsLength flag in UTS #46.
 func VerifyDNSLength(verify bool) Option {
        return func(o *options) { o.verifyDNSLength = verify }
 }
 
 // RemoveLeadingDots removes leading label separators. Leading runes that map to
 // dots, such as U+3002 IDEOGRAPHIC FULL STOP, are removed as well.
-//
-// This is the behavior suggested by the UTS #46 and is adopted by some
-// browsers.
 func RemoveLeadingDots(remove bool) Option {
        return func(o *options) { o.removeLeadingDots = remove }
 }
@@ -82,6 +82,8 @@ func RemoveLeadingDots(remove bool) Option {
 // ValidateLabels sets whether to check the mandatory label validation criteria
 // as defined in Section 5.4 of RFC 5891. This includes testing for correct use
 // of hyphens ('-'), normalization, validity of runes, and the context rules.
+// In particular, ValidateLabels also sets the CheckHyphens and CheckJoiners flags
+// in UTS #46.
 func ValidateLabels(enable bool) Option {
        return func(o *options) {
                // Don't override existing mappings, but set one that at least checks
@@ -90,25 +92,48 @@ func ValidateLabels(enable bool) Option {
                        o.mapping = normalize
                }
                o.trie = trie
-               o.validateLabels = enable
-               o.fromPuny = validateFromPunycode
+               o.checkJoiners = enable
+               o.checkHyphens = enable
+               if enable {
+                       o.fromPuny = validateFromPunycode
+               } else {
+                       o.fromPuny = nil
+               }
+       }
+}
+
+// CheckHyphens sets whether to check for correct use of hyphens ('-') in
+// labels. Most web browsers do not have this option set, since labels such as
+// "r3---sn-apo3qvuoxuxbt-j5pe" are in common use.
+//
+// This option corresponds to the CheckHyphens flag in UTS #46.
+func CheckHyphens(enable bool) Option {
+       return func(o *options) { o.checkHyphens = enable }
+}
+
+// CheckJoiners sets whether to check the ContextJ rules as defined in Appendix
+// A of RFC 5892, concerning the use of joiner runes.
+//
+// This option corresponds to the CheckJoiners flag in UTS #46.
+func CheckJoiners(enable bool) Option {
+       return func(o *options) {
+               o.trie = trie
+               o.checkJoiners = enable
        }
 }
 
 // StrictDomainName limits the set of permissible ASCII characters to those
 // allowed in domain names as defined in RFC 1034 (A-Z, a-z, 0-9 and the
-// hyphen). This is set by default for MapForLookup and ValidateForRegistration.
+// hyphen). This is set by default for MapForLookup and ValidateForRegistration,
+// but is only useful if ValidateLabels is set.
 //
 // This option is useful, for instance, for browsers that allow characters
 // outside this range, for example a '_' (U+005F LOW LINE). See
-// http://www.rfc-editor.org/std/std3.txt for more details This option
-// corresponds to the UseSTD3ASCIIRules option in UTS #46.
+// http://www.rfc-editor.org/std/std3.txt for more details.
+//
+// This option corresponds to the UseSTD3ASCIIRules flag in UTS #46.
 func StrictDomainName(use bool) Option {
-       return func(o *options) {
-               o.trie = trie
-               o.useSTD3Rules = use
-               o.fromPuny = validateFromPunycode
-       }
+       return func(o *options) { o.useSTD3Rules = use }
 }
 
 // NOTE: the following options pull in tables. The tables should not be linked
@@ -116,6 +141,8 @@ func StrictDomainName(use bool) Option {
 
 // BidiRule enables the Bidi rule as defined in RFC 5893. Any application
 // that relies on proper validation of labels should include this rule.
+//
+// This option corresponds to the CheckBidi flag in UTS #46.
 func BidiRule() Option {
        return func(o *options) { o.bidirule = bidirule.ValidString }
 }
@@ -151,7 +178,8 @@ func MapForLookup() Option {
 type options struct {
        transitional      bool
        useSTD3Rules      bool
-       validateLabels    bool
+       checkHyphens      bool
+       checkJoiners      bool
        verifyDNSLength   bool
        removeLeadingDots bool
 
@@ -224,8 +252,11 @@ func (p *Profile) String() string {
        if p.useSTD3Rules {
                s += ":UseSTD3Rules"
        }
-       if p.validateLabels {
-               s += ":ValidateLabels"
+       if p.checkHyphens {
+               s += ":CheckHyphens"
+       }
+       if p.checkJoiners {
+               s += ":CheckJoiners"
        }
        if p.verifyDNSLength {
                s += ":VerifyDNSLength"
@@ -253,26 +284,29 @@ var (
 
        punycode = &Profile{}
        lookup   = &Profile{options{
-               transitional:   true,
-               useSTD3Rules:   true,
-               validateLabels: true,
-               trie:           trie,
-               fromPuny:       validateFromPunycode,
-               mapping:        validateAndMap,
-               bidirule:       bidirule.ValidString,
+               transitional: true,
+               useSTD3Rules: true,
+               checkHyphens: true,
+               checkJoiners: true,
+               trie:         trie,
+               fromPuny:     validateFromPunycode,
+               mapping:      validateAndMap,
+               bidirule:     bidirule.ValidString,
        }}
        display = &Profile{options{
-               useSTD3Rules:   true,
-               validateLabels: true,
-               trie:           trie,
-               fromPuny:       validateFromPunycode,
-               mapping:        validateAndMap,
-               bidirule:       bidirule.ValidString,
+               useSTD3Rules: true,
+               checkHyphens: true,
+               checkJoiners: true,
+               trie:         trie,
+               fromPuny:     validateFromPunycode,
+               mapping:      validateAndMap,
+               bidirule:     bidirule.ValidString,
        }}
        registration = &Profile{options{
                useSTD3Rules:    true,
-               validateLabels:  true,
                verifyDNSLength: true,
+               checkHyphens:    true,
+               checkJoiners:    true,
                trie:            trie,
                fromPuny:        validateFromPunycode,
                mapping:         validateRegistration,
@@ -339,7 +373,7 @@ func (p *Profile) process(s string, toASCII bool) (string, error) {
                        }
                        isBidi = isBidi || bidirule.DirectionString(u) != bidi.LeftToRight
                        labels.set(u)
-                       if err == nil && p.validateLabels {
+                       if err == nil && p.fromPuny != nil {
                                err = p.fromPuny(p, u)
                        }
                        if err == nil {
@@ -680,16 +714,18 @@ func (p *Profile) validateLabel(s string) (err error) {
                }
                return nil
        }
-       if !p.validateLabels {
-               return nil
-       }
-       trie := p.trie // p.validateLabels is only set if trie is set.
-       if len(s) > 4 && s[2] == '-' && s[3] == '-' {
-               return &labelError{s, "V2"}
+       if p.checkHyphens {
+               if len(s) > 4 && s[2] == '-' && s[3] == '-' {
+                       return &labelError{s, "V2"}
+               }
+               if s[0] == '-' || s[len(s)-1] == '-' {
+                       return &labelError{s, "V3"}
+               }
        }
-       if s[0] == '-' || s[len(s)-1] == '-' {
-               return &labelError{s, "V3"}
+       if !p.checkJoiners {
+               return nil
        }
+       trie := p.trie // p.checkJoiners is only set if trie is set.
        // TODO: merge the use of this in the trie.
        v, sz := trie.lookupString(s)
        x := info(v)
index 8842146b5d9920954100babde5eb3dcc2ffb9150..55f718f12744713d679c049765086d87a7262132 100644 (file)
@@ -4,6 +4,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !go1.10
 // +build !go1.10
 
 // Package idna implements IDNA2008 using the compatibility processing
@@ -65,15 +66,14 @@ func Transitional(transitional bool) Option {
 
 // VerifyDNSLength sets whether a Profile should fail if any of the IDN parts
 // are longer than allowed by the RFC.
+//
+// This option corresponds to the VerifyDnsLength flag in UTS #46.
 func VerifyDNSLength(verify bool) Option {
        return func(o *options) { o.verifyDNSLength = verify }
 }
 
 // RemoveLeadingDots removes leading label separators. Leading runes that map to
 // dots, such as U+3002 IDEOGRAPHIC FULL STOP, are removed as well.
-//
-// This is the behavior suggested by the UTS #46 and is adopted by some
-// browsers.
 func RemoveLeadingDots(remove bool) Option {
        return func(o *options) { o.removeLeadingDots = remove }
 }
@@ -81,6 +81,8 @@ func RemoveLeadingDots(remove bool) Option {
 // ValidateLabels sets whether to check the mandatory label validation criteria
 // as defined in Section 5.4 of RFC 5891. This includes testing for correct use
 // of hyphens ('-'), normalization, validity of runes, and the context rules.
+// In particular, ValidateLabels also sets the CheckHyphens and CheckJoiners flags
+// in UTS #46.
 func ValidateLabels(enable bool) Option {
        return func(o *options) {
                // Don't override existing mappings, but set one that at least checks
@@ -89,25 +91,48 @@ func ValidateLabels(enable bool) Option {
                        o.mapping = normalize
                }
                o.trie = trie
-               o.validateLabels = enable
-               o.fromPuny = validateFromPunycode
+               o.checkJoiners = enable
+               o.checkHyphens = enable
+               if enable {
+                       o.fromPuny = validateFromPunycode
+               } else {
+                       o.fromPuny = nil
+               }
+       }
+}
+
+// CheckHyphens sets whether to check for correct use of hyphens ('-') in
+// labels. Most web browsers do not have this option set, since labels such as
+// "r3---sn-apo3qvuoxuxbt-j5pe" are in common use.
+//
+// This option corresponds to the CheckHyphens flag in UTS #46.
+func CheckHyphens(enable bool) Option {
+       return func(o *options) { o.checkHyphens = enable }
+}
+
+// CheckJoiners sets whether to check the ContextJ rules as defined in Appendix
+// A of RFC 5892, concerning the use of joiner runes.
+//
+// This option corresponds to the CheckJoiners flag in UTS #46.
+func CheckJoiners(enable bool) Option {
+       return func(o *options) {
+               o.trie = trie
+               o.checkJoiners = enable
        }
 }
 
 // StrictDomainName limits the set of permissable ASCII characters to those
 // allowed in domain names as defined in RFC 1034 (A-Z, a-z, 0-9 and the
-// hyphen). This is set by default for MapForLookup and ValidateForRegistration.
+// hyphen). This is set by default for MapForLookup and ValidateForRegistration,
+// but is only useful if ValidateLabels is set.
 //
 // This option is useful, for instance, for browsers that allow characters
 // outside this range, for example a '_' (U+005F LOW LINE). See
-// http://www.rfc-editor.org/std/std3.txt for more details This option
-// corresponds to the UseSTD3ASCIIRules option in UTS #46.
+// http://www.rfc-editor.org/std/std3.txt for more details.
+//
+// This option corresponds to the UseSTD3ASCIIRules flag in UTS #46.
 func StrictDomainName(use bool) Option {
-       return func(o *options) {
-               o.trie = trie
-               o.useSTD3Rules = use
-               o.fromPuny = validateFromPunycode
-       }
+       return func(o *options) { o.useSTD3Rules = use }
 }
 
 // NOTE: the following options pull in tables. The tables should not be linked
@@ -115,6 +140,8 @@ func StrictDomainName(use bool) Option {
 
 // BidiRule enables the Bidi rule as defined in RFC 5893. Any application
 // that relies on proper validation of labels should include this rule.
+//
+// This option corresponds to the CheckBidi flag in UTS #46.
 func BidiRule() Option {
        return func(o *options) { o.bidirule = bidirule.ValidString }
 }
@@ -151,7 +178,8 @@ func MapForLookup() Option {
 type options struct {
        transitional      bool
        useSTD3Rules      bool
-       validateLabels    bool
+       checkHyphens      bool
+       checkJoiners      bool
        verifyDNSLength   bool
        removeLeadingDots bool
 
@@ -224,8 +252,11 @@ func (p *Profile) String() string {
        if p.useSTD3Rules {
                s += ":UseSTD3Rules"
        }
-       if p.validateLabels {
-               s += ":ValidateLabels"
+       if p.checkHyphens {
+               s += ":CheckHyphens"
+       }
+       if p.checkJoiners {
+               s += ":CheckJoiners"
        }
        if p.verifyDNSLength {
                s += ":VerifyDNSLength"
@@ -254,9 +285,10 @@ var (
        punycode = &Profile{}
        lookup   = &Profile{options{
                transitional:      true,
-               useSTD3Rules:      true,
-               validateLabels:    true,
                removeLeadingDots: true,
+               useSTD3Rules:      true,
+               checkHyphens:      true,
+               checkJoiners:      true,
                trie:              trie,
                fromPuny:          validateFromPunycode,
                mapping:           validateAndMap,
@@ -264,8 +296,9 @@ var (
        }}
        display = &Profile{options{
                useSTD3Rules:      true,
-               validateLabels:    true,
                removeLeadingDots: true,
+               checkHyphens:      true,
+               checkJoiners:      true,
                trie:              trie,
                fromPuny:          validateFromPunycode,
                mapping:           validateAndMap,
@@ -273,8 +306,9 @@ var (
        }}
        registration = &Profile{options{
                useSTD3Rules:    true,
-               validateLabels:  true,
                verifyDNSLength: true,
+               checkHyphens:    true,
+               checkJoiners:    true,
                trie:            trie,
                fromPuny:        validateFromPunycode,
                mapping:         validateRegistration,
@@ -338,7 +372,7 @@ func (p *Profile) process(s string, toASCII bool) (string, error) {
                                continue
                        }
                        labels.set(u)
-                       if err == nil && p.validateLabels {
+                       if err == nil && p.fromPuny != nil {
                                err = p.fromPuny(p, u)
                        }
                        if err == nil {
@@ -628,16 +662,18 @@ func (p *Profile) validateLabel(s string) error {
        if p.bidirule != nil && !p.bidirule(s) {
                return &labelError{s, "B"}
        }
-       if !p.validateLabels {
-               return nil
-       }
-       trie := p.trie // p.validateLabels is only set if trie is set.
-       if len(s) > 4 && s[2] == '-' && s[3] == '-' {
-               return &labelError{s, "V2"}
+       if p.checkHyphens {
+               if len(s) > 4 && s[2] == '-' && s[3] == '-' {
+                       return &labelError{s, "V2"}
+               }
+               if s[0] == '-' || s[len(s)-1] == '-' {
+                       return &labelError{s, "V3"}
+               }
        }
-       if s[0] == '-' || s[len(s)-1] == '-' {
-               return &labelError{s, "V3"}
+       if !p.checkJoiners {
+               return nil
        }
+       trie := p.trie // p.checkJoiners is only set if trie is set.
        // TODO: merge the use of this in the trie.
        v, sz := trie.lookupString(s)
        x := info(v)
index 54fddb4b16cce914c20f23527658f5b70ab1b873..d1d62ef459bb730ff5c6ff70c91d0289b8c4c40b 100644 (file)
@@ -1,5 +1,6 @@
 // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
 
+//go:build go1.10 && !go1.13
 // +build go1.10,!go1.13
 
 package idna
index 8ce0811fdf3dec0009c9d5223c12bf5ae5867dc3..167efba71256cd1696d175013b5bfb9f16348524 100644 (file)
@@ -1,5 +1,6 @@
 // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
 
+//go:build go1.13 && !go1.14
 // +build go1.13,!go1.14
 
 package idna
index f39f0cb4cd879e8364b5f48c011fee00b03a6098..ab40f7bcc3b81235e6868d5ac016802eb336efe1 100644 (file)
@@ -1,5 +1,6 @@
 // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
 
+//go:build go1.14 && !go1.16
 // +build go1.14,!go1.16
 
 package idna
index e8c7a36d7a747f38deb0c45b01976400805772cf..390c5e56d2a4e4c667ac20624dbe8e4c273e7003 100644 (file)
@@ -1,5 +1,6 @@
 // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
 
+//go:build go1.16
 // +build go1.16
 
 package idna
index 8b65fa16783034e716548f6e2a23a7a816f0ebba..4074b5332e3e3451eeb50793ab57aecd36a6485d 100644 (file)
@@ -1,5 +1,6 @@
 // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
 
+//go:build !go1.10
 // +build !go1.10
 
 package idna
index 22c2461c1c0599ed84c1cc5727fe7feecc7e6699..6e3a9312b9a065e17a8275e08ca9bc4c63c8097e 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows && !zos
 // +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows,!zos
 
 package nettest
index c1b13593fe7658eac8dd8a760a97655880d58a92..b1cb8b2f3b12da1c1eeedb7c0bc4d37e75125cdb 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
 // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
 
 package nettest
index 3c2fe15a970098c4f9f2ce4de37bc9536e40ff41..4f6ad968a247e4de7ea06e991164e3197ba02120 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || netbsd || openbsd
 // +build darwin dragonfly freebsd netbsd openbsd
 
 package route
index 6910520eca5d039205947eeed528cc65b2f23da5..a5e28f1e9cd6ca3a32c396096bb35c52b317006c 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || netbsd || openbsd
 // +build darwin dragonfly freebsd netbsd openbsd
 
 package route
index 05ef2a9ce3c790071100d0adb48af9552f29ae7e..9e9407830c59e6228aca9fbc9fecb93fd16f74d7 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || netbsd || openbsd
 // +build darwin dragonfly freebsd netbsd openbsd
 
 package route
index 520d657b578fcee174cf63b72ba36583d306556a..8282bfe9e229d5668d53ebbd8b45c2724cc226ef 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build dragonfly || freebsd || netbsd
 // +build dragonfly freebsd netbsd
 
 package route
index ac4e7a6805afdfbce423940550ffe139b08f36b1..85b7e993bb350f60ae5e1c7c9d0ae4663b5cb8d4 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || netbsd
 // +build darwin dragonfly netbsd
 
 package route
index 1e99a9cc64b9ad0b0713322588b4998e01e725f8..dd0b214baa99a4b9d41783f606166d4740344a4f 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd
 // +build darwin dragonfly freebsd
 
 package route
index 80c482ae94a6a6a78680c60951dc21d3a79cc7e1..d53bb7f9b13108c9c1367da1874897afe5fb46e4 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || netbsd || openbsd
 // +build darwin dragonfly freebsd netbsd openbsd
 
 package route
index 4462cf1b6f6566f6f40e6eb5fca9d4097620d77e..fd0019ecc560aaf061c4a590d9713ecd72ed2124 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || netbsd || openbsd
 // +build darwin dragonfly freebsd netbsd openbsd
 
 // Package route provides basic functions for the manipulation of
@@ -107,17 +108,28 @@ const (
 // an interface index or a set of interface flags. In most cases, zero
 // means a wildcard.
 func FetchRIB(af int, typ RIBType, arg int) ([]byte, error) {
-       mib := [6]int32{sysCTL_NET, sysAF_ROUTE, 0, int32(af), int32(typ), int32(arg)}
-       n := uintptr(0)
-       if err := sysctl(mib[:], nil, &n, nil, 0); err != nil {
-               return nil, os.NewSyscallError("sysctl", err)
+       try := 0
+       for {
+               try++
+               mib := [6]int32{sysCTL_NET, sysAF_ROUTE, 0, int32(af), int32(typ), int32(arg)}
+               n := uintptr(0)
+               if err := sysctl(mib[:], nil, &n, nil, 0); err != nil {
+                       return nil, os.NewSyscallError("sysctl", err)
+               }
+               if n == 0 {
+                       return nil, nil
+               }
+               b := make([]byte, n)
+               if err := sysctl(mib[:], &b[0], &n, nil, 0); err != nil {
+                       // If the sysctl failed because the data got larger
+                       // between the two sysctl calls, try a few times
+                       // before failing. (golang.org/issue/45736).
+                       const maxTries = 3
+                       if err == syscall.ENOMEM && try < maxTries {
+                               continue
+                       }
+                       return nil, os.NewSyscallError("sysctl", err)
+               }
+               return b[:n], nil
        }
-       if n == 0 {
-               return nil, nil
-       }
-       b := make([]byte, n)
-       if err := sysctl(mib[:], &b[0], &n, nil, 0); err != nil {
-               return nil, os.NewSyscallError("sysctl", err)
-       }
-       return b[:n], nil
 }
index b83add668e7db46cc1349449af9dcceff2b14635..d6ee42f1b1d1d3e7722ff8958f0488bac02f83a2 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || netbsd
 // +build darwin dragonfly freebsd netbsd
 
 package route
index a0ab3e9c73bdbeed753bf41d2414318d9b7b1e75..537484ae5aa2cedcff4bd3efc5a6bf7df42f9e83 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || netbsd || openbsd
 // +build darwin dragonfly freebsd netbsd openbsd
 
 package route
index 72431b0341061445ff53a9140739153db25ef4dd..97166dd3c4c52ee5c37424ad0a7a3d883d5e095e 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build dragonfly || freebsd || netbsd || openbsd
 // +build dragonfly freebsd netbsd openbsd
 
 package route
index 7922a6836fc3da2e7b1668640289192d9730b84e..7a13e4fd90430d6ec08dc0ce114abf8bd4378255 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build go1.12
 // +build go1.12
 
 package route
index f77701fe86854828200db6d391769b50860fc195..abbec2d44bfbe30fa5dda7fd33da3cbf9bdc9523 100644 (file)
@@ -154,14 +154,13 @@ var MIPS64X struct {
 // For ppc64/ppc64le, it is safe to check only for ISA level starting on ISA v3.00,
 // since there are no optional categories. There are some exceptions that also
 // require kernel support to work (DARN, SCV), so there are feature bits for
-// those as well. The minimum processor requirement is POWER8 (ISA 2.07).
-// The struct is padded to avoid false sharing.
+// those as well. The struct is padded to avoid false sharing.
 var PPC64 struct {
        _        CacheLinePad
        HasDARN  bool // Hardware random number generator (requires kernel enablement)
        HasSCV   bool // Syscall vectored (requires kernel enablement)
        IsPOWER8 bool // ISA v2.07 (POWER8)
-       IsPOWER9 bool // ISA v3.00 (POWER9)
+       IsPOWER9 bool // ISA v3.00 (POWER9), implies IsPOWER8
        _        CacheLinePad
 }
 
index 464a209cf598f6d2369b7b62b0ad93e4fabe5051..8aaeef545a76bee1f012a9fe4f02d65150b187ce 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix
 // +build aix
 
 package cpu
@@ -19,6 +20,7 @@ func archInit() {
                PPC64.IsPOWER8 = true
        }
        if impl&_IMPL_POWER9 != 0 {
+               PPC64.IsPOWER8 = true
                PPC64.IsPOWER9 = true
        }
 
index 7f7f272a014f78663214ef55749f03a90bbf39ef..ccf542a73da87b9da870e840fa21d5423c5e1ed0 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build gc
 // +build gc
 
 package cpu
index 75a95566161d072f987b5a0c9dc02ace9fee50ed..0af2f248412d5541eff2178327242351d8ac3ba5 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build gc
 // +build gc
 
 package cpu
index 4adb89cf9cc84db8631b811bd40bdb181f7f6714..3298a87e98129347604f98f4f7ce08d7a40c23e1 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build (386 || amd64 || amd64p32) && gc
 // +build 386 amd64 amd64p32
 // +build gc
 
@@ -14,3 +15,7 @@ func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32)
 // xgetbv with ecx = 0 is implemented in cpu_x86.s for gc compiler
 // and in cpu_gccgo.c for gccgo.
 func xgetbv() (eax, edx uint32)
+
+// darwinSupportsAVX512 is implemented in cpu_x86.s for gc compiler
+// and in cpu_gccgo_x86.go for gccgo.
+func darwinSupportsAVX512() bool
index 53ca8d65c37eb0006e87ee7de7814f384011a9e8..2aff31891162e82fdb8669bec0f5145e2821dbf6 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build gccgo
 // +build gccgo
 
 package cpu
index aa986f77825f45931c7472fe0a21ae5a265e02b1..4bfbda61993df172c27bdb795f26b56dd007b548 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build gccgo
 // +build gccgo
 
 package cpu
index ba49b91bd398cd72c437e85af46655d204416794..863d415ab4987c21623b1b873a80c902335e6c9e 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build (386 || amd64 || amd64p32) && gccgo
 // +build 386 amd64 amd64p32
 // +build gccgo
 
@@ -24,3 +25,9 @@ func xgetbv() (eax, edx uint32) {
        gccgoXgetbv(&a, &d)
        return a, d
 }
+
+// gccgo doesn't build on Darwin, per:
+// https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/gcc.rb#L76
+func darwinSupportsAVX512() bool {
+       return false
+}
index 6fc874f7fefd04f217de2bca379dbebd931bcafb..159a686f6f7a9226d2af484264aa272a75ec2728 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !386 && !amd64 && !amd64p32 && !arm64
 // +build !386,!amd64,!amd64p32,!arm64
 
 package cpu
index 5a418900538094d42eef30224b2c3f7e5a453c52..6000db4cdd1b32a326b533fc608bd54a6eefd421 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build linux && (mips64 || mips64le)
 // +build linux
 // +build mips64 mips64le
 
index 42b5d33cb69854d20ae7677c12ad912e336da0f5..f4992b1a59388afe57b25cd150e7d4058cd8843c 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build linux && !arm && !arm64 && !mips64 && !mips64le && !ppc64 && !ppc64le && !s390x
 // +build linux,!arm,!arm64,!mips64,!mips64le,!ppc64,!ppc64le,!s390x
 
 package cpu
index 99f8a6399efbf1c7e96639f14c570a85cf84b6da..021356d6deb05e7cc40be27cfe6d09936be8e1f0 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build linux && (ppc64 || ppc64le)
 // +build linux
 // +build ppc64 ppc64le
 
index eb4e01049366bd49b807e540e8262b5941671012..d10b9800c9b18c573dc4c8511b7bb4ee54f9abe3 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build mips64 || mips64le
 // +build mips64 mips64le
 
 package cpu
index f6767b70028cb1a7805e4c1eeae836f807c44c3d..e67e88f4c96c0a5d39792735602b50e383420064 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build mips || mipsle
 // +build mips mipsle
 
 package cpu
index b412efc1bd1ddf55db7076510662a87ce576de8e..d7b4fb4ccc24fb6d6f5979b936b2184f057ad685 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !linux && arm
 // +build !linux,arm
 
 package cpu
index 16c1c4090ee2f1c7060d5d4d723c231fa6d2e6f2..f8c484f589f5e01c10a907cf5a3a0b229ab72ccb 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !linux,!netbsd
-// +build arm64
+//go:build !linux && !netbsd && arm64
+// +build !linux,!netbsd,arm64
 
 package cpu
 
index f49fad67783e61e5632833d613f084ab536556b8..0dafe9644a5a18cfc3e8319dedbaddf336a76fb8 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !linux && (mips64 || mips64le)
 // +build !linux
 // +build mips64 mips64le
 
index aedfb17e3f9c8ade7a9f978b3d1b7d0f3c06ef83..f2e92c0564ce72df8f7096bc8600fb9873395a6a 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ppc64 || ppc64le
 // +build ppc64 ppc64le
 
 package cpu
index 2001b99893b5b15e46f6fbe133546cbc0dc17f03..edfa5b7d605a095d6a84395dd5164998f9ad2d36 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build riscv64
 // +build riscv64
 
 package cpu
index 60017a6fae331a720973e57a08e742d88ef7d0a9..8d4e8fb2edc30cc0193eff3bbef3a1badc4b224b 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build wasm
 // +build wasm
 
 package cpu
index 8cc67e68fdffb63259cce7d0e22382c9c0d1420a..e50ed987599bd83d001cad6a901af2e1054d73e9 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build 386 || amd64 || amd64p32
 // +build 386 amd64 amd64p32
 
 package cpu
@@ -86,8 +87,14 @@ func archInit() {
                // Check if XMM and YMM registers have OS support.
                osSupportsAVX = isSet(1, eax) && isSet(2, eax)
 
-               // Check if OPMASK and ZMM registers have OS support.
-               osSupportsAVX512 = osSupportsAVX && isSet(5, eax) && isSet(6, eax) && isSet(7, eax)
+               if runtime.GOOS == "darwin" {
+                       // Check darwin commpage for AVX512 support. Necessary because:
+                       // https://github.com/apple/darwin-xnu/blob/0a798f6738bc1db01281fc08ae024145e84df927/osfmk/i386/fpu.c#L175-L201
+                       osSupportsAVX512 = osSupportsAVX && darwinSupportsAVX512()
+               } else {
+                       // Check if OPMASK and ZMM registers have OS support.
+                       osSupportsAVX512 = osSupportsAVX && isSet(5, eax) && isSet(6, eax) && isSet(7, eax)
+               }
        }
 
        X86.HasAVX = isSet(28, ecx1) && osSupportsAVX
index 76fbe40b762d732b17c501c56a34921957c53e7b..a864f24d7589aa0d84734690953a55c27b2d9bba 100644 (file)
@@ -8,8 +8,8 @@
 // Morever, this file will be used during the building of
 // gccgo's libgo and thus must not used a CGo method.
 
-// +build aix
-// +build gccgo
+//go:build aix && gccgo
+// +build aix,gccgo
 
 package cpu
 
index 5b427d67e2f7b7079fbec24115a90494d7d885b8..904be42ffdce1bc6d7351305cef046f14faa0543 100644 (file)
@@ -6,8 +6,8 @@
 // system call on AIX without depending on x/sys/unix.
 // (See golang.org/issue/32102)
 
-// +build aix,ppc64
-// +build gc
+//go:build aix && ppc64 && gc
+// +build aix,ppc64,gc
 
 package cpu
 
index e4c62289f90d41a1c41cf07491bc12963dccd8c3..8a7392c4a162fc46fae4ba0f332ff0ccf132c0e7 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build go1.10
 // +build go1.10
 
 package bidirule
index 02b9e1e9d4c27000937c72482dd72b29aacaa3bc..bb0a920018c8f1b52cdac1fb1fccef23edab20f7 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !go1.10
 // +build !go1.10
 
 package bidirule
index e8edc54cc28d20d9a2bb02a6a7310f87e8fe39ed..fd057601bd9178c5def359f002b06ef0769bd6f3 100644 (file)
 // and without notice.
 package bidi // import "golang.org/x/text/unicode/bidi"
 
-// TODO:
-// The following functionality would not be hard to implement, but hinges on
-// the definition of a Segmenter interface. For now this is up to the user.
-// - Iterate over paragraphs
-// - Segmenter to iterate over runs directly from a given text.
-// Also:
+// TODO
 // - Transformer for reordering?
 // - Transformer (validator, really) for Bidi Rule.
 
+import (
+       "bytes"
+)
+
 // This API tries to avoid dealing with embedding levels for now. Under the hood
 // these will be computed, but the question is to which extent the user should
 // know they exist. We should at some point allow the user to specify an
@@ -49,7 +48,9 @@ const (
        Neutral
 )
 
-type options struct{}
+type options struct {
+       defaultDirection Direction
+}
 
 // An Option is an option for Bidi processing.
 type Option func(*options)
@@ -66,12 +67,62 @@ type Option func(*options)
 // DefaultDirection sets the default direction for a Paragraph. The direction is
 // overridden if the text contains directional characters.
 func DefaultDirection(d Direction) Option {
-       panic("unimplemented")
+       return func(opts *options) {
+               opts.defaultDirection = d
+       }
 }
 
 // A Paragraph holds a single Paragraph for Bidi processing.
 type Paragraph struct {
-       // buffers
+       p          []byte
+       o          Ordering
+       opts       []Option
+       types      []Class
+       pairTypes  []bracketType
+       pairValues []rune
+       runes      []rune
+       options    options
+}
+
+// Initialize the p.pairTypes, p.pairValues and p.types from the input previously
+// set by p.SetBytes() or p.SetString(). Also limit the input up to (and including) a paragraph
+// separator (bidi class B).
+//
+// The function p.Order() needs these values to be set, so this preparation could be postponed.
+// But since the SetBytes and SetStrings functions return the length of the input up to the paragraph
+// separator, the whole input needs to be processed anyway and should not be done twice.
+//
+// The function has the same return values as SetBytes() / SetString()
+func (p *Paragraph) prepareInput() (n int, err error) {
+       p.runes = bytes.Runes(p.p)
+       bytecount := 0
+       // clear slices from previous SetString or SetBytes
+       p.pairTypes = nil
+       p.pairValues = nil
+       p.types = nil
+
+       for _, r := range p.runes {
+               props, i := LookupRune(r)
+               bytecount += i
+               cls := props.Class()
+               if cls == B {
+                       return bytecount, nil
+               }
+               p.types = append(p.types, cls)
+               if props.IsOpeningBracket() {
+                       p.pairTypes = append(p.pairTypes, bpOpen)
+                       p.pairValues = append(p.pairValues, r)
+               } else if props.IsBracket() {
+                       // this must be a closing bracket,
+                       // since IsOpeningBracket is not true
+                       p.pairTypes = append(p.pairTypes, bpClose)
+                       p.pairValues = append(p.pairValues, r)
+               } else {
+                       p.pairTypes = append(p.pairTypes, bpNone)
+                       p.pairValues = append(p.pairValues, 0)
+               }
+       }
+       return bytecount, nil
 }
 
 // SetBytes configures p for the given paragraph text. It replaces text
@@ -80,70 +131,150 @@ type Paragraph struct {
 // consumed from b including this separator. Error may be non-nil if options are
 // given.
 func (p *Paragraph) SetBytes(b []byte, opts ...Option) (n int, err error) {
-       panic("unimplemented")
+       p.p = b
+       p.opts = opts
+       return p.prepareInput()
 }
 
-// SetString configures p for the given paragraph text. It replaces text
-// previously set by SetBytes or SetString. If b contains a paragraph separator
+// SetString configures s for the given paragraph text. It replaces text
+// previously set by SetBytes or SetString. If s contains a paragraph separator
 // it will only process the first paragraph and report the number of bytes
-// consumed from b including this separator. Error may be non-nil if options are
+// consumed from s including this separator. Error may be non-nil if options are
 // given.
 func (p *Paragraph) SetString(s string, opts ...Option) (n int, err error) {
-       panic("unimplemented")
+       p.p = []byte(s)
+       p.opts = opts
+       return p.prepareInput()
 }
 
 // IsLeftToRight reports whether the principle direction of rendering for this
 // paragraphs is left-to-right. If this returns false, the principle direction
 // of rendering is right-to-left.
 func (p *Paragraph) IsLeftToRight() bool {
-       panic("unimplemented")
+       return p.Direction() == LeftToRight
 }
 
 // Direction returns the direction of the text of this paragraph.
 //
 // The direction may be LeftToRight, RightToLeft, Mixed, or Neutral.
 func (p *Paragraph) Direction() Direction {
-       panic("unimplemented")
+       return p.o.Direction()
 }
 
+// TODO: what happens if the position is > len(input)? This should return an error.
+
 // RunAt reports the Run at the given position of the input text.
 //
 // This method can be used for computing line breaks on paragraphs.
 func (p *Paragraph) RunAt(pos int) Run {
-       panic("unimplemented")
+       c := 0
+       runNumber := 0
+       for i, r := range p.o.runes {
+               c += len(r)
+               if pos < c {
+                       runNumber = i
+               }
+       }
+       return p.o.Run(runNumber)
+}
+
+func calculateOrdering(levels []level, runes []rune) Ordering {
+       var curDir Direction
+
+       prevDir := Neutral
+       prevI := 0
+
+       o := Ordering{}
+       // lvl = 0,2,4,...: left to right
+       // lvl = 1,3,5,...: right to left
+       for i, lvl := range levels {
+               if lvl%2 == 0 {
+                       curDir = LeftToRight
+               } else {
+                       curDir = RightToLeft
+               }
+               if curDir != prevDir {
+                       if i > 0 {
+                               o.runes = append(o.runes, runes[prevI:i])
+                               o.directions = append(o.directions, prevDir)
+                               o.startpos = append(o.startpos, prevI)
+                       }
+                       prevI = i
+                       prevDir = curDir
+               }
+       }
+       o.runes = append(o.runes, runes[prevI:])
+       o.directions = append(o.directions, prevDir)
+       o.startpos = append(o.startpos, prevI)
+       return o
 }
 
 // Order computes the visual ordering of all the runs in a Paragraph.
 func (p *Paragraph) Order() (Ordering, error) {
-       panic("unimplemented")
+       if len(p.types) == 0 {
+               return Ordering{}, nil
+       }
+
+       for _, fn := range p.opts {
+               fn(&p.options)
+       }
+       lvl := level(-1)
+       if p.options.defaultDirection == RightToLeft {
+               lvl = 1
+       }
+       para, err := newParagraph(p.types, p.pairTypes, p.pairValues, lvl)
+       if err != nil {
+               return Ordering{}, err
+       }
+
+       levels := para.getLevels([]int{len(p.types)})
+
+       p.o = calculateOrdering(levels, p.runes)
+       return p.o, nil
 }
 
 // Line computes the visual ordering of runs for a single line starting and
 // ending at the given positions in the original text.
 func (p *Paragraph) Line(start, end int) (Ordering, error) {
-       panic("unimplemented")
+       lineTypes := p.types[start:end]
+       para, err := newParagraph(lineTypes, p.pairTypes[start:end], p.pairValues[start:end], -1)
+       if err != nil {
+               return Ordering{}, err
+       }
+       levels := para.getLevels([]int{len(lineTypes)})
+       o := calculateOrdering(levels, p.runes[start:end])
+       return o, nil
 }
 
 // An Ordering holds the computed visual order of runs of a Paragraph. Calling
 // SetBytes or SetString on the originating Paragraph invalidates an Ordering.
 // The methods of an Ordering should only be called by one goroutine at a time.
-type Ordering struct{}
+type Ordering struct {
+       runes      [][]rune
+       directions []Direction
+       startpos   []int
+}
 
 // Direction reports the directionality of the runs.
 //
 // The direction may be LeftToRight, RightToLeft, Mixed, or Neutral.
 func (o *Ordering) Direction() Direction {
-       panic("unimplemented")
+       return o.directions[0]
 }
 
 // NumRuns returns the number of runs.
 func (o *Ordering) NumRuns() int {
-       panic("unimplemented")
+       return len(o.runes)
 }
 
 // Run returns the ith run within the ordering.
 func (o *Ordering) Run(i int) Run {
-       panic("unimplemented")
+       r := Run{
+               runes:     o.runes[i],
+               direction: o.directions[i],
+               startpos:  o.startpos[i],
+       }
+       return r
 }
 
 // TODO: perhaps with options.
@@ -155,16 +286,19 @@ func (o *Ordering) Run(i int) Run {
 
 // A Run is a continuous sequence of characters of a single direction.
 type Run struct {
+       runes     []rune
+       direction Direction
+       startpos  int
 }
 
 // String returns the text of the run in its original order.
 func (r *Run) String() string {
-       panic("unimplemented")
+       return string(r.runes)
 }
 
 // Bytes returns the text of the run in its original order.
 func (r *Run) Bytes() []byte {
-       panic("unimplemented")
+       return []byte(r.String())
 }
 
 // TODO: methods for
@@ -174,25 +308,52 @@ func (r *Run) Bytes() []byte {
 
 // Direction reports the direction of the run.
 func (r *Run) Direction() Direction {
-       panic("unimplemented")
+       return r.direction
 }
 
-// Position of the Run within the text passed to SetBytes or SetString of the
+// Pos returns the position of the Run within the text passed to SetBytes or SetString of the
 // originating Paragraph value.
 func (r *Run) Pos() (start, end int) {
-       panic("unimplemented")
+       return r.startpos, r.startpos + len(r.runes) - 1
 }
 
 // AppendReverse reverses the order of characters of in, appends them to out,
 // and returns the result. Modifiers will still follow the runes they modify.
 // Brackets are replaced with their counterparts.
 func AppendReverse(out, in []byte) []byte {
-       panic("unimplemented")
+       ret := make([]byte, len(in)+len(out))
+       copy(ret, out)
+       inRunes := bytes.Runes(in)
+
+       for i, r := range inRunes {
+               prop, _ := LookupRune(r)
+               if prop.IsBracket() {
+                       inRunes[i] = prop.reverseBracket(r)
+               }
+       }
+
+       for i, j := 0, len(inRunes)-1; i < j; i, j = i+1, j-1 {
+               inRunes[i], inRunes[j] = inRunes[j], inRunes[i]
+       }
+       copy(ret[len(out):], string(inRunes))
+
+       return ret
 }
 
 // ReverseString reverses the order of characters in s and returns a new string.
 // Modifiers will still follow the runes they modify. Brackets are replaced with
 // their counterparts.
 func ReverseString(s string) string {
-       panic("unimplemented")
+       input := []rune(s)
+       li := len(input)
+       ret := make([]rune, li)
+       for i, r := range input {
+               prop, _ := LookupRune(r)
+               if prop.IsBracket() {
+                       ret[li-i-1] = prop.reverseBracket(r)
+               } else {
+                       ret[li-i-1] = r
+               }
+       }
+       return string(ret)
 }
index 50deb6600a3c0c6b6149146bcb6c07703632c02e..e4c0811016c2acd3f54b0ec93d59f84f8cbba190 100644 (file)
@@ -4,7 +4,10 @@
 
 package bidi
 
-import "log"
+import (
+       "fmt"
+       "log"
+)
 
 // This implementation is a port based on the reference implementation found at:
 // https://www.unicode.org/Public/PROGRAMS/BidiReferenceJava/
@@ -97,13 +100,20 @@ type paragraph struct {
 // rune (suggested is the rune of the open bracket for opening and matching
 // close brackets, after normalization). The embedding levels are optional, but
 // may be supplied to encode embedding levels of styled text.
-//
-// TODO: return an error.
-func newParagraph(types []Class, pairTypes []bracketType, pairValues []rune, levels level) *paragraph {
-       validateTypes(types)
-       validatePbTypes(pairTypes)
-       validatePbValues(pairValues, pairTypes)
-       validateParagraphEmbeddingLevel(levels)
+func newParagraph(types []Class, pairTypes []bracketType, pairValues []rune, levels level) (*paragraph, error) {
+       var err error
+       if err = validateTypes(types); err != nil {
+               return nil, err
+       }
+       if err = validatePbTypes(pairTypes); err != nil {
+               return nil, err
+       }
+       if err = validatePbValues(pairValues, pairTypes); err != nil {
+               return nil, err
+       }
+       if err = validateParagraphEmbeddingLevel(levels); err != nil {
+               return nil, err
+       }
 
        p := &paragraph{
                initialTypes:   append([]Class(nil), types...),
@@ -115,7 +125,7 @@ func newParagraph(types []Class, pairTypes []bracketType, pairValues []rune, lev
                resultTypes: append([]Class(nil), types...),
        }
        p.run()
-       return p
+       return p, nil
 }
 
 func (p *paragraph) Len() int { return len(p.initialTypes) }
@@ -1001,58 +1011,61 @@ func typeForLevel(level level) Class {
        return R
 }
 
-// TODO: change validation to not panic
-
-func validateTypes(types []Class) {
+func validateTypes(types []Class) error {
        if len(types) == 0 {
-               log.Panic("types is null")
+               return fmt.Errorf("types is null")
        }
        for i, t := range types[:len(types)-1] {
                if t == B {
-                       log.Panicf("B type before end of paragraph at index: %d", i)
+                       return fmt.Errorf("B type before end of paragraph at index: %d", i)
                }
        }
+       return nil
 }
 
-func validateParagraphEmbeddingLevel(embeddingLevel level) {
+func validateParagraphEmbeddingLevel(embeddingLevel level) error {
        if embeddingLevel != implicitLevel &&
                embeddingLevel != 0 &&
                embeddingLevel != 1 {
-               log.Panicf("illegal paragraph embedding level: %d", embeddingLevel)
+               return fmt.Errorf("illegal paragraph embedding level: %d", embeddingLevel)
        }
+       return nil
 }
 
-func validateLineBreaks(linebreaks []int, textLength int) {
+func validateLineBreaks(linebreaks []int, textLength int) error {
        prev := 0
        for i, next := range linebreaks {
                if next <= prev {
-                       log.Panicf("bad linebreak: %d at index: %d", next, i)
+                       return fmt.Errorf("bad linebreak: %d at index: %d", next, i)
                }
                prev = next
        }
        if prev != textLength {
-               log.Panicf("last linebreak was %d, want %d", prev, textLength)
+               return fmt.Errorf("last linebreak was %d, want %d", prev, textLength)
        }
+       return nil
 }
 
-func validatePbTypes(pairTypes []bracketType) {
+func validatePbTypes(pairTypes []bracketType) error {
        if len(pairTypes) == 0 {
-               log.Panic("pairTypes is null")
+               return fmt.Errorf("pairTypes is null")
        }
        for i, pt := range pairTypes {
                switch pt {
                case bpNone, bpOpen, bpClose:
                default:
-                       log.Panicf("illegal pairType value at %d: %v", i, pairTypes[i])
+                       return fmt.Errorf("illegal pairType value at %d: %v", i, pairTypes[i])
                }
        }
+       return nil
 }
 
-func validatePbValues(pairValues []rune, pairTypes []bracketType) {
+func validatePbValues(pairValues []rune, pairTypes []bracketType) error {
        if pairValues == nil {
-               log.Panic("pairValues is null")
+               return fmt.Errorf("pairValues is null")
        }
        if len(pairTypes) != len(pairValues) {
-               log.Panic("pairTypes is different length from pairValues")
+               return fmt.Errorf("pairTypes is different length from pairValues")
        }
+       return nil
 }
index d8c94e1bd1a651c78c2175360d53530b9fc80128..42fa8d72cec004940ea8e126979a4e5ee09c7ee5 100644 (file)
@@ -1,5 +1,6 @@
 // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
 
+//go:build go1.10 && !go1.13
 // +build go1.10,!go1.13
 
 package bidi
index 16b11db53883871fcb640e11c0ab7c46dde67d94..56a0e1ea2165e4cc8f087abd53953e849f140dd0 100644 (file)
@@ -1,5 +1,6 @@
 // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
 
+//go:build go1.13 && !go1.14
 // +build go1.13,!go1.14
 
 package bidi
index 647f2d4279e6d917c028dd6c98f911ec7adb4fe2..baacf32b43c310593f1c176f9b4619a2007e826d 100644 (file)
@@ -1,5 +1,6 @@
 // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
 
+//go:build go1.14 && !go1.16
 // +build go1.14,!go1.16
 
 package bidi
index c937d0976febb45a93fa048391aeef872e27e0bc..f248effae17b18ec90a15d5344726176317db914 100644 (file)
@@ -1,5 +1,6 @@
 // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
 
+//go:build go1.16
 // +build go1.16
 
 package bidi
index 0ca0193ebe2d6192c56356d7bb723aa7d794fee0..f517fdb202a5cfb6e57fa527fb7270c27b6c095a 100644 (file)
@@ -1,5 +1,6 @@
 // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
 
+//go:build !go1.10
 // +build !go1.10
 
 package bidi
index 26fbd55a1243df8b03f820542f0939b6a3d291d1..f5a0788277ffd15f6b820905e3cca0f89746049e 100644 (file)
@@ -1,5 +1,6 @@
 // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
 
+//go:build go1.10 && !go1.13
 // +build go1.10,!go1.13
 
 package norm
index 2c58f09baa495fc59e99c18f95bfd712dc445c0a..cb7239c4377d47eb325ad8443b66384526e0ffd1 100644 (file)
@@ -1,5 +1,6 @@
 // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
 
+//go:build go1.13 && !go1.14
 // +build go1.13,!go1.14
 
 package norm
index 7e1ae096e5c00b890237ac84a7ca778b0ecea585..11b27330017d823b3971c6bbba612b106283e0a1 100644 (file)
@@ -1,5 +1,6 @@
 // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
 
+//go:build go1.14 && !go1.16
 // +build go1.14,!go1.16
 
 package norm
index 9ea1b421407d55d5a207b022a49402bc1924ce18..96a130d30e9e2085a6ec6fbeb99c699b31070d50 100644 (file)
@@ -1,5 +1,6 @@
 // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
 
+//go:build go1.16
 // +build go1.16
 
 package norm
index 942906929135c9665c7ec0d5f7524e37f7ea4ad9..0175eae50aa68e064d309cfef981dab0e7daec96 100644 (file)
@@ -1,5 +1,6 @@
 // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
 
+//go:build !go1.10
 // +build !go1.10
 
 package norm
diff --git a/libgo/go/golang.org/x/tools/cover/profile.go b/libgo/go/golang.org/x/tools/cover/profile.go
new file mode 100644 (file)
index 0000000..5719577
--- /dev/null
@@ -0,0 +1,261 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package cover provides support for parsing coverage profiles
+// generated by "go test -coverprofile=cover.out".
+package cover // import "golang.org/x/tools/cover"
+
+import (
+       "bufio"
+       "errors"
+       "fmt"
+       "math"
+       "os"
+       "sort"
+       "strconv"
+       "strings"
+)
+
+// Profile represents the profiling data for a specific file.
+type Profile struct {
+       FileName string
+       Mode     string
+       Blocks   []ProfileBlock
+}
+
+// ProfileBlock represents a single block of profiling data.
+type ProfileBlock struct {
+       StartLine, StartCol int
+       EndLine, EndCol     int
+       NumStmt, Count      int
+}
+
+type byFileName []*Profile
+
+func (p byFileName) Len() int           { return len(p) }
+func (p byFileName) Less(i, j int) bool { return p[i].FileName < p[j].FileName }
+func (p byFileName) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
+
+// ParseProfiles parses profile data in the specified file and returns a
+// Profile for each source file described therein.
+func ParseProfiles(fileName string) ([]*Profile, error) {
+       pf, err := os.Open(fileName)
+       if err != nil {
+               return nil, err
+       }
+       defer pf.Close()
+
+       files := make(map[string]*Profile)
+       buf := bufio.NewReader(pf)
+       // First line is "mode: foo", where foo is "set", "count", or "atomic".
+       // Rest of file is in the format
+       //      encoding/base64/base64.go:34.44,37.40 3 1
+       // where the fields are: name.go:line.column,line.column numberOfStatements count
+       s := bufio.NewScanner(buf)
+       mode := ""
+       for s.Scan() {
+               line := s.Text()
+               if mode == "" {
+                       const p = "mode: "
+                       if !strings.HasPrefix(line, p) || line == p {
+                               return nil, fmt.Errorf("bad mode line: %v", line)
+                       }
+                       mode = line[len(p):]
+                       continue
+               }
+               fn, b, err := parseLine(line)
+               if err != nil {
+                       return nil, fmt.Errorf("line %q doesn't match expected format: %v", line, err)
+               }
+               p := files[fn]
+               if p == nil {
+                       p = &Profile{
+                               FileName: fn,
+                               Mode:     mode,
+                       }
+                       files[fn] = p
+               }
+               p.Blocks = append(p.Blocks, b)
+       }
+       if err := s.Err(); err != nil {
+               return nil, err
+       }
+       for _, p := range files {
+               sort.Sort(blocksByStart(p.Blocks))
+               // Merge samples from the same location.
+               j := 1
+               for i := 1; i < len(p.Blocks); i++ {
+                       b := p.Blocks[i]
+                       last := p.Blocks[j-1]
+                       if b.StartLine == last.StartLine &&
+                               b.StartCol == last.StartCol &&
+                               b.EndLine == last.EndLine &&
+                               b.EndCol == last.EndCol {
+                               if b.NumStmt != last.NumStmt {
+                                       return nil, fmt.Errorf("inconsistent NumStmt: changed from %d to %d", last.NumStmt, b.NumStmt)
+                               }
+                               if mode == "set" {
+                                       p.Blocks[j-1].Count |= b.Count
+                               } else {
+                                       p.Blocks[j-1].Count += b.Count
+                               }
+                               continue
+                       }
+                       p.Blocks[j] = b
+                       j++
+               }
+               p.Blocks = p.Blocks[:j]
+       }
+       // Generate a sorted slice.
+       profiles := make([]*Profile, 0, len(files))
+       for _, profile := range files {
+               profiles = append(profiles, profile)
+       }
+       sort.Sort(byFileName(profiles))
+       return profiles, nil
+}
+
+// parseLine parses a line from a coverage file.
+// It is equivalent to the regex
+// ^(.+):([0-9]+)\.([0-9]+),([0-9]+)\.([0-9]+) ([0-9]+) ([0-9]+)$
+//
+// However, it is much faster: https://golang.org/cl/179377
+func parseLine(l string) (fileName string, block ProfileBlock, err error) {
+       end := len(l)
+
+       b := ProfileBlock{}
+       b.Count, end, err = seekBack(l, ' ', end, "Count")
+       if err != nil {
+               return "", b, err
+       }
+       b.NumStmt, end, err = seekBack(l, ' ', end, "NumStmt")
+       if err != nil {
+               return "", b, err
+       }
+       b.EndCol, end, err = seekBack(l, '.', end, "EndCol")
+       if err != nil {
+               return "", b, err
+       }
+       b.EndLine, end, err = seekBack(l, ',', end, "EndLine")
+       if err != nil {
+               return "", b, err
+       }
+       b.StartCol, end, err = seekBack(l, '.', end, "StartCol")
+       if err != nil {
+               return "", b, err
+       }
+       b.StartLine, end, err = seekBack(l, ':', end, "StartLine")
+       if err != nil {
+               return "", b, err
+       }
+       fn := l[0:end]
+       if fn == "" {
+               return "", b, errors.New("a FileName cannot be blank")
+       }
+       return fn, b, nil
+}
+
+// seekBack searches backwards from end to find sep in l, then returns the
+// value between sep and end as an integer.
+// If seekBack fails, the returned error will reference what.
+func seekBack(l string, sep byte, end int, what string) (value int, nextSep int, err error) {
+       // Since we're seeking backwards and we know only ASCII is legal for these values,
+       // we can ignore the possibility of non-ASCII characters.
+       for start := end - 1; start >= 0; start-- {
+               if l[start] == sep {
+                       i, err := strconv.Atoi(l[start+1 : end])
+                       if err != nil {
+                               return 0, 0, fmt.Errorf("couldn't parse %q: %v", what, err)
+                       }
+                       if i < 0 {
+                               return 0, 0, fmt.Errorf("negative values are not allowed for %s, found %d", what, i)
+                       }
+                       return i, start, nil
+               }
+       }
+       return 0, 0, fmt.Errorf("couldn't find a %s before %s", string(sep), what)
+}
+
+type blocksByStart []ProfileBlock
+
+func (b blocksByStart) Len() int      { return len(b) }
+func (b blocksByStart) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
+func (b blocksByStart) Less(i, j int) bool {
+       bi, bj := b[i], b[j]
+       return bi.StartLine < bj.StartLine || bi.StartLine == bj.StartLine && bi.StartCol < bj.StartCol
+}
+
+// Boundary represents the position in a source file of the beginning or end of a
+// block as reported by the coverage profile. In HTML mode, it will correspond to
+// the opening or closing of a <span> tag and will be used to colorize the source
+type Boundary struct {
+       Offset int     // Location as a byte offset in the source file.
+       Start  bool    // Is this the start of a block?
+       Count  int     // Event count from the cover profile.
+       Norm   float64 // Count normalized to [0..1].
+       Index  int     // Order in input file.
+}
+
+// Boundaries returns a Profile as a set of Boundary objects within the provided src.
+func (p *Profile) Boundaries(src []byte) (boundaries []Boundary) {
+       // Find maximum count.
+       max := 0
+       for _, b := range p.Blocks {
+               if b.Count > max {
+                       max = b.Count
+               }
+       }
+       // Divisor for normalization.
+       divisor := math.Log(float64(max))
+
+       // boundary returns a Boundary, populating the Norm field with a normalized Count.
+       index := 0
+       boundary := func(offset int, start bool, count int) Boundary {
+               b := Boundary{Offset: offset, Start: start, Count: count, Index: index}
+               index++
+               if !start || count == 0 {
+                       return b
+               }
+               if max <= 1 {
+                       b.Norm = 0.8 // Profile is in"set" mode; we want a heat map. Use cov8 in the CSS.
+               } else if count > 0 {
+                       b.Norm = math.Log(float64(count)) / divisor
+               }
+               return b
+       }
+
+       line, col := 1, 2 // TODO: Why is this 2?
+       for si, bi := 0, 0; si < len(src) && bi < len(p.Blocks); {
+               b := p.Blocks[bi]
+               if b.StartLine == line && b.StartCol == col {
+                       boundaries = append(boundaries, boundary(si, true, b.Count))
+               }
+               if b.EndLine == line && b.EndCol == col || line > b.EndLine {
+                       boundaries = append(boundaries, boundary(si, false, 0))
+                       bi++
+                       continue // Don't advance through src; maybe the next block starts here.
+               }
+               if src[si] == '\n' {
+                       line++
+                       col = 0
+               }
+               col++
+               si++
+       }
+       sort.Sort(boundariesByPos(boundaries))
+       return
+}
+
+type boundariesByPos []Boundary
+
+func (b boundariesByPos) Len() int      { return len(b) }
+func (b boundariesByPos) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
+func (b boundariesByPos) Less(i, j int) bool {
+       if b[i].Offset == b[j].Offset {
+               // Boundaries at the same offset should be ordered according to
+               // their original position.
+               return b[i].Index < b[j].Index
+       }
+       return b[i].Offset < b[j].Offset
+}
index 841b928578440879fc4111d08373bd9759e6f203..c4407ad91fe425d4546b5a1d9fcc9b32392261d3 100644 (file)
@@ -2,14 +2,17 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build go1.16
+// +build go1.16
+
 // Package buildtag defines an Analyzer that checks build tags.
 package buildtag
 
 import (
-       "bytes"
-       "fmt"
        "go/ast"
+       "go/build/constraint"
        "go/parser"
+       "go/token"
        "strings"
        "unicode"
 
@@ -52,118 +55,313 @@ func runBuildTag(pass *analysis.Pass) (interface{}, error) {
 }
 
 func checkGoFile(pass *analysis.Pass, f *ast.File) {
-       pastCutoff := false
+       var check checker
+       check.init(pass)
+       defer check.finish()
+
        for _, group := range f.Comments {
                // A +build comment is ignored after or adjoining the package declaration.
                if group.End()+1 >= f.Package {
-                       pastCutoff = true
+                       check.plusBuildOK = false
                }
-
-               // "+build" is ignored within or after a /*...*/ comment.
-               if !strings.HasPrefix(group.List[0].Text, "//") {
-                       pastCutoff = true
-                       continue
+               // A //go:build comment is ignored after the package declaration
+               // (but adjoining it is OK, in contrast to +build comments).
+               if group.Pos() >= f.Package {
+                       check.goBuildOK = false
                }
 
                // Check each line of a //-comment.
                for _, c := range group.List {
-                       if !strings.Contains(c.Text, "+build") {
-                               continue
-                       }
-                       if err := checkLine(c.Text, pastCutoff); err != nil {
-                               pass.Reportf(c.Pos(), "%s", err)
+                       // "+build" is ignored within or after a /*...*/ comment.
+                       if !strings.HasPrefix(c.Text, "//") {
+                               check.plusBuildOK = false
                        }
+                       check.comment(c.Slash, c.Text)
                }
        }
 }
 
 func checkOtherFile(pass *analysis.Pass, filename string) error {
+       var check checker
+       check.init(pass)
+       defer check.finish()
+
+       // We cannot use the Go parser, since this may not be a Go source file.
+       // Read the raw bytes instead.
        content, tf, err := analysisutil.ReadFile(pass.Fset, filename)
        if err != nil {
                return err
        }
 
-       // We must look at the raw lines, as build tags may appear in non-Go
-       // files such as assembly files.
-       lines := bytes.SplitAfter(content, nl)
+       check.file(token.Pos(tf.Base()), string(content))
+       return nil
+}
+
+type checker struct {
+       pass         *analysis.Pass
+       plusBuildOK  bool            // "+build" lines still OK
+       goBuildOK    bool            // "go:build" lines still OK
+       crossCheck   bool            // cross-check go:build and +build lines when done reading file
+       inStar       bool            // currently in a /* */ comment
+       goBuildPos   token.Pos       // position of first go:build line found
+       plusBuildPos token.Pos       // position of first "+build" line found
+       goBuild      constraint.Expr // go:build constraint found
+       plusBuild    constraint.Expr // AND of +build constraints found
+}
+
+func (check *checker) init(pass *analysis.Pass) {
+       check.pass = pass
+       check.goBuildOK = true
+       check.plusBuildOK = true
+       check.crossCheck = true
+}
 
+func (check *checker) file(pos token.Pos, text string) {
        // Determine cutpoint where +build comments are no longer valid.
        // They are valid in leading // comments in the file followed by
        // a blank line.
        //
        // This must be done as a separate pass because of the
        // requirement that the comment be followed by a blank line.
-       var cutoff int
-       for i, line := range lines {
-               line = bytes.TrimSpace(line)
-               if !bytes.HasPrefix(line, slashSlash) {
-                       if len(line) > 0 {
-                               break
-                       }
-                       cutoff = i
+       var plusBuildCutoff int
+       fullText := text
+       for text != "" {
+               i := strings.Index(text, "\n")
+               if i < 0 {
+                       i = len(text)
+               } else {
+                       i++
+               }
+               offset := len(fullText) - len(text)
+               line := text[:i]
+               text = text[i:]
+               line = strings.TrimSpace(line)
+               if !strings.HasPrefix(line, "//") && line != "" {
+                       break
+               }
+               if line == "" {
+                       plusBuildCutoff = offset
                }
        }
 
-       for i, line := range lines {
-               line = bytes.TrimSpace(line)
-               if !bytes.HasPrefix(line, slashSlash) {
-                       continue
+       // Process each line.
+       // Must stop once we hit goBuildOK == false
+       text = fullText
+       check.inStar = false
+       for text != "" {
+               i := strings.Index(text, "\n")
+               if i < 0 {
+                       i = len(text)
+               } else {
+                       i++
                }
-               if !bytes.Contains(line, []byte("+build")) {
+               offset := len(fullText) - len(text)
+               line := text[:i]
+               text = text[i:]
+               check.plusBuildOK = offset < plusBuildCutoff
+
+               if strings.HasPrefix(line, "//") {
+                       check.comment(pos+token.Pos(offset), line)
                        continue
                }
-               if err := checkLine(string(line), i >= cutoff); err != nil {
-                       pass.Reportf(analysisutil.LineStart(tf, i+1), "%s", err)
-                       continue
+
+               // Keep looking for the point at which //go:build comments
+               // stop being allowed. Skip over, cut out any /* */ comments.
+               for {
+                       line = strings.TrimSpace(line)
+                       if check.inStar {
+                               i := strings.Index(line, "*/")
+                               if i < 0 {
+                                       line = ""
+                                       break
+                               }
+                               line = line[i+len("*/"):]
+                               check.inStar = false
+                               continue
+                       }
+                       if strings.HasPrefix(line, "/*") {
+                               check.inStar = true
+                               line = line[len("/*"):]
+                               continue
+                       }
+                       break
+               }
+               if line != "" {
+                       // Found non-comment non-blank line.
+                       // Ends space for valid //go:build comments,
+                       // but also ends the fraction of the file we can
+                       // reliably parse. From this point on we might
+                       // incorrectly flag "comments" inside multiline
+                       // string constants or anything else (this might
+                       // not even be a Go program). So stop.
+                       break
                }
        }
-       return nil
 }
 
-// checkLine checks a line that starts with "//" and contains "+build".
-func checkLine(line string, pastCutoff bool) error {
-       line = strings.TrimPrefix(line, "//")
-       line = strings.TrimSpace(line)
-
-       if strings.HasPrefix(line, "+build") {
-               fields := strings.Fields(line)
-               if fields[0] != "+build" {
-                       // Comment is something like +buildasdf not +build.
-                       return fmt.Errorf("possible malformed +build comment")
+func (check *checker) comment(pos token.Pos, text string) {
+       if strings.HasPrefix(text, "//") {
+               if strings.Contains(text, "+build") {
+                       check.plusBuildLine(pos, text)
                }
-               if pastCutoff {
-                       return fmt.Errorf("+build comment must appear before package clause and be followed by a blank line")
+               if strings.Contains(text, "//go:build") {
+                       check.goBuildLine(pos, text)
                }
-               if err := checkArguments(fields); err != nil {
-                       return err
+       }
+       if strings.HasPrefix(text, "/*") {
+               if i := strings.Index(text, "\n"); i >= 0 {
+                       // multiline /* */ comment - process interior lines
+                       check.inStar = true
+                       i++
+                       pos += token.Pos(i)
+                       text = text[i:]
+                       for text != "" {
+                               i := strings.Index(text, "\n")
+                               if i < 0 {
+                                       i = len(text)
+                               } else {
+                                       i++
+                               }
+                               line := text[:i]
+                               if strings.HasPrefix(line, "//") {
+                                       check.comment(pos, line)
+                               }
+                               pos += token.Pos(i)
+                               text = text[i:]
+                       }
+                       check.inStar = false
+               }
+       }
+}
+
+func (check *checker) goBuildLine(pos token.Pos, line string) {
+       if !constraint.IsGoBuild(line) {
+               if !strings.HasPrefix(line, "//go:build") && constraint.IsGoBuild("//"+strings.TrimSpace(line[len("//"):])) {
+                       check.pass.Reportf(pos, "malformed //go:build line (space between // and go:build)")
                }
+               return
+       }
+       if !check.goBuildOK || check.inStar {
+               check.pass.Reportf(pos, "misplaced //go:build comment")
+               check.crossCheck = false
+               return
+       }
+
+       if check.goBuildPos == token.NoPos {
+               check.goBuildPos = pos
        } else {
+               check.pass.Reportf(pos, "unexpected extra //go:build line")
+               check.crossCheck = false
+       }
+
+       // testing hack: stop at // ERROR
+       if i := strings.Index(line, " // ERROR "); i >= 0 {
+               line = line[:i]
+       }
+
+       x, err := constraint.Parse(line)
+       if err != nil {
+               check.pass.Reportf(pos, "%v", err)
+               check.crossCheck = false
+               return
+       }
+
+       if check.goBuild == nil {
+               check.goBuild = x
+       }
+}
+
+func (check *checker) plusBuildLine(pos token.Pos, line string) {
+       line = strings.TrimSpace(line)
+       if !constraint.IsPlusBuild(line) {
                // Comment with +build but not at beginning.
-               if !pastCutoff {
-                       return fmt.Errorf("possible malformed +build comment")
+               // Only report early in file.
+               if check.plusBuildOK && !strings.HasPrefix(line, "// want") {
+                       check.pass.Reportf(pos, "possible malformed +build comment")
                }
+               return
+       }
+       if !check.plusBuildOK { // inStar implies !plusBuildOK
+               check.pass.Reportf(pos, "misplaced +build comment")
+               check.crossCheck = false
        }
-       return nil
-}
 
-func checkArguments(fields []string) error {
+       if check.plusBuildPos == token.NoPos {
+               check.plusBuildPos = pos
+       }
+
+       // testing hack: stop at // ERROR
+       if i := strings.Index(line, " // ERROR "); i >= 0 {
+               line = line[:i]
+       }
+
+       fields := strings.Fields(line[len("//"):])
+       // IsPlusBuildConstraint check above implies fields[0] == "+build"
        for _, arg := range fields[1:] {
                for _, elem := range strings.Split(arg, ",") {
                        if strings.HasPrefix(elem, "!!") {
-                               return fmt.Errorf("invalid double negative in build constraint: %s", arg)
+                               check.pass.Reportf(pos, "invalid double negative in build constraint: %s", arg)
+                               check.crossCheck = false
+                               continue
                        }
                        elem = strings.TrimPrefix(elem, "!")
                        for _, c := range elem {
                                if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' {
-                                       return fmt.Errorf("invalid non-alphanumeric build constraint: %s", arg)
+                                       check.pass.Reportf(pos, "invalid non-alphanumeric build constraint: %s", arg)
+                                       check.crossCheck = false
+                                       break
                                }
                        }
                }
        }
-       return nil
+
+       if check.crossCheck {
+               y, err := constraint.Parse(line)
+               if err != nil {
+                       // Should never happen - constraint.Parse never rejects a // +build line.
+                       // Also, we just checked the syntax above.
+                       // Even so, report.
+                       check.pass.Reportf(pos, "%v", err)
+                       check.crossCheck = false
+                       return
+               }
+               if check.plusBuild == nil {
+                       check.plusBuild = y
+               } else {
+                       check.plusBuild = &constraint.AndExpr{X: check.plusBuild, Y: y}
+               }
+       }
 }
 
-var (
-       nl         = []byte("\n")
-       slashSlash = []byte("//")
-)
+func (check *checker) finish() {
+       if !check.crossCheck || check.plusBuildPos == token.NoPos || check.goBuildPos == token.NoPos {
+               return
+       }
+
+       // Have both //go:build and // +build,
+       // with no errors found (crossCheck still true).
+       // Check they match.
+       var want constraint.Expr
+       lines, err := constraint.PlusBuildLines(check.goBuild)
+       if err != nil {
+               check.pass.Reportf(check.goBuildPos, "%v", err)
+               return
+       }
+       for _, line := range lines {
+               y, err := constraint.Parse(line)
+               if err != nil {
+                       // Definitely should not happen, but not the user's fault.
+                       // Do not report.
+                       return
+               }
+               if want == nil {
+                       want = y
+               } else {
+                       want = &constraint.AndExpr{X: want, Y: y}
+               }
+       }
+       if want.String() != check.plusBuild.String() {
+               check.pass.Reportf(check.plusBuildPos, "+build lines do not match //go:build condition")
+               return
+       }
+}
diff --git a/libgo/go/golang.org/x/tools/go/analysis/passes/buildtag/buildtag_old.go b/libgo/go/golang.org/x/tools/go/analysis/passes/buildtag/buildtag_old.go
new file mode 100644 (file)
index 0000000..e923492
--- /dev/null
@@ -0,0 +1,174 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// TODO(rsc): Delete this file once Go 1.17 comes out and we can retire Go 1.15 support.
+
+//go:build !go1.16
+// +build !go1.16
+
+// Package buildtag defines an Analyzer that checks build tags.
+package buildtag
+
+import (
+       "bytes"
+       "fmt"
+       "go/ast"
+       "go/parser"
+       "strings"
+       "unicode"
+
+       "golang.org/x/tools/go/analysis"
+       "golang.org/x/tools/go/analysis/passes/internal/analysisutil"
+)
+
+const Doc = "check that +build tags are well-formed and correctly located"
+
+var Analyzer = &analysis.Analyzer{
+       Name: "buildtag",
+       Doc:  Doc,
+       Run:  runBuildTag,
+}
+
+func runBuildTag(pass *analysis.Pass) (interface{}, error) {
+       for _, f := range pass.Files {
+               checkGoFile(pass, f)
+       }
+       for _, name := range pass.OtherFiles {
+               if err := checkOtherFile(pass, name); err != nil {
+                       return nil, err
+               }
+       }
+       for _, name := range pass.IgnoredFiles {
+               if strings.HasSuffix(name, ".go") {
+                       f, err := parser.ParseFile(pass.Fset, name, nil, parser.ParseComments)
+                       if err != nil {
+                               // Not valid Go source code - not our job to diagnose, so ignore.
+                               return nil, nil
+                       }
+                       checkGoFile(pass, f)
+               } else {
+                       if err := checkOtherFile(pass, name); err != nil {
+                               return nil, err
+                       }
+               }
+       }
+       return nil, nil
+}
+
+func checkGoFile(pass *analysis.Pass, f *ast.File) {
+       pastCutoff := false
+       for _, group := range f.Comments {
+               // A +build comment is ignored after or adjoining the package declaration.
+               if group.End()+1 >= f.Package {
+                       pastCutoff = true
+               }
+
+               // "+build" is ignored within or after a /*...*/ comment.
+               if !strings.HasPrefix(group.List[0].Text, "//") {
+                       pastCutoff = true
+                       continue
+               }
+
+               // Check each line of a //-comment.
+               for _, c := range group.List {
+                       if !strings.Contains(c.Text, "+build") {
+                               continue
+                       }
+                       if err := checkLine(c.Text, pastCutoff); err != nil {
+                               pass.Reportf(c.Pos(), "%s", err)
+                       }
+               }
+       }
+}
+
+func checkOtherFile(pass *analysis.Pass, filename string) error {
+       content, tf, err := analysisutil.ReadFile(pass.Fset, filename)
+       if err != nil {
+               return err
+       }
+
+       // We must look at the raw lines, as build tags may appear in non-Go
+       // files such as assembly files.
+       lines := bytes.SplitAfter(content, nl)
+
+       // Determine cutpoint where +build comments are no longer valid.
+       // They are valid in leading // comments in the file followed by
+       // a blank line.
+       //
+       // This must be done as a separate pass because of the
+       // requirement that the comment be followed by a blank line.
+       var cutoff int
+       for i, line := range lines {
+               line = bytes.TrimSpace(line)
+               if !bytes.HasPrefix(line, slashSlash) {
+                       if len(line) > 0 {
+                               break
+                       }
+                       cutoff = i
+               }
+       }
+
+       for i, line := range lines {
+               line = bytes.TrimSpace(line)
+               if !bytes.HasPrefix(line, slashSlash) {
+                       continue
+               }
+               if !bytes.Contains(line, []byte("+build")) {
+                       continue
+               }
+               if err := checkLine(string(line), i >= cutoff); err != nil {
+                       pass.Reportf(analysisutil.LineStart(tf, i+1), "%s", err)
+                       continue
+               }
+       }
+       return nil
+}
+
+// checkLine checks a line that starts with "//" and contains "+build".
+func checkLine(line string, pastCutoff bool) error {
+       line = strings.TrimPrefix(line, "//")
+       line = strings.TrimSpace(line)
+
+       if strings.HasPrefix(line, "+build") {
+               fields := strings.Fields(line)
+               if fields[0] != "+build" {
+                       // Comment is something like +buildasdf not +build.
+                       return fmt.Errorf("possible malformed +build comment")
+               }
+               if pastCutoff {
+                       return fmt.Errorf("+build comment must appear before package clause and be followed by a blank line")
+               }
+               if err := checkArguments(fields); err != nil {
+                       return err
+               }
+       } else {
+               // Comment with +build but not at beginning.
+               if !pastCutoff {
+                       return fmt.Errorf("possible malformed +build comment")
+               }
+       }
+       return nil
+}
+
+func checkArguments(fields []string) error {
+       for _, arg := range fields[1:] {
+               for _, elem := range strings.Split(arg, ",") {
+                       if strings.HasPrefix(elem, "!!") {
+                               return fmt.Errorf("invalid double negative in build constraint: %s", arg)
+                       }
+                       elem = strings.TrimPrefix(elem, "!")
+                       for _, c := range elem {
+                               if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' {
+                                       return fmt.Errorf("invalid non-alphanumeric build constraint: %s", arg)
+                               }
+                       }
+               }
+       }
+       return nil
+}
+
+var (
+       nl         = []byte("\n")
+       slashSlash = []byte("//")
+)
index 2856df137c562f01a225ca7553ae7a1a88c264e5..4bb652a726c8978da2a4907f0f30577948c0eb04 100644 (file)
@@ -3,8 +3,8 @@
 // license that can be found in the LICENSE file.
 
 // Package inspect defines an Analyzer that provides an AST inspector
-// (golang.org/x/tools/go/ast/inspect.Inspect) for the syntax trees of a
-// package. It is only a building block for other analyzers.
+// (golang.org/x/tools/go/ast/inspector.Inspector) for the syntax trees
+// of a package. It is only a building block for other analyzers.
 //
 // Example of use in another analysis:
 //
index a14e7eb55d0abf0a2caf2aa3255a05a307a4cbb1..3ea91574dc8385bd67073580bdca940831dec089 100644 (file)
@@ -8,22 +8,14 @@ package loopclosure
 
 import (
        "go/ast"
+       "go/types"
 
        "golang.org/x/tools/go/analysis"
        "golang.org/x/tools/go/analysis/passes/inspect"
        "golang.org/x/tools/go/ast/inspector"
+       "golang.org/x/tools/go/types/typeutil"
 )
 
-// TODO(adonovan): also report an error for the following structure,
-// which is often used to ensure that deferred calls do not accumulate
-// in a loop:
-//
-//     for i, x := range c {
-//             func() {
-//                     ...reference to i or x...
-//             }()
-//     }
-
 const Doc = `check references to loop variables from within nested functions
 
 This analyzer checks for references to loop variables from within a
@@ -95,16 +87,19 @@ func run(pass *analysis.Pass) (interface{}, error) {
                if len(body.List) == 0 {
                        return
                }
-               var last *ast.CallExpr
+               // The function invoked in the last return statement.
+               var fun ast.Expr
                switch s := body.List[len(body.List)-1].(type) {
                case *ast.GoStmt:
-                       last = s.Call
+                       fun = s.Call.Fun
                case *ast.DeferStmt:
-                       last = s.Call
-               default:
-                       return
+                       fun = s.Call.Fun
+               case *ast.ExprStmt: // check for errgroup.Group.Go()
+                       if call, ok := s.X.(*ast.CallExpr); ok {
+                               fun = goInvokes(pass.TypesInfo, call)
+                       }
                }
-               lit, ok := last.Fun.(*ast.FuncLit)
+               lit, ok := fun.(*ast.FuncLit)
                if !ok {
                        return
                }
@@ -128,3 +123,43 @@ func run(pass *analysis.Pass) (interface{}, error) {
        })
        return nil, nil
 }
+
+// goInvokes returns a function expression that would be called asynchronously
+// (but not awaited) in another goroutine as a consequence of the call.
+// For example, given the g.Go call below, it returns the function literal expression.
+//
+//   import "sync/errgroup"
+//   var g errgroup.Group
+//   g.Go(func() error { ... })
+//
+// Currently only "golang.org/x/sync/errgroup.Group()" is considered.
+func goInvokes(info *types.Info, call *ast.CallExpr) ast.Expr {
+       f := typeutil.StaticCallee(info, call)
+       // Note: Currently only supports: golang.org/x/sync/errgroup.Go.
+       if f == nil || f.Name() != "Go" {
+               return nil
+       }
+       recv := f.Type().(*types.Signature).Recv()
+       if recv == nil {
+               return nil
+       }
+       rtype, ok := recv.Type().(*types.Pointer)
+       if !ok {
+               return nil
+       }
+       named, ok := rtype.Elem().(*types.Named)
+       if !ok {
+               return nil
+       }
+       if named.Obj().Name() != "Group" {
+               return nil
+       }
+       pkg := f.Pkg()
+       if pkg == nil {
+               return nil
+       }
+       if pkg.Path() != "golang.org/x/sync/errgroup" {
+               return nil
+       }
+       return call.Args[0]
+}
index ddad4c796cbcbe83008aa611ea666a67bb463ea4..822820f06e9bef9e6872cf713f1d6690f0a93e5f 100644 (file)
@@ -590,7 +590,7 @@ func checkPrintf(pass *analysis.Pass, kind Kind, call *ast.CallExpr, fn *types.F
                }
                if state.verb == 'w' {
                        if kind != KindErrorf {
-                               pass.Reportf(call.Pos(), "%s call has error-wrapping directive %%w", state.name)
+                               pass.Reportf(call.Pos(), "%s call has error-wrapping directive %%w, which is only supported by Errorf", state.name)
                                return
                        }
                        if anyW {
diff --git a/libgo/go/golang.org/x/tools/go/analysis/passes/sigchanyzer/sigchanyzer.go b/libgo/go/golang.org/x/tools/go/analysis/passes/sigchanyzer/sigchanyzer.go
new file mode 100644 (file)
index 0000000..0d6c8eb
--- /dev/null
@@ -0,0 +1,154 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package sigchanyzer defines an Analyzer that detects
+// misuse of unbuffered signal as argument to signal.Notify.
+package sigchanyzer
+
+import (
+       "bytes"
+       "go/ast"
+       "go/format"
+       "go/token"
+       "go/types"
+
+       "golang.org/x/tools/go/analysis"
+       "golang.org/x/tools/go/analysis/passes/inspect"
+       "golang.org/x/tools/go/ast/inspector"
+)
+
+const Doc = `check for unbuffered channel of os.Signal
+
+This checker reports call expression of the form signal.Notify(c <-chan os.Signal, sig ...os.Signal),
+where c is an unbuffered channel, which can be at risk of missing the signal.`
+
+// Analyzer describes sigchanyzer analysis function detector.
+var Analyzer = &analysis.Analyzer{
+       Name:     "sigchanyzer",
+       Doc:      Doc,
+       Requires: []*analysis.Analyzer{inspect.Analyzer},
+       Run:      run,
+}
+
+func run(pass *analysis.Pass) (interface{}, error) {
+       inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
+
+       nodeFilter := []ast.Node{
+               (*ast.CallExpr)(nil),
+       }
+       inspect.Preorder(nodeFilter, func(n ast.Node) {
+               call := n.(*ast.CallExpr)
+               if !isSignalNotify(pass.TypesInfo, call) {
+                       return
+               }
+               var chanDecl *ast.CallExpr
+               switch arg := call.Args[0].(type) {
+               case *ast.Ident:
+                       if decl, ok := findDecl(arg).(*ast.CallExpr); ok {
+                               chanDecl = decl
+                       }
+               case *ast.CallExpr:
+                       // Only signal.Notify(make(chan os.Signal), os.Interrupt) is safe,
+                       // conservatively treate others as not safe, see golang/go#45043
+                       if isBuiltinMake(pass.TypesInfo, arg) {
+                               return
+                       }
+                       chanDecl = arg
+               }
+               if chanDecl == nil || len(chanDecl.Args) != 1 {
+                       return
+               }
+
+               // Make a copy of the channel's declaration to avoid
+               // mutating the AST. See https://golang.org/issue/46129.
+               chanDeclCopy := &ast.CallExpr{}
+               *chanDeclCopy = *chanDecl
+               chanDeclCopy.Args = append([]ast.Expr(nil), chanDecl.Args...)
+               chanDeclCopy.Args = append(chanDeclCopy.Args, &ast.BasicLit{
+                       Kind:  token.INT,
+                       Value: "1",
+               })
+
+               var buf bytes.Buffer
+               if err := format.Node(&buf, token.NewFileSet(), chanDeclCopy); err != nil {
+                       return
+               }
+               pass.Report(analysis.Diagnostic{
+                       Pos:     call.Pos(),
+                       End:     call.End(),
+                       Message: "misuse of unbuffered os.Signal channel as argument to signal.Notify",
+                       SuggestedFixes: []analysis.SuggestedFix{{
+                               Message: "Change to buffer channel",
+                               TextEdits: []analysis.TextEdit{{
+                                       Pos:     chanDecl.Pos(),
+                                       End:     chanDecl.End(),
+                                       NewText: buf.Bytes(),
+                               }},
+                       }},
+               })
+       })
+       return nil, nil
+}
+
+func isSignalNotify(info *types.Info, call *ast.CallExpr) bool {
+       check := func(id *ast.Ident) bool {
+               obj := info.ObjectOf(id)
+               return obj.Name() == "Notify" && obj.Pkg().Path() == "os/signal"
+       }
+       switch fun := call.Fun.(type) {
+       case *ast.SelectorExpr:
+               return check(fun.Sel)
+       case *ast.Ident:
+               if fun, ok := findDecl(fun).(*ast.SelectorExpr); ok {
+                       return check(fun.Sel)
+               }
+               return false
+       default:
+               return false
+       }
+}
+
+func findDecl(arg *ast.Ident) ast.Node {
+       if arg.Obj == nil {
+               return nil
+       }
+       switch as := arg.Obj.Decl.(type) {
+       case *ast.AssignStmt:
+               if len(as.Lhs) != len(as.Rhs) {
+                       return nil
+               }
+               for i, lhs := range as.Lhs {
+                       lid, ok := lhs.(*ast.Ident)
+                       if !ok {
+                               continue
+                       }
+                       if lid.Obj == arg.Obj {
+                               return as.Rhs[i]
+                       }
+               }
+       case *ast.ValueSpec:
+               if len(as.Names) != len(as.Values) {
+                       return nil
+               }
+               for i, name := range as.Names {
+                       if name.Obj == arg.Obj {
+                               return as.Values[i]
+                       }
+               }
+       }
+       return nil
+}
+
+func isBuiltinMake(info *types.Info, call *ast.CallExpr) bool {
+       typVal := info.Types[call.Fun]
+       if !typVal.IsBuiltin() {
+               return false
+       }
+       switch fun := call.Fun.(type) {
+       case *ast.Ident:
+               return info.ObjectOf(fun).Name() == "make"
+       default:
+               return false
+       }
+}
index 856c6ae0d811eef294a0016fe526c4ca783391ec..64a28ac0b976265431acd4e2c8d0fa98a828b764 100644 (file)
@@ -61,10 +61,12 @@ var Analyzer = &analysis.Analyzer{
 // we let it go. But if it does have a fmt.ScanState, then the
 // rest has to match.
 var canonicalMethods = map[string]struct{ args, results []string }{
+       "As": {[]string{"interface{}"}, []string{"bool"}}, // errors.As
        // "Flush": {{}, {"error"}}, // http.Flusher and jpeg.writer conflict
        "Format":        {[]string{"=fmt.State", "rune"}, []string{}},                      // fmt.Formatter
        "GobDecode":     {[]string{"[]byte"}, []string{"error"}},                           // gob.GobDecoder
        "GobEncode":     {[]string{}, []string{"[]byte", "error"}},                         // gob.GobEncoder
+       "Is":            {[]string{"error"}, []string{"bool"}},                             // errors.Is
        "MarshalJSON":   {[]string{}, []string{"[]byte", "error"}},                         // json.Marshaler
        "MarshalXML":    {[]string{"*xml.Encoder", "xml.StartElement"}, []string{"error"}}, // xml.Marshaler
        "ReadByte":      {[]string{}, []string{"byte", "error"}},                           // io.ByteReader
@@ -76,6 +78,7 @@ var canonicalMethods = map[string]struct{ args, results []string }{
        "UnmarshalXML":  {[]string{"*xml.Decoder", "xml.StartElement"}, []string{"error"}}, // xml.Unmarshaler
        "UnreadByte":    {[]string{}, []string{"error"}},
        "UnreadRune":    {[]string{}, []string{"error"}},
+       "Unwrap":        {[]string{}, []string{"error"}},                      // errors.Unwrap
        "WriteByte":     {[]string{"byte"}, []string{"error"}},                // jpeg.writer (matching bufio.Writer)
        "WriteTo":       {[]string{"=io.Writer"}, []string{"int64", "error"}}, // io.WriterTo
 }
@@ -123,6 +126,14 @@ func canonicalMethod(pass *analysis.Pass, id *ast.Ident) {
                return
        }
 
+       // Special case: Is, As and Unwrap only apply when type
+       // implements error.
+       if id.Name == "Is" || id.Name == "As" || id.Name == "Unwrap" {
+               if recv := sign.Recv(); recv == nil || !implementsError(recv.Type()) {
+                       return
+               }
+       }
+
        // Do the =s (if any) all match?
        if !matchParams(pass, expect.args, args, "=") || !matchParams(pass, expect.results, results, "=") {
                return
@@ -185,3 +196,9 @@ func matchParamType(expect string, actual types.Type) bool {
        // Overkill but easy.
        return typeString(actual) == expect
 }
+
+var errorType = types.Universe.Lookup("error").Type().Underlying().(*types.Interface)
+
+func implementsError(actual types.Type) bool {
+       return types.Implements(actual, errorType)
+}
index 02ec2fa3f21ab997c1600340aa737c0099012d8b..323282136fb9aad2fa8d548af7901fb07867e85d 100644 (file)
@@ -97,7 +97,7 @@ func Main(analyzers ...*analysis.Analyzer) {
 
 Usage of %[1]s:
        %.16[1]s unit.cfg       # execute analysis specified by config file
-       %.16[1]s help           # general help
+       %.16[1]s help           # general help, including listing analyzers and flags
        %.16[1]s help name      # help on specific analyzer and its flags
 `, progname)
                os.Exit(1)
index 9051456e396ffcfb865b04c8f68bef4568ee509c..3180f4abe14a590ceed0fc155e7d67da44799754 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build go1.12
 // +build go1.12
 
 package unitchecker
index 86f9fd9229c5380ac559870e1394607c952eb14c..07e257ac2bf731bd376c63fef9b238ffbd1ed046 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//-go:build !amd64 && !s390x && !ppc64le && !arm64
 // -build !amd64,!s390x,!ppc64le,!arm64
 
 package crc32
index d7af018af48f9d1176520693a958864014fe6bdf..c98454c6850cf84290ee92233c5f911b525b2d61 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 // Generate the constant table associated with the poly used by the
index ecc147d5997b4a9d552c5ea9f91931e93410a242..d022d746a74ff64bb882b55f1194409618570057 100644 (file)
 //
 package maphash
 
-import "unsafe"
+import (
+       "internal/unsafeheader"
+       "unsafe"
+)
 
 // A Seed is a random value that selects the specific hash function
 // computed by a Hash. If two Hashes use the same Seeds, they
@@ -34,7 +37,7 @@ type Seed struct {
 //
 // The zero Hash is a valid Hash ready to use.
 // A zero Hash chooses a random seed for itself during
-// the first call to a Reset, Write, Seed, Sum64, or Seed method.
+// the first call to a Reset, Write, Seed, or Sum64 method.
 // For control over the seed, use SetSeed.
 //
 // The computed hash values depend only on the initial seed and
@@ -54,13 +57,19 @@ type Seed struct {
 // If multiple goroutines must compute the same seeded hash,
 // each can declare its own Hash and call SetSeed with a common Seed.
 type Hash struct {
-       _     [0]func() // not comparable
-       seed  Seed      // initial seed used for this hash
-       state Seed      // current hash of all flushed bytes
-       buf   [64]byte  // unflushed byte buffer
-       n     int       // number of unflushed bytes
+       _     [0]func()     // not comparable
+       seed  Seed          // initial seed used for this hash
+       state Seed          // current hash of all flushed bytes
+       buf   [bufSize]byte // unflushed byte buffer
+       n     int           // number of unflushed bytes
 }
 
+// bufSize is the size of the Hash write buffer.
+// The buffer ensures that writes depend only on the sequence of bytes,
+// not the sequence of WriteByte/Write/WriteString calls,
+// by always calling rthash with a full buffer (except for the tail).
+const bufSize = 128
+
 // initSeed seeds the hash if necessary.
 // initSeed is called lazily before any operation that actually uses h.seed/h.state.
 // Note that this does not include Write/WriteByte/WriteString in the case
@@ -68,7 +77,9 @@ type Hash struct {
 // which does call h.initSeed.)
 func (h *Hash) initSeed() {
        if h.seed.s == 0 {
-               h.setSeed(MakeSeed())
+               seed := MakeSeed()
+               h.seed = seed
+               h.state = seed
        }
 }
 
@@ -87,27 +98,58 @@ func (h *Hash) WriteByte(b byte) error {
 // It always writes all of b and never fails; the count and error result are for implementing io.Writer.
 func (h *Hash) Write(b []byte) (int, error) {
        size := len(b)
-       for h.n+len(b) > len(h.buf) {
+       // Deal with bytes left over in h.buf.
+       // h.n <= bufSize is always true.
+       // Checking it is ~free and it lets the compiler eliminate a bounds check.
+       if h.n > 0 && h.n <= bufSize {
                k := copy(h.buf[h.n:], b)
-               h.n = len(h.buf)
+               h.n += k
+               if h.n < bufSize {
+                       // Copied the entirety of b to h.buf.
+                       return size, nil
+               }
                b = b[k:]
                h.flush()
+               // No need to set h.n = 0 here; it happens just before exit.
+       }
+       // Process as many full buffers as possible, without copying, and calling initSeed only once.
+       if len(b) > bufSize {
+               h.initSeed()
+               for len(b) > bufSize {
+                       h.state.s = rthash(&b[0], bufSize, h.state.s)
+                       b = b[bufSize:]
+               }
        }
-       h.n += copy(h.buf[h.n:], b)
+       // Copy the tail.
+       copy(h.buf[:], b)
+       h.n = len(b)
        return size, nil
 }
 
 // WriteString adds the bytes of s to the sequence of bytes hashed by h.
 // It always writes all of s and never fails; the count and error result are for implementing io.StringWriter.
 func (h *Hash) WriteString(s string) (int, error) {
+       // WriteString mirrors Write. See Write for comments.
        size := len(s)
-       for h.n+len(s) > len(h.buf) {
+       if h.n > 0 && h.n <= bufSize {
                k := copy(h.buf[h.n:], s)
-               h.n = len(h.buf)
+               h.n += k
+               if h.n < bufSize {
+                       return size, nil
+               }
                s = s[k:]
                h.flush()
        }
-       h.n += copy(h.buf[h.n:], s)
+       if len(s) > bufSize {
+               h.initSeed()
+               for len(s) > bufSize {
+                       ptr := (*byte)((*unsafeheader.String)(unsafe.Pointer(&s)).Data)
+                       h.state.s = rthash(ptr, bufSize, h.state.s)
+                       s = s[bufSize:]
+               }
+       }
+       copy(h.buf[:], s)
+       h.n = len(s)
        return size, nil
 }
 
@@ -123,17 +165,12 @@ func (h *Hash) Seed() Seed {
 // Two Hash objects with different seeds will very likely behave differently.
 // Any bytes added to h before this call will be discarded.
 func (h *Hash) SetSeed(seed Seed) {
-       h.setSeed(seed)
-       h.n = 0
-}
-
-// setSeed sets seed without discarding accumulated data.
-func (h *Hash) setSeed(seed Seed) {
        if seed.s == 0 {
                panic("maphash: use of uninitialized Seed")
        }
        h.seed = seed
        h.state = seed
+       h.n = 0
 }
 
 // Reset discards all bytes added to h.
@@ -150,7 +187,7 @@ func (h *Hash) flush() {
                panic("maphash: flush of partially full buffer")
        }
        h.initSeed()
-       h.state.s = rthash(h.buf[:], h.state.s)
+       h.state.s = rthash(&h.buf[0], h.n, h.state.s)
        h.n = 0
 }
 
@@ -163,7 +200,7 @@ func (h *Hash) flush() {
 // by using bit masking, shifting, or modular arithmetic.
 func (h *Hash) Sum64() uint64 {
        h.initSeed()
-       return rthash(h.buf[:h.n], h.state.s)
+       return rthash(&h.buf[0], h.n, h.state.s)
 }
 
 // MakeSeed returns a new random seed.
@@ -184,18 +221,18 @@ func MakeSeed() Seed {
 //go:linkname runtime_fastrand runtime.fastrand
 func runtime_fastrand() uint32
 
-func rthash(b []byte, seed uint64) uint64 {
-       if len(b) == 0 {
+func rthash(ptr *byte, len int, seed uint64) uint64 {
+       if len == 0 {
                return seed
        }
        // The runtime hasher only works on uintptr. For 64-bit
        // architectures, we use the hasher directly. Otherwise,
        // we use two parallel hashers on the lower and upper 32 bits.
        if unsafe.Sizeof(uintptr(0)) == 8 {
-               return uint64(runtime_memhash(unsafe.Pointer(&b[0]), uintptr(seed), uintptr(len(b))))
+               return uint64(runtime_memhash(unsafe.Pointer(ptr), uintptr(seed), uintptr(len)))
        }
-       lo := runtime_memhash(unsafe.Pointer(&b[0]), uintptr(seed), uintptr(len(b)))
-       hi := runtime_memhash(unsafe.Pointer(&b[0]), uintptr(seed>>32), uintptr(len(b)))
+       lo := runtime_memhash(unsafe.Pointer(ptr), uintptr(seed), uintptr(len))
+       hi := runtime_memhash(unsafe.Pointer(ptr), uintptr(seed>>32), uintptr(len))
        return uint64(hi)<<32 | uint64(lo)
 }
 
index daf6eb478662262fb4406768e6bea075eea483b1..78cdfc0e737088843c368b250de79c825af45b1a 100644 (file)
@@ -5,6 +5,7 @@
 package maphash
 
 import (
+       "bytes"
        "hash"
        "testing"
 )
@@ -34,19 +35,57 @@ func TestSeededHash(t *testing.T) {
 }
 
 func TestHashGrouping(t *testing.T) {
-       b := []byte("foo")
-       h1 := new(Hash)
-       h2 := new(Hash)
-       h2.SetSeed(h1.Seed())
-       h1.Write(b)
-       for _, x := range b {
-               err := h2.WriteByte(x)
+       b := bytes.Repeat([]byte("foo"), 100)
+       hh := make([]*Hash, 7)
+       for i := range hh {
+               hh[i] = new(Hash)
+       }
+       for _, h := range hh[1:] {
+               h.SetSeed(hh[0].Seed())
+       }
+       hh[0].Write(b)
+       hh[1].WriteString(string(b))
+
+       writeByte := func(h *Hash, b byte) {
+               err := h.WriteByte(b)
                if err != nil {
                        t.Fatalf("WriteByte: %v", err)
                }
        }
-       if h1.Sum64() != h2.Sum64() {
-               t.Errorf("hash of \"foo\" and \"f\",\"o\",\"o\" not identical")
+       writeSingleByte := func(h *Hash, b byte) {
+               _, err := h.Write([]byte{b})
+               if err != nil {
+                       t.Fatalf("Write single byte: %v", err)
+               }
+       }
+       writeStringSingleByte := func(h *Hash, b byte) {
+               _, err := h.WriteString(string([]byte{b}))
+               if err != nil {
+                       t.Fatalf("WriteString single byte: %v", err)
+               }
+       }
+
+       for i, x := range b {
+               writeByte(hh[2], x)
+               writeSingleByte(hh[3], x)
+               if i == 0 {
+                       writeByte(hh[4], x)
+               } else {
+                       writeSingleByte(hh[4], x)
+               }
+               writeStringSingleByte(hh[5], x)
+               if i == 0 {
+                       writeByte(hh[6], x)
+               } else {
+                       writeStringSingleByte(hh[6], x)
+               }
+       }
+
+       sum := hh[0].Sum64()
+       for i, h := range hh {
+               if sum != h.Sum64() {
+                       t.Errorf("hash %d not identical to a single Write", i)
+               }
        }
 }
 
index ffa3e257f4052a1aff16f83e9d672ccb00d50181..ecaf4f9069416b14c27f28c49618a70e1315c110 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build gofuzz
 // +build gofuzz
 
 package html
index 7d1bef1782a9cc0be2a97179acb080a5ab7afad3..888587335de112cd5637f0bfe4e94d3213126c43 100644 (file)
@@ -1720,8 +1720,6 @@ var v = "v";
 `
 
 func TestEscapeRace(t *testing.T) {
-       t.Skip("this test currently fails with -race; see issue #39807")
-
        tmpl := New("")
        _, err := tmpl.New("templ.html").Parse(raceText)
        if err != nil {
index 3243e539819127bab68bd72d37cdf72329a12526..7bb257d865ffa6bfa6ea15240efe916c41fc3695 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 package main
index 8f96aa2d180eb7d774240c242d6fab14e24e90d6..13f6668293814e7b0c4d8e3271164c94d72eeb30 100644 (file)
@@ -23,6 +23,16 @@ type Image interface {
        Set(x, y int, c color.Color)
 }
 
+// RGBA64Image extends both the Image and image.RGBA64Image interfaces with a
+// SetRGBA64 method to change a single pixel. SetRGBA64 is equivalent to
+// calling Set, but it can avoid allocations from converting concrete color
+// types to the color.Color interface type.
+type RGBA64Image interface {
+       image.RGBA64Image
+       Set(x, y int, c color.Color)
+       SetRGBA64(x, y int, c color.RGBA64)
+}
+
 // Quantizer produces a palette for an image.
 type Quantizer interface {
        // Quantize appends up to cap(p) - len(p) colors to p and returns the
index 78e9e49d4f6995ddcc52c42dff8d0e6e4d829b74..e71aa611872c539a6512674eb099db52f02f34e2 100644 (file)
@@ -246,6 +246,14 @@ func (r Rectangle) At(x, y int) color.Color {
        return color.Transparent
 }
 
+// RGBA64At implements the RGBA64Image interface.
+func (r Rectangle) RGBA64At(x, y int) color.RGBA64 {
+       if (Point{x, y}).In(r) {
+               return color.RGBA64{0xffff, 0xffff, 0xffff, 0xffff}
+       }
+       return color.RGBA64{}
+}
+
 // Bounds implements the Image interface.
 func (r Rectangle) Bounds() Rectangle {
        return r
index e580ab049e6edb87dd04dc581576f58138fc5119..9e8268c86f3c018af93723a748a258b8c13870da 100644 (file)
@@ -116,7 +116,7 @@ type decoder struct {
 // consumed when checking that the blockReader is exhausted.
 //
 // To avoid the allocation of a bufio.Reader for the lzw Reader, blockReader
-// implements io.ReadByte and buffers blocks into the decoder's "tmp" buffer.
+// implements io.ByteReader and buffers blocks into the decoder's "tmp" buffer.
 type blockReader struct {
        d    *decoder
        i, j uint8 // d.tmp[i:j] contains the buffered bytes
index 8adba96ab6eb418f7f2c4457212f153e706e3143..930d9ac6c7bacdb9c98dfa2a7500e565cb42fd2e 100644 (file)
@@ -45,6 +45,17 @@ type Image interface {
        At(x, y int) color.Color
 }
 
+// RGBA64Image is an Image whose pixels can be converted directly to a
+// color.RGBA64.
+type RGBA64Image interface {
+       // RGBA64At returns the RGBA64 color of the pixel at (x, y). It is
+       // equivalent to calling At(x, y).RGBA() and converting the resulting
+       // 32-bit return values to a color.RGBA64, but it can avoid allocations
+       // from converting concrete color types to the color.Color interface type.
+       RGBA64At(x, y int) color.RGBA64
+       Image
+}
+
 // PalettedImage is an image whose colors may come from a limited palette.
 // If m is a PalettedImage and m.ColorModel() returns a color.Palette p,
 // then m.At(x, y) should be equivalent to p[m.ColorIndexAt(x, y)]. If m's
@@ -90,6 +101,24 @@ func (p *RGBA) At(x, y int) color.Color {
        return p.RGBAAt(x, y)
 }
 
+func (p *RGBA) RGBA64At(x, y int) color.RGBA64 {
+       if !(Point{x, y}.In(p.Rect)) {
+               return color.RGBA64{}
+       }
+       i := p.PixOffset(x, y)
+       s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
+       r := uint16(s[0])
+       g := uint16(s[1])
+       b := uint16(s[2])
+       a := uint16(s[3])
+       return color.RGBA64{
+               (r << 8) | r,
+               (g << 8) | g,
+               (b << 8) | b,
+               (a << 8) | a,
+       }
+}
+
 func (p *RGBA) RGBAAt(x, y int) color.RGBA {
        if !(Point{x, y}.In(p.Rect)) {
                return color.RGBA{}
@@ -118,6 +147,18 @@ func (p *RGBA) Set(x, y int, c color.Color) {
        s[3] = c1.A
 }
 
+func (p *RGBA) SetRGBA64(x, y int, c color.RGBA64) {
+       if !(Point{x, y}.In(p.Rect)) {
+               return
+       }
+       i := p.PixOffset(x, y)
+       s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
+       s[0] = uint8(c.R >> 8)
+       s[1] = uint8(c.G >> 8)
+       s[2] = uint8(c.B >> 8)
+       s[3] = uint8(c.A >> 8)
+}
+
 func (p *RGBA) SetRGBA(x, y int, c color.RGBA) {
        if !(Point{x, y}.In(p.Rect)) {
                return
@@ -311,6 +352,11 @@ func (p *NRGBA) At(x, y int) color.Color {
        return p.NRGBAAt(x, y)
 }
 
+func (p *NRGBA) RGBA64At(x, y int) color.RGBA64 {
+       r, g, b, a := p.NRGBAAt(x, y).RGBA()
+       return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
+}
+
 func (p *NRGBA) NRGBAAt(x, y int) color.NRGBA {
        if !(Point{x, y}.In(p.Rect)) {
                return color.NRGBA{}
@@ -339,6 +385,24 @@ func (p *NRGBA) Set(x, y int, c color.Color) {
        s[3] = c1.A
 }
 
+func (p *NRGBA) SetRGBA64(x, y int, c color.RGBA64) {
+       if !(Point{x, y}.In(p.Rect)) {
+               return
+       }
+       r, g, b, a := uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A)
+       if (a != 0) && (a != 0xffff) {
+               r = (r * 0xffff) / a
+               g = (g * 0xffff) / a
+               b = (b * 0xffff) / a
+       }
+       i := p.PixOffset(x, y)
+       s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
+       s[0] = uint8(r >> 8)
+       s[1] = uint8(g >> 8)
+       s[2] = uint8(b >> 8)
+       s[3] = uint8(a >> 8)
+}
+
 func (p *NRGBA) SetNRGBA(x, y int, c color.NRGBA) {
        if !(Point{x, y}.In(p.Rect)) {
                return
@@ -415,6 +479,11 @@ func (p *NRGBA64) At(x, y int) color.Color {
        return p.NRGBA64At(x, y)
 }
 
+func (p *NRGBA64) RGBA64At(x, y int) color.RGBA64 {
+       r, g, b, a := p.NRGBA64At(x, y).RGBA()
+       return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
+}
+
 func (p *NRGBA64) NRGBA64At(x, y int) color.NRGBA64 {
        if !(Point{x, y}.In(p.Rect)) {
                return color.NRGBA64{}
@@ -452,6 +521,28 @@ func (p *NRGBA64) Set(x, y int, c color.Color) {
        s[7] = uint8(c1.A)
 }
 
+func (p *NRGBA64) SetRGBA64(x, y int, c color.RGBA64) {
+       if !(Point{x, y}.In(p.Rect)) {
+               return
+       }
+       r, g, b, a := uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A)
+       if (a != 0) && (a != 0xffff) {
+               r = (r * 0xffff) / a
+               g = (g * 0xffff) / a
+               b = (b * 0xffff) / a
+       }
+       i := p.PixOffset(x, y)
+       s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
+       s[0] = uint8(r >> 8)
+       s[1] = uint8(r)
+       s[2] = uint8(g >> 8)
+       s[3] = uint8(g)
+       s[4] = uint8(b >> 8)
+       s[5] = uint8(b)
+       s[6] = uint8(a >> 8)
+       s[7] = uint8(a)
+}
+
 func (p *NRGBA64) SetNRGBA64(x, y int, c color.NRGBA64) {
        if !(Point{x, y}.In(p.Rect)) {
                return
@@ -532,6 +623,12 @@ func (p *Alpha) At(x, y int) color.Color {
        return p.AlphaAt(x, y)
 }
 
+func (p *Alpha) RGBA64At(x, y int) color.RGBA64 {
+       a := uint16(p.AlphaAt(x, y).A)
+       a |= a << 8
+       return color.RGBA64{a, a, a, a}
+}
+
 func (p *Alpha) AlphaAt(x, y int) color.Alpha {
        if !(Point{x, y}.In(p.Rect)) {
                return color.Alpha{}
@@ -554,6 +651,14 @@ func (p *Alpha) Set(x, y int, c color.Color) {
        p.Pix[i] = color.AlphaModel.Convert(c).(color.Alpha).A
 }
 
+func (p *Alpha) SetRGBA64(x, y int, c color.RGBA64) {
+       if !(Point{x, y}.In(p.Rect)) {
+               return
+       }
+       i := p.PixOffset(x, y)
+       p.Pix[i] = uint8(c.A >> 8)
+}
+
 func (p *Alpha) SetAlpha(x, y int, c color.Alpha) {
        if !(Point{x, y}.In(p.Rect)) {
                return
@@ -626,6 +731,11 @@ func (p *Alpha16) At(x, y int) color.Color {
        return p.Alpha16At(x, y)
 }
 
+func (p *Alpha16) RGBA64At(x, y int) color.RGBA64 {
+       a := p.Alpha16At(x, y).A
+       return color.RGBA64{a, a, a, a}
+}
+
 func (p *Alpha16) Alpha16At(x, y int) color.Alpha16 {
        if !(Point{x, y}.In(p.Rect)) {
                return color.Alpha16{}
@@ -650,6 +760,15 @@ func (p *Alpha16) Set(x, y int, c color.Color) {
        p.Pix[i+1] = uint8(c1.A)
 }
 
+func (p *Alpha16) SetRGBA64(x, y int, c color.RGBA64) {
+       if !(Point{x, y}.In(p.Rect)) {
+               return
+       }
+       i := p.PixOffset(x, y)
+       p.Pix[i+0] = uint8(c.A >> 8)
+       p.Pix[i+1] = uint8(c.A)
+}
+
 func (p *Alpha16) SetAlpha16(x, y int, c color.Alpha16) {
        if !(Point{x, y}.In(p.Rect)) {
                return
@@ -723,6 +842,12 @@ func (p *Gray) At(x, y int) color.Color {
        return p.GrayAt(x, y)
 }
 
+func (p *Gray) RGBA64At(x, y int) color.RGBA64 {
+       gray := uint16(p.GrayAt(x, y).Y)
+       gray |= gray << 8
+       return color.RGBA64{gray, gray, gray, 0xffff}
+}
+
 func (p *Gray) GrayAt(x, y int) color.Gray {
        if !(Point{x, y}.In(p.Rect)) {
                return color.Gray{}
@@ -745,6 +870,16 @@ func (p *Gray) Set(x, y int, c color.Color) {
        p.Pix[i] = color.GrayModel.Convert(c).(color.Gray).Y
 }
 
+func (p *Gray) SetRGBA64(x, y int, c color.RGBA64) {
+       if !(Point{x, y}.In(p.Rect)) {
+               return
+       }
+       // This formula is the same as in color.grayModel.
+       gray := (19595*uint32(c.R) + 38470*uint32(c.G) + 7471*uint32(c.B) + 1<<15) >> 24
+       i := p.PixOffset(x, y)
+       p.Pix[i] = uint8(gray)
+}
+
 func (p *Gray) SetGray(x, y int, c color.Gray) {
        if !(Point{x, y}.In(p.Rect)) {
                return
@@ -804,6 +939,11 @@ func (p *Gray16) At(x, y int) color.Color {
        return p.Gray16At(x, y)
 }
 
+func (p *Gray16) RGBA64At(x, y int) color.RGBA64 {
+       gray := p.Gray16At(x, y).Y
+       return color.RGBA64{gray, gray, gray, 0xffff}
+}
+
 func (p *Gray16) Gray16At(x, y int) color.Gray16 {
        if !(Point{x, y}.In(p.Rect)) {
                return color.Gray16{}
@@ -828,6 +968,17 @@ func (p *Gray16) Set(x, y int, c color.Color) {
        p.Pix[i+1] = uint8(c1.Y)
 }
 
+func (p *Gray16) SetRGBA64(x, y int, c color.RGBA64) {
+       if !(Point{x, y}.In(p.Rect)) {
+               return
+       }
+       // This formula is the same as in color.gray16Model.
+       gray := (19595*uint32(c.R) + 38470*uint32(c.G) + 7471*uint32(c.B) + 1<<15) >> 16
+       i := p.PixOffset(x, y)
+       p.Pix[i+0] = uint8(gray >> 8)
+       p.Pix[i+1] = uint8(gray)
+}
+
 func (p *Gray16) SetGray16(x, y int, c color.Gray16) {
        if !(Point{x, y}.In(p.Rect)) {
                return
@@ -888,6 +1039,11 @@ func (p *CMYK) At(x, y int) color.Color {
        return p.CMYKAt(x, y)
 }
 
+func (p *CMYK) RGBA64At(x, y int) color.RGBA64 {
+       r, g, b, a := p.CMYKAt(x, y).RGBA()
+       return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
+}
+
 func (p *CMYK) CMYKAt(x, y int) color.CMYK {
        if !(Point{x, y}.In(p.Rect)) {
                return color.CMYK{}
@@ -916,6 +1072,19 @@ func (p *CMYK) Set(x, y int, c color.Color) {
        s[3] = c1.K
 }
 
+func (p *CMYK) SetRGBA64(x, y int, c color.RGBA64) {
+       if !(Point{x, y}.In(p.Rect)) {
+               return
+       }
+       cc, mm, yy, kk := color.RGBToCMYK(uint8(c.R>>8), uint8(c.G>>8), uint8(c.B>>8))
+       i := p.PixOffset(x, y)
+       s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
+       s[0] = cc
+       s[1] = mm
+       s[2] = yy
+       s[3] = kk
+}
+
 func (p *CMYK) SetCMYK(x, y int, c color.CMYK) {
        if !(Point{x, y}.In(p.Rect)) {
                return
@@ -988,6 +1157,26 @@ func (p *Paletted) At(x, y int) color.Color {
        return p.Palette[p.Pix[i]]
 }
 
+func (p *Paletted) RGBA64At(x, y int) color.RGBA64 {
+       if len(p.Palette) == 0 {
+               return color.RGBA64{}
+       }
+       c := color.Color(nil)
+       if !(Point{x, y}.In(p.Rect)) {
+               c = p.Palette[0]
+       } else {
+               i := p.PixOffset(x, y)
+               c = p.Palette[p.Pix[i]]
+       }
+       r, g, b, a := c.RGBA()
+       return color.RGBA64{
+               uint16(r),
+               uint16(g),
+               uint16(b),
+               uint16(a),
+       }
+}
+
 // PixOffset returns the index of the first element of Pix that corresponds to
 // the pixel at (x, y).
 func (p *Paletted) PixOffset(x, y int) int {
@@ -1002,6 +1191,14 @@ func (p *Paletted) Set(x, y int, c color.Color) {
        p.Pix[i] = uint8(p.Palette.Index(c))
 }
 
+func (p *Paletted) SetRGBA64(x, y int, c color.RGBA64) {
+       if !(Point{x, y}.In(p.Rect)) {
+               return
+       }
+       i := p.PixOffset(x, y)
+       p.Pix[i] = uint8(p.Palette.Index(c))
+}
+
 func (p *Paletted) ColorIndexAt(x, y int) uint8 {
        if !(Point{x, y}.In(p.Rect)) {
                return 0
index b9b9bfaa28ca4157adf0c08478e2a733baeb9ac7..7f41bcb6c7086f1eb737fdd33cac1cd8135c488a 100644 (file)
@@ -6,6 +6,7 @@ package image
 
 import (
        "image/color"
+       "image/color/palette"
        "testing"
 )
 
@@ -191,6 +192,92 @@ func Test16BitsPerColorChannel(t *testing.T) {
        }
 }
 
+func TestRGBA64Image(t *testing.T) {
+       // memset sets every element of s to v.
+       memset := func(s []byte, v byte) {
+               for i := range s {
+                       s[i] = v
+               }
+       }
+
+       r := Rect(0, 0, 3, 2)
+       testCases := []Image{
+               NewAlpha(r),
+               NewAlpha16(r),
+               NewCMYK(r),
+               NewGray(r),
+               NewGray16(r),
+               NewNRGBA(r),
+               NewNRGBA64(r),
+               NewNYCbCrA(r, YCbCrSubsampleRatio444),
+               NewPaletted(r, palette.Plan9),
+               NewRGBA(r),
+               NewRGBA64(r),
+               NewUniform(color.RGBA64{}),
+               NewYCbCr(r, YCbCrSubsampleRatio444),
+               r,
+       }
+       for _, tc := range testCases {
+               switch tc := tc.(type) {
+               // Most of the concrete image types in the testCases implement the
+               // draw.RGBA64Image interface: they have a SetRGBA64 method. We use an
+               // interface literal here, instead of importing "image/draw", to avoid
+               // an import cycle.
+               //
+               // The YCbCr and NYCbCrA types are special-cased. Chroma subsampling
+               // means that setting one pixel can modify neighboring pixels. They
+               // don't have Set or SetRGBA64 methods because that side effect could
+               // be surprising. Here, we just memset the channel buffers instead.
+               //
+               // The Uniform and Rectangle types are also special-cased, as they
+               // don't have a Set or SetRGBA64 method.
+               case interface {
+                       SetRGBA64(x, y int, c color.RGBA64)
+               }:
+                       tc.SetRGBA64(1, 1, color.RGBA64{0x7FFF, 0x3FFF, 0x0000, 0x7FFF})
+
+               case *NYCbCrA:
+                       memset(tc.YCbCr.Y, 0x77)
+                       memset(tc.YCbCr.Cb, 0x88)
+                       memset(tc.YCbCr.Cr, 0x99)
+                       memset(tc.A, 0xAA)
+
+               case *Uniform:
+                       tc.C = color.RGBA64{0x7FFF, 0x3FFF, 0x0000, 0x7FFF}
+
+               case *YCbCr:
+                       memset(tc.Y, 0x77)
+                       memset(tc.Cb, 0x88)
+                       memset(tc.Cr, 0x99)
+
+               case Rectangle:
+                       // No-op. Rectangle pixels' colors are immutable. They're always
+                       // color.Opaque.
+
+               default:
+                       t.Errorf("could not initialize pixels for %T", tc)
+                       continue
+               }
+
+               // Check that RGBA64At(x, y) is equivalent to At(x, y).RGBA().
+               rgba64Image, ok := tc.(RGBA64Image)
+               if !ok {
+                       t.Errorf("%T is not an RGBA64Image", tc)
+                       continue
+               }
+               got := rgba64Image.RGBA64At(1, 1)
+               wantR, wantG, wantB, wantA := tc.At(1, 1).RGBA()
+               if (uint32(got.R) != wantR) || (uint32(got.G) != wantG) ||
+                       (uint32(got.B) != wantB) || (uint32(got.A) != wantA) {
+                       t.Errorf("%T:\ngot  (0x%04X, 0x%04X, 0x%04X, 0x%04X)\n"+
+                               "want (0x%04X, 0x%04X, 0x%04X, 0x%04X)", tc,
+                               got.R, got.G, got.B, got.A,
+                               wantR, wantG, wantB, wantA)
+                       continue
+               }
+       }
+}
+
 func BenchmarkAt(b *testing.B) {
        for _, tc := range testImages {
                b.Run(tc.name, func(b *testing.B) {
index 36de5dc9cc6b5bf9c137a86ccbceb65dd46014b1..38f41303fa747fa23b67f2306bc761eecde9ee28 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 package main
index 4a4706ffe7727333fd56778f549030d3b2a26d12..b34072396cbefaf464b7525f179315a1d142424b 100644 (file)
@@ -14,9 +14,6 @@ import (
        "io"
 )
 
-// TODO(nigeltao): fix up the doc comment style so that sentences start with
-// the name of the type or function that they annotate.
-
 // A FormatError reports that the input is not a valid JPEG.
 type FormatError string
 
index 8595a35014db0d568471defe31a7f02e98485519..17b06588ac52e597067a7491046b56e7e6cf7d62 100644 (file)
@@ -41,6 +41,11 @@ func (c *Uniform) Bounds() Rectangle { return Rectangle{Point{-1e9, -1e9}, Point
 
 func (c *Uniform) At(x, y int) color.Color { return c.C }
 
+func (c *Uniform) RGBA64At(x, y int) color.RGBA64 {
+       r, g, b, a := c.C.RGBA()
+       return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
+}
+
 // Opaque scans the entire image and reports whether it is fully opaque.
 func (c *Uniform) Opaque() bool {
        _, _, _, a := c.C.RGBA()
index d9cb3921e57a5fe1b1f256e3e689ed99d69de046..6508533f4440b3f2816c43593e4beee387a30030 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build gofuzz
 // +build gofuzz
 
 package png
index 53adc1633c0dba6a7e82b19fc9b898d1c222d1ba..cbcdb9e798519488c1a5925968a9661230b60460 100644 (file)
@@ -51,6 +51,7 @@ type encoder struct {
        bw      *bufio.Writer
 }
 
+// CompressionLevel indicates the compression level.
 type CompressionLevel int
 
 const (
index fbdffe1bd1babc8c9b93c1b6c2cf46bf6e8559aa..328b90d1525655d079bab6a5f10a1604d9e0c413 100644 (file)
@@ -71,6 +71,11 @@ func (p *YCbCr) At(x, y int) color.Color {
        return p.YCbCrAt(x, y)
 }
 
+func (p *YCbCr) RGBA64At(x, y int) color.RGBA64 {
+       r, g, b, a := p.YCbCrAt(x, y).RGBA()
+       return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
+}
+
 func (p *YCbCr) YCbCrAt(x, y int) color.YCbCr {
        if !(Point{x, y}.In(p.Rect)) {
                return color.YCbCr{}
@@ -210,6 +215,11 @@ func (p *NYCbCrA) At(x, y int) color.Color {
        return p.NYCbCrAAt(x, y)
 }
 
+func (p *NYCbCrA) RGBA64At(x, y int) color.RGBA64 {
+       r, g, b, a := p.NYCbCrAAt(x, y).RGBA()
+       return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
+}
+
 func (p *NYCbCrA) NYCbCrAAt(x, y int) color.NYCbCrA {
        if !(Point{X: x, Y: y}.In(p.Rect)) {
                return color.NYCbCrA{}
index 94184d71b68309417d896b17c235c6bab7528c46..3bc9b1e2aea4328551f95aa8da19c5f3ab83ac44 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 // Gen generates sais2.go by duplicating functions in sais.go
diff --git a/libgo/go/internal/buildcfg/cfg.go b/libgo/go/internal/buildcfg/cfg.go
new file mode 100644 (file)
index 0000000..4bf418e
--- /dev/null
@@ -0,0 +1,136 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package buildcfg provides access to the build configuration
+// described by the current environment. It is for use by build tools
+// such as cmd/go or cmd/compile and for setting up go/build's Default context.
+//
+// Note that it does NOT provide access to the build configuration used to
+// build the currently-running binary. For that, use runtime.GOOS etc
+// as well as internal/goexperiment.
+package buildcfg
+
+import (
+       "fmt"
+       "os"
+       "path/filepath"
+       "strings"
+)
+
+var (
+       defaultGOROOT = defaultGOROOTValue()
+
+       GOROOT   = envOr("GOROOT", defaultGOROOT)
+       GOARCH   = envOr("GOARCH", defaultGOARCH)
+       GOOS     = envOr("GOOS", defaultGOOS)
+       GO386    = envOr("GO386", defaultGO386)
+       GOARM    = goarm()
+       GOMIPS   = gomips()
+       GOMIPS64 = gomips64()
+       GOPPC64  = goppc64()
+       GOWASM   = gowasm()
+       GO_LDSO  = defaultGO_LDSO
+       Version  = version
+)
+
+// Error is one of the errors found (if any) in the build configuration.
+var Error error
+
+// Check exits the program with a fatal error if Error is non-nil.
+func Check() {
+       if Error != nil {
+               fmt.Fprintf(os.Stderr, "%s: %v\n", filepath.Base(os.Args[0]), Error)
+               os.Exit(2)
+       }
+}
+
+func envOr(key, value string) string {
+       if x := os.Getenv(key); x != "" {
+               return x
+       }
+       return value
+}
+
+func goarm() int {
+       def := defaultGOARM
+       if GOOS == "android" && GOARCH == "arm" {
+               // Android arm devices always support GOARM=7.
+               def = "7"
+       }
+       switch v := envOr("GOARM", def); v {
+       case "5":
+               return 5
+       case "6":
+               return 6
+       case "7":
+               return 7
+       }
+       Error = fmt.Errorf("invalid GOARM: must be 5, 6, 7")
+       return int(def[0] - '0')
+}
+
+func gomips() string {
+       switch v := envOr("GOMIPS", defaultGOMIPS); v {
+       case "hardfloat", "softfloat":
+               return v
+       }
+       Error = fmt.Errorf("invalid GOMIPS: must be hardfloat, softfloat")
+       return defaultGOMIPS
+}
+
+func gomips64() string {
+       switch v := envOr("GOMIPS64", defaultGOMIPS64); v {
+       case "hardfloat", "softfloat":
+               return v
+       }
+       Error = fmt.Errorf("invalid GOMIPS64: must be hardfloat, softfloat")
+       return defaultGOMIPS64
+}
+
+func goppc64() int {
+       switch v := envOr("GOPPC64", defaultGOPPC64); v {
+       case "power8":
+               return 8
+       case "power9":
+               return 9
+       }
+       Error = fmt.Errorf("invalid GOPPC64: must be power8, power9")
+       return int(defaultGOPPC64[len("power")] - '0')
+}
+
+type gowasmFeatures struct {
+       SignExt bool
+       SatConv bool
+}
+
+func (f gowasmFeatures) String() string {
+       var flags []string
+       if f.SatConv {
+               flags = append(flags, "satconv")
+       }
+       if f.SignExt {
+               flags = append(flags, "signext")
+       }
+       return strings.Join(flags, ",")
+}
+
+func gowasm() (f gowasmFeatures) {
+       for _, opt := range strings.Split(envOr("GOWASM", ""), ",") {
+               switch opt {
+               case "satconv":
+                       f.SatConv = true
+               case "signext":
+                       f.SignExt = true
+               case "":
+                       // ignore
+               default:
+                       Error = fmt.Errorf("invalid GOWASM: no such feature %q", opt)
+               }
+       }
+       return
+}
+
+func Getgoextlinkenabled() string {
+       return envOr("GO_EXTLINK_ENABLED", defaultGO_EXTLINK_ENABLED)
+}
diff --git a/libgo/go/internal/buildcfg/exp.go b/libgo/go/internal/buildcfg/exp.go
new file mode 100644 (file)
index 0000000..736c080
--- /dev/null
@@ -0,0 +1,189 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package buildcfg
+
+import (
+       "fmt"
+       "reflect"
+       "strings"
+
+       "internal/goexperiment"
+)
+
+// Experiment contains the toolchain experiments enabled for the
+// current build.
+//
+// (This is not necessarily the set of experiments the compiler itself
+// was built with.)
+//
+// experimentBaseline specifies the experiment flags that are enabled by
+// default in the current toolchain. This is, in effect, the "control"
+// configuration and any variation from this is an experiment.
+var Experiment, experimentBaseline = func() (goexperiment.Flags, goexperiment.Flags) {
+       flags, baseline, err := ParseGOEXPERIMENT(GOOS, GOARCH, envOr("GOEXPERIMENT", defaultGOEXPERIMENT))
+       if err != nil {
+               Error = err
+       }
+       return flags, baseline
+}()
+
+const DefaultGOEXPERIMENT = defaultGOEXPERIMENT
+
+// FramePointerEnabled enables the use of platform conventions for
+// saving frame pointers.
+//
+// This used to be an experiment, but now it's always enabled on
+// platforms that support it.
+//
+// Note: must agree with runtime.framepointer_enabled.
+var FramePointerEnabled = GOARCH == "amd64" || GOARCH == "arm64"
+
+// ParseGOEXPERIMENT parses a (GOOS, GOARCH, GOEXPERIMENT)
+// configuration tuple and returns the enabled and baseline experiment
+// flag sets.
+//
+// TODO(mdempsky): Move to internal/goexperiment.
+func ParseGOEXPERIMENT(goos, goarch, goexp string) (flags, baseline goexperiment.Flags, err error) {
+       regabiSupported := false
+
+       baseline = goexperiment.Flags{
+               RegabiWrappers: regabiSupported,
+               RegabiG:        regabiSupported,
+               RegabiReflect:  regabiSupported,
+               RegabiDefer:    regabiSupported,
+               RegabiArgs:     regabiSupported,
+       }
+
+       // Start with the statically enabled set of experiments.
+       flags = baseline
+
+       // Pick up any changes to the baseline configuration from the
+       // GOEXPERIMENT environment. This can be set at make.bash time
+       // and overridden at build time.
+       if goexp != "" {
+               // Create a map of known experiment names.
+               names := make(map[string]func(bool))
+               rv := reflect.ValueOf(&flags).Elem()
+               rt := rv.Type()
+               for i := 0; i < rt.NumField(); i++ {
+                       field := rv.Field(i)
+                       names[strings.ToLower(rt.Field(i).Name)] = field.SetBool
+               }
+
+               // "regabi" is an alias for all working regabi
+               // subexperiments, and not an experiment itself. Doing
+               // this as an alias make both "regabi" and "noregabi"
+               // do the right thing.
+               names["regabi"] = func(v bool) {
+                       flags.RegabiWrappers = v
+                       flags.RegabiG = v
+                       flags.RegabiReflect = v
+                       flags.RegabiDefer = v
+                       flags.RegabiArgs = v
+               }
+
+               // Parse names.
+               for _, f := range strings.Split(goexp, ",") {
+                       if f == "" {
+                               continue
+                       }
+                       if f == "none" {
+                               // GOEXPERIMENT=none disables all experiment flags.
+                               // This is used by cmd/dist, which doesn't know how
+                               // to build with any experiment flags.
+                               flags = goexperiment.Flags{}
+                               continue
+                       }
+                       val := true
+                       if strings.HasPrefix(f, "no") {
+                               f, val = f[2:], false
+                       }
+                       set, ok := names[f]
+                       if !ok {
+                               err = fmt.Errorf("unknown GOEXPERIMENT %s", f)
+                               return
+                       }
+                       set(val)
+               }
+       }
+
+       // regabi is only supported on amd64.
+       if goarch != "amd64" {
+               flags.RegabiWrappers = false
+               flags.RegabiG = false
+               flags.RegabiReflect = false
+               flags.RegabiDefer = false
+               flags.RegabiArgs = false
+       }
+       // Check regabi dependencies.
+       if flags.RegabiG && !flags.RegabiWrappers {
+               err = fmt.Errorf("GOEXPERIMENT regabig requires regabiwrappers")
+       }
+       if flags.RegabiArgs && !(flags.RegabiWrappers && flags.RegabiG && flags.RegabiReflect && flags.RegabiDefer) {
+               err = fmt.Errorf("GOEXPERIMENT regabiargs requires regabiwrappers,regabig,regabireflect,regabidefer")
+       }
+       return
+}
+
+// expList returns the list of lower-cased experiment names for
+// experiments that differ from base. base may be nil to indicate no
+// experiments. If all is true, then include all experiment flags,
+// regardless of base.
+func expList(exp, base *goexperiment.Flags, all bool) []string {
+       var list []string
+       rv := reflect.ValueOf(exp).Elem()
+       var rBase reflect.Value
+       if base != nil {
+               rBase = reflect.ValueOf(base).Elem()
+       }
+       rt := rv.Type()
+       for i := 0; i < rt.NumField(); i++ {
+               name := strings.ToLower(rt.Field(i).Name)
+               val := rv.Field(i).Bool()
+               baseVal := false
+               if base != nil {
+                       baseVal = rBase.Field(i).Bool()
+               }
+               if all || val != baseVal {
+                       if val {
+                               list = append(list, name)
+                       } else {
+                               list = append(list, "no"+name)
+                       }
+               }
+       }
+       return list
+}
+
+// GOEXPERIMENT is a comma-separated list of enabled or disabled
+// experiments that differ from the baseline experiment configuration.
+// GOEXPERIMENT is exactly what a user would set on the command line
+// to get the set of enabled experiments.
+func GOEXPERIMENT() string {
+       return strings.Join(expList(&Experiment, &experimentBaseline, false), ",")
+}
+
+// EnabledExperiments returns a list of enabled experiments, as
+// lower-cased experiment names.
+func EnabledExperiments() []string {
+       return expList(&Experiment, nil, false)
+}
+
+// AllExperiments returns a list of all experiment settings.
+// Disabled experiments appear in the list prefixed by "no".
+func AllExperiments() []string {
+       return expList(&Experiment, nil, true)
+}
+
+// UpdateExperiments updates the Experiment global based on a new GOARCH value.
+// This is only required for cmd/go, which can change GOARCH after
+// program startup due to use of "go env -w".
+func UpdateExperiments(goos, goarch, goexperiment string) {
+       var err error
+       Experiment, experimentBaseline, err = ParseGOEXPERIMENT(goos, goarch, goexperiment)
+       if err != nil {
+               Error = err
+       }
+}
index 58efb95c32805c9f3afcb4a1a3a7e320835981ba..68de560a6b59a9d8850c006461885eaeffb4d193 100644 (file)
@@ -17,6 +17,8 @@ const (
        offsetX86HasPOPCNT = unsafe.Offsetof(cpu.X86.HasPOPCNT)
 
        offsetS390xHasVX = unsafe.Offsetof(cpu.S390X.HasVX)
+
+       offsetPPC64HasPOWER9 = unsafe.Offsetof(cpu.PPC64.IsPOWER9)
 )
 
 // MaxLen is the maximum length of the string to be searched for (argument b) in Index.
index a29e8e7c2bbabf76ee59e5ba3f4d153c66122c61..45e6a022e3a04346d5701ff4e4b51be2dcdb381d 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build ignore_for_gccgo
-// +build !386,!amd64,!s390x,!arm,!arm64,!ppc64,!ppc64le,!mips,!mipsle,!wasm,!mips64,!mips64le
+//go:build ignore
+// +build ignore
 
 package bytealg
 
index b189998c46cf7641a2f091b27288bfcdcd0473a6..629e8589300bbe30f46b05dab08f93ea70725e47 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//-go:build 386 || amd64 || s390x || arm || arm64 || ppc64 || ppc64le || mips || mipsle || wasm || mips64 || mips64le
 // -build 386 amd64 s390x arm arm64 ppc64 ppc64le mips mipsle wasm mips64 mips64le
 
 package bytealg
index 7e4510c0b13e5c5520b2dca6a0fb74ddc6a026b8..d0e1c3b467aecba06e87558742e6d01b602d2434 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//-go:build !amd64 && !arm && !arm64 && !ppc64le && !ppc64 && !riscv64 && !s390x
 // -build !amd64,!arm,!arm64,!ppc64le,!ppc64,!riscv64,!s390x
 
 package bytealg
index a0151a0935014855eb4d066bfa8ed8cd74d67b4a..efb782f6b1d2293982c1f1eaab5aaaee3b4700aa 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build ignore_for_gccgo
-// +build amd64 arm arm64 ppc64le ppc64 riscv64 s390x
+//go:build ignore
+// +build ignore
 
 package bytealg
 
index dd6a6cf52e2faab1cda8f186b04da442fcc88269..7208118f0111c8f8897b2a96686a9c7ce1854f73 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore_for_gccgo
 // +build ignore_for_gccgo
 
 package bytealg
index c595c231cf019c4c88446c2f0fa311648f5f19f5..a880eb3c171dc569709e5e28dc060d34427a73fa 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build ignore_for_gccgo
-// +build !amd64,!arm64,!s390x
+//go:build ignore
+// +build ignore
 
 package bytealg
 
index 26f4769c2a0e5c0dd6fab85a4fbb98278a0eb3ae..7086940541a824464be3b84c0d0b31eac921202b 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// -build amd64 arm64 s390x
+//-go:build amd64 || arm64 || s390x || ppc64le || ppc64
+// -build amd64 arm64 s390x ppc64le ppc64
 
 package bytealg
 
diff --git a/libgo/go/internal/bytealg/index_ppc64x.go b/libgo/go/internal/bytealg/index_ppc64x.go
new file mode 100644 (file)
index 0000000..f8f8f50
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build ignore_for_gccgo
+// +build ignore_for_gccgo
+
+package bytealg
+
+import "internal/cpu"
+
+const MaxBruteForce = 16
+
+var SupportsPower9 = cpu.PPC64.IsPOWER9
+
+func init() {
+       MaxLen = 32
+}
+
+// Cutover reports the number of failures of IndexByte we should tolerate
+// before switching over to Index.
+// n is the number of bytes processed so far.
+// See the bytes.Index implementation for details.
+func Cutover(n int) int {
+       // 1 error per 8 characters, plus a few slop to start.
+       return (n + 16) / 8
+}
index 46325dd7f07273e4e41c4639dfe58522d4bd071f..09a66155d8a5ef05efef92b8ca97649fbf2461e8 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build ignore_for_gccgo
-// +build !386,!amd64,!s390x,!arm,!arm64,!ppc64,!ppc64le,!mips,!mipsle,!mips64,!mips64le,!riscv,!riscv64,!wasm
+//go:build ignore
+// +build ignore
 
 package bytealg
 
index c427e669bbd34cddc93d8b5dc020d9f721fd810c..2cc118ce748248ba36494f48a4c019224f3720b4 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// -build 386 amd64 s390x arm arm64 ppc64 ppc64le mips mipsle mips64 mips64le riscv riscv64 wasm
+//-go:build 386 || amd64 || s390x || arm || arm64 || ppc64 || ppc64le || mips || mipsle || mips64 || mips64le || riscv64 || wasm
+// -build 386 amd64 s390x arm arm64 ppc64 ppc64le mips mipsle mips64 mips64le riscv64 wasm
 
 package bytealg
 
index 553021374d5f1c0dff5317297c9268eaa8c0e0e5..815994b679ac3c70658822a155d9981e4576da54 100644 (file)
@@ -39,6 +39,7 @@ const KnownEnv = `
        GOCACHE
        GOENV
        GOEXE
+       GOEXPERIMENT
        GOFLAGS
        GOGCCFLAGS
        GOHOSTARCH
index 3c9e57c52aa14ce874d45a94d7036f97fd4c430a..ac6eee54b211389b095a5bc3acdaf30e46535fb5 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build arm64
 // +build arm64
 
 package cpu
index e094b97f973c39645b07e74a868cfbcf0526fec2..ce1b250a18913792c2733007b3e0259fb64950f4 100644 (file)
@@ -2,9 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build arm64
-// +build darwin
-// +build !ios
+//go:build arm64 && darwin && !ios
+// +build arm64,darwin,!ios
 
 package cpu
 
index 9de2005c2e36846f1392e72d1ad4401401a579cd..8c481370da65778478a7dbdbff65bc2b990c6193 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build arm64
 // +build arm64
 
 package cpu
index fdaf43e1a25e05542efce14f5694ab5fc56ece2f..8ac04fd8f975b8d5b18967b47c085c432948d360 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build arm64
-// +build linux
+//go:build arm64 && linux
+// +build arm64,linux
 
 package cpu
 
index 2f7411ff1e11993f666242055036797d1cece69e..c3a3f9a8e9d64d97d3dc40546be5845503feda33 100644 (file)
@@ -2,9 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build arm64
-// +build linux
-// +build !android
+//go:build arm64 && linux && !android
+// +build arm64,linux,!android
 
 package cpu
 
index f191db28d2a0d3481c46613afaed1f3fd7b09d22..e8b5d529a4bbd6517b563bb6ece707c5ef54a9c4 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build arm64 && !linux && !freebsd && !android && (!darwin || ios)
 // +build arm64
 // +build !linux
 // +build !freebsd
index 58fbd3db93dbfd1fb7942edbb970c5398d0406c2..c6604033962e92a2e4bfb4b313addb08661e3dde 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build mips64 || mips64le
 // +build mips64 mips64le
 
 package cpu
index f028a92c9357179af653c1140e0956099423b9a2..8e636d5fa103adbac854f8b554188221e512d79e 100644 (file)
@@ -2,9 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !386
-// +build !amd64
-// +build !amd64p32
+//go:build !386 && !amd64 && !amd64p32
+// +build !386,!amd64,!amd64p32
 
 package cpu
 
index 0a48f6a0a06e45de5215ea5bb3d8b1a3dcf511d6..1c7c39fc130f8e8c8bcdea5c839e852c056a34a6 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ppc || ppc64 || ppc64le
 // +build ppc ppc64 ppc64le
 
 package cpu
index e2422a6ddaa696b48010b365b90b0b5624739c45..c7e47b2929be8e425eb74e146cc8199bac923561 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ppc || ppc64 || ppc64le
 // +build ppc ppc64 ppc64le
 
 package cpu
index 068a799781ab6638c0e528d011665b415d1c270b..0c89f3b5df6f58856538badbf895154e87fce458 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ppc || ppc64 || ppc64le
 // +build ppc ppc64 ppc64le
 
 package cpu
index 338d90992c504d80a3371db2156a1f59f0efbbb7..6182532733cc72da55e9a4621856cb66efa14bfa 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build 386 || amd64 || amd64p32
 // +build 386 amd64 amd64p32
 
 package cpu
index 61db93bd517f153635e0971f8d312ea8d34204a4..e3e16cc1612e05955295a965204ca0dc66e497aa 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build 386 || amd64
 // +build 386 amd64
 
 package cpu_test
index b71458587c5e847db83c45f0528a0a8841155e14..97a3f39b4a24bbca1e3496d2cfa02defe82ce139 100644 (file)
@@ -8,7 +8,6 @@ import (
        "context"
        "fmt"
        "internal/testenv"
-       "io/ioutil"
        "os"
        "os/exec"
        "path/filepath"
@@ -42,8 +41,8 @@ func TestCommand(t *testing.T) {
                if runtime.GOOS == "windows" {
                        executable += ".exe"
                }
-               if err := ioutil.WriteFile(filepath.Join(tmpDir, executable), []byte{1, 2, 3}, 0111); err != nil {
-                       t.Fatalf("ioutil.WriteFile failed: %s", err)
+               if err := os.WriteFile(filepath.Join(tmpDir, executable), []byte{1, 2, 3}, 0111); err != nil {
+                       t.Fatalf("os.WriteFile failed: %s", err)
                }
                cwd, err := os.Getwd()
                if err != nil {
@@ -77,8 +76,8 @@ func TestLookPath(t *testing.T) {
        if runtime.GOOS == "windows" {
                executable += ".exe"
        }
-       if err := ioutil.WriteFile(filepath.Join(tmpDir, executable), []byte{1, 2, 3}, 0111); err != nil {
-               t.Fatalf("ioutil.WriteFile failed: %s", err)
+       if err := os.WriteFile(filepath.Join(tmpDir, executable), []byte{1, 2, 3}, 0111); err != nil {
+               t.Fatalf("os.WriteFile failed: %s", err)
        }
        cwd, err := os.Getwd()
        if err != nil {
diff --git a/libgo/go/internal/goexperiment/exp_fieldtrack_off.go b/libgo/go/internal/goexperiment/exp_fieldtrack_off.go
new file mode 100644 (file)
index 0000000..e5e1326
--- /dev/null
@@ -0,0 +1,9 @@
+// Code generated by mkconsts.go. DO NOT EDIT.
+
+//go:build !goexperiment.fieldtrack
+// +build !goexperiment.fieldtrack
+
+package goexperiment
+
+const FieldTrack = false
+const FieldTrackInt = 0
diff --git a/libgo/go/internal/goexperiment/exp_fieldtrack_on.go b/libgo/go/internal/goexperiment/exp_fieldtrack_on.go
new file mode 100644 (file)
index 0000000..0d8c447
--- /dev/null
@@ -0,0 +1,9 @@
+// Code generated by mkconsts.go. DO NOT EDIT.
+
+//go:build goexperiment.fieldtrack
+// +build goexperiment.fieldtrack
+
+package goexperiment
+
+const FieldTrack = true
+const FieldTrackInt = 1
diff --git a/libgo/go/internal/goexperiment/exp_preemptibleloops_off.go b/libgo/go/internal/goexperiment/exp_preemptibleloops_off.go
new file mode 100644 (file)
index 0000000..7a26088
--- /dev/null
@@ -0,0 +1,9 @@
+// Code generated by mkconsts.go. DO NOT EDIT.
+
+//go:build !goexperiment.preemptibleloops
+// +build !goexperiment.preemptibleloops
+
+package goexperiment
+
+const PreemptibleLoops = false
+const PreemptibleLoopsInt = 0
diff --git a/libgo/go/internal/goexperiment/exp_preemptibleloops_on.go b/libgo/go/internal/goexperiment/exp_preemptibleloops_on.go
new file mode 100644 (file)
index 0000000..a9ca28c
--- /dev/null
@@ -0,0 +1,9 @@
+// Code generated by mkconsts.go. DO NOT EDIT.
+
+//go:build goexperiment.preemptibleloops
+// +build goexperiment.preemptibleloops
+
+package goexperiment
+
+const PreemptibleLoops = true
+const PreemptibleLoopsInt = 1
diff --git a/libgo/go/internal/goexperiment/exp_regabi_off.go b/libgo/go/internal/goexperiment/exp_regabi_off.go
new file mode 100644 (file)
index 0000000..5d88238
--- /dev/null
@@ -0,0 +1,9 @@
+// Code generated by mkconsts.go. DO NOT EDIT.
+
+//go:build !goexperiment.regabi
+// +build !goexperiment.regabi
+
+package goexperiment
+
+const Regabi = false
+const RegabiInt = 0
diff --git a/libgo/go/internal/goexperiment/exp_regabi_on.go b/libgo/go/internal/goexperiment/exp_regabi_on.go
new file mode 100644 (file)
index 0000000..c08d58e
--- /dev/null
@@ -0,0 +1,9 @@
+// Code generated by mkconsts.go. DO NOT EDIT.
+
+//go:build goexperiment.regabi
+// +build goexperiment.regabi
+
+package goexperiment
+
+const Regabi = true
+const RegabiInt = 1
diff --git a/libgo/go/internal/goexperiment/exp_regabiargs_off.go b/libgo/go/internal/goexperiment/exp_regabiargs_off.go
new file mode 100644 (file)
index 0000000..31a139b
--- /dev/null
@@ -0,0 +1,9 @@
+// Code generated by mkconsts.go. DO NOT EDIT.
+
+//go:build !goexperiment.regabiargs
+// +build !goexperiment.regabiargs
+
+package goexperiment
+
+const RegabiArgs = false
+const RegabiArgsInt = 0
diff --git a/libgo/go/internal/goexperiment/exp_regabiargs_on.go b/libgo/go/internal/goexperiment/exp_regabiargs_on.go
new file mode 100644 (file)
index 0000000..9b26f3c
--- /dev/null
@@ -0,0 +1,9 @@
+// Code generated by mkconsts.go. DO NOT EDIT.
+
+//go:build goexperiment.regabiargs
+// +build goexperiment.regabiargs
+
+package goexperiment
+
+const RegabiArgs = true
+const RegabiArgsInt = 1
diff --git a/libgo/go/internal/goexperiment/exp_regabidefer_off.go b/libgo/go/internal/goexperiment/exp_regabidefer_off.go
new file mode 100644 (file)
index 0000000..b47c0c2
--- /dev/null
@@ -0,0 +1,9 @@
+// Code generated by mkconsts.go. DO NOT EDIT.
+
+//go:build !goexperiment.regabidefer
+// +build !goexperiment.regabidefer
+
+package goexperiment
+
+const RegabiDefer = false
+const RegabiDeferInt = 0
diff --git a/libgo/go/internal/goexperiment/exp_regabidefer_on.go b/libgo/go/internal/goexperiment/exp_regabidefer_on.go
new file mode 100644 (file)
index 0000000..bbf2f6c
--- /dev/null
@@ -0,0 +1,9 @@
+// Code generated by mkconsts.go. DO NOT EDIT.
+
+//go:build goexperiment.regabidefer
+// +build goexperiment.regabidefer
+
+package goexperiment
+
+const RegabiDefer = true
+const RegabiDeferInt = 1
diff --git a/libgo/go/internal/goexperiment/exp_regabig_off.go b/libgo/go/internal/goexperiment/exp_regabig_off.go
new file mode 100644 (file)
index 0000000..1b37d45
--- /dev/null
@@ -0,0 +1,9 @@
+// Code generated by mkconsts.go. DO NOT EDIT.
+
+//go:build !goexperiment.regabig
+// +build !goexperiment.regabig
+
+package goexperiment
+
+const RegabiG = false
+const RegabiGInt = 0
diff --git a/libgo/go/internal/goexperiment/exp_regabig_on.go b/libgo/go/internal/goexperiment/exp_regabig_on.go
new file mode 100644 (file)
index 0000000..7e5b162
--- /dev/null
@@ -0,0 +1,9 @@
+// Code generated by mkconsts.go. DO NOT EDIT.
+
+//go:build goexperiment.regabig
+// +build goexperiment.regabig
+
+package goexperiment
+
+const RegabiG = true
+const RegabiGInt = 1
diff --git a/libgo/go/internal/goexperiment/exp_regabireflect_off.go b/libgo/go/internal/goexperiment/exp_regabireflect_off.go
new file mode 100644 (file)
index 0000000..515f4a5
--- /dev/null
@@ -0,0 +1,9 @@
+// Code generated by mkconsts.go. DO NOT EDIT.
+
+//go:build !goexperiment.regabireflect
+// +build !goexperiment.regabireflect
+
+package goexperiment
+
+const RegabiReflect = false
+const RegabiReflectInt = 0
diff --git a/libgo/go/internal/goexperiment/exp_regabireflect_on.go b/libgo/go/internal/goexperiment/exp_regabireflect_on.go
new file mode 100644 (file)
index 0000000..e8a3e9c
--- /dev/null
@@ -0,0 +1,9 @@
+// Code generated by mkconsts.go. DO NOT EDIT.
+
+//go:build goexperiment.regabireflect
+// +build goexperiment.regabireflect
+
+package goexperiment
+
+const RegabiReflect = true
+const RegabiReflectInt = 1
diff --git a/libgo/go/internal/goexperiment/exp_regabiwrappers_off.go b/libgo/go/internal/goexperiment/exp_regabiwrappers_off.go
new file mode 100644 (file)
index 0000000..bfa0fa3
--- /dev/null
@@ -0,0 +1,9 @@
+// Code generated by mkconsts.go. DO NOT EDIT.
+
+//go:build !goexperiment.regabiwrappers
+// +build !goexperiment.regabiwrappers
+
+package goexperiment
+
+const RegabiWrappers = false
+const RegabiWrappersInt = 0
diff --git a/libgo/go/internal/goexperiment/exp_regabiwrappers_on.go b/libgo/go/internal/goexperiment/exp_regabiwrappers_on.go
new file mode 100644 (file)
index 0000000..11ffffb
--- /dev/null
@@ -0,0 +1,9 @@
+// Code generated by mkconsts.go. DO NOT EDIT.
+
+//go:build goexperiment.regabiwrappers
+// +build goexperiment.regabiwrappers
+
+package goexperiment
+
+const RegabiWrappers = true
+const RegabiWrappersInt = 1
diff --git a/libgo/go/internal/goexperiment/exp_staticlockranking_off.go b/libgo/go/internal/goexperiment/exp_staticlockranking_off.go
new file mode 100644 (file)
index 0000000..3d546c0
--- /dev/null
@@ -0,0 +1,9 @@
+// Code generated by mkconsts.go. DO NOT EDIT.
+
+//go:build !goexperiment.staticlockranking
+// +build !goexperiment.staticlockranking
+
+package goexperiment
+
+const StaticLockRanking = false
+const StaticLockRankingInt = 0
diff --git a/libgo/go/internal/goexperiment/exp_staticlockranking_on.go b/libgo/go/internal/goexperiment/exp_staticlockranking_on.go
new file mode 100644 (file)
index 0000000..78188fb
--- /dev/null
@@ -0,0 +1,9 @@
+// Code generated by mkconsts.go. DO NOT EDIT.
+
+//go:build goexperiment.staticlockranking
+// +build goexperiment.staticlockranking
+
+package goexperiment
+
+const StaticLockRanking = true
+const StaticLockRankingInt = 1
diff --git a/libgo/go/internal/goexperiment/flags.go b/libgo/go/internal/goexperiment/flags.go
new file mode 100644 (file)
index 0000000..cd4c178
--- /dev/null
@@ -0,0 +1,93 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package goexperiment implements support for toolchain experiments.
+//
+// Toolchain experiments are controlled by the GOEXPERIMENT
+// environment variable. GOEXPERIMENT is a comma-separated list of
+// experiment names. GOEXPERIMENT can be set at make.bash time, which
+// sets the default experiments for binaries built with the tool
+// chain; or it can be set at build time. GOEXPERIMENT can also be set
+// to "none", which disables any experiments that were enabled at
+// make.bash time.
+//
+// Experiments are exposed to the build in the following ways:
+//
+// - Build tag goexperiment.x is set if experiment x (lower case) is
+// enabled.
+//
+// - For each experiment x (in camel case), this package contains a
+// boolean constant x and an integer constant xInt.
+//
+// - In runtime assembly, the macro GOEXPERIMENT_x is defined if
+// experiment x (lower case) is enabled.
+//
+// In the toolchain, the set of experiments enabled for the current
+// build should be accessed via objabi.Experiment.
+//
+// The set of experiments is included in the output of runtime.Version()
+// and "go version <binary>" if it differs from the default experiments.
+//
+// For the set of experiments supported by the current toolchain, see
+// "go doc goexperiment.Flags".
+//
+// Note that this package defines the set of experiments (in Flags)
+// and records the experiments that were enabled when the package
+// was compiled (as boolean and integer constants).
+//
+// Note especially that this package does not itself change behavior
+// at run time based on the GOEXPERIMENT variable.
+// The code used in builds to interpret the GOEXPERIMENT variable
+// is in the separate package internal/buildcfg.
+package goexperiment
+
+//go:generate go run mkconsts.go
+
+// Flags is the set of experiments that can be enabled or disabled in
+// the current toolchain.
+//
+// When specified in the GOEXPERIMENT environment variable or as build
+// tags, experiments use the strings.ToLower of their field name.
+//
+// For the baseline experimental configuration, see
+// objabi.experimentBaseline.
+//
+// If you change this struct definition, run "go generate".
+type Flags struct {
+       FieldTrack        bool
+       PreemptibleLoops  bool
+       StaticLockRanking bool
+
+       // Regabi is split into several sub-experiments that can be
+       // enabled individually. Not all combinations work.
+       // The "regabi" GOEXPERIMENT is an alias for all "working"
+       // subexperiments.
+
+       // RegabiWrappers enables ABI wrappers for calling between
+       // ABI0 and ABIInternal functions. Without this, the ABIs are
+       // assumed to be identical so cross-ABI calls are direct.
+       RegabiWrappers bool
+       // RegabiG enables dedicated G and zero registers in
+       // ABIInternal.
+       //
+       // Requires wrappers because it makes the ABIs incompatible.
+       RegabiG bool
+       // RegabiReflect enables the register-passing paths in
+       // reflection calls. This is also gated by intArgRegs in
+       // reflect and runtime (which are disabled by default) so it
+       // can be used in targeted tests.
+       RegabiReflect bool
+       // RegabiDefer enables desugaring defer and go calls
+       // into argument-less closures.
+       RegabiDefer bool
+       // RegabiArgs enables register arguments/results in all
+       // compiled Go functions.
+       //
+       // Requires wrappers (to do ABI translation), g (because
+       // runtime assembly that's been ported to ABIInternal uses the
+       // G register), reflect (so reflection calls use registers),
+       // and defer (because the runtime doesn't support passing
+       // register arguments to defer/go).
+       RegabiArgs bool
+}
diff --git a/libgo/go/internal/goexperiment/mkconsts.go b/libgo/go/internal/goexperiment/mkconsts.go
new file mode 100644 (file)
index 0000000..204ca9d
--- /dev/null
@@ -0,0 +1,74 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build ignore
+// +build ignore
+
+// mkconsts generates const definition files for each GOEXPERIMENT.
+package main
+
+import (
+       "bytes"
+       "fmt"
+       "internal/goexperiment"
+       "log"
+       "os"
+       "reflect"
+       "strings"
+)
+
+func main() {
+       // Delete existing experiment constant files.
+       ents, err := os.ReadDir(".")
+       if err != nil {
+               log.Fatal(err)
+       }
+       for _, ent := range ents {
+               name := ent.Name()
+               if !strings.HasPrefix(name, "exp_") {
+                       continue
+               }
+               // Check that this is definitely a generated file.
+               data, err := os.ReadFile(name)
+               if err != nil {
+                       log.Fatalf("reading %s: %v", name, err)
+               }
+               if !bytes.Contains(data, []byte("Code generated by mkconsts")) {
+                       log.Fatalf("%s: expected generated file", name)
+               }
+               if err := os.Remove(name); err != nil {
+                       log.Fatal(err)
+               }
+       }
+
+       // Generate new experiment constant files.
+       rt := reflect.TypeOf(&goexperiment.Flags{}).Elem()
+       for i := 0; i < rt.NumField(); i++ {
+               f := rt.Field(i).Name
+               buildTag := "goexperiment." + strings.ToLower(f)
+               for _, val := range []bool{false, true} {
+                       name := fmt.Sprintf("exp_%s_%s.go", strings.ToLower(f), pick(val, "off", "on"))
+                       data := fmt.Sprintf(`// Code generated by mkconsts.go. DO NOT EDIT.
+
+//go:build %s%s
+// +build %s%s
+
+package goexperiment
+
+const %s = %v
+const %sInt = %s
+`, pick(val, "!", ""), buildTag, pick(val, "!", ""), buildTag, f, val, f, pick(val, "0", "1"))
+                       if err := os.WriteFile(name, []byte(data), 0666); err != nil {
+                               log.Fatalf("writing %s: %v", name, err)
+                       }
+               }
+       }
+}
+
+func pick(v bool, f, t string) string {
+       if v {
+               return t
+       }
+       return f
+}
index ce72bc389656a43681504ee97feff50b60526f1a..2338b78f3aa987a3e76c871c2eb3ca029d277f95 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build gc
 // +build gc
 
 package goroot
index 3530e59a15f88d1452c73bba2729d8a91e44cd1f..b1041da11d8b7c048b15c0758b6b334667bf950f 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build gccgo
 // +build gccgo
 
 package goroot
index 513be456bdaab7c631ab02d460159d59d5b626fc..4cc15688c0b70505e47ddd4ffce5c20a85852442 100644 (file)
@@ -9,4 +9,4 @@ package goversion
 //
 // It should be updated at the start of each development cycle to be
 // the version of the next Go 1.x release. See golang.org/issue/40705.
-const Version = 16
+const Version = 17
diff --git a/libgo/go/internal/itoa/itoa.go b/libgo/go/internal/itoa/itoa.go
new file mode 100644 (file)
index 0000000..c6062d9
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Simple conversions to avoid depending on strconv.
+
+package itoa
+
+// Itoa converts val to a decimal string.
+func Itoa(val int) string {
+       if val < 0 {
+               return "-" + Uitoa(uint(-val))
+       }
+       return Uitoa(uint(val))
+}
+
+// Uitoa converts val to a decimal string.
+func Uitoa(val uint) string {
+       if val == 0 { // avoid string allocation
+               return "0"
+       }
+       var buf [20]byte // big enough for 64bit value base 10
+       i := len(buf) - 1
+       for val >= 10 {
+               q := val / 10
+               buf[i] = byte('0' + val - q*10)
+               i--
+               val = q
+       }
+       // val < 10
+       buf[i] = byte('0' + val)
+       return string(buf[i:])
+}
diff --git a/libgo/go/internal/itoa/itoa_test.go b/libgo/go/internal/itoa/itoa_test.go
new file mode 100644 (file)
index 0000000..71931c1
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package itoa_test
+
+import (
+       "fmt"
+       "internal/itoa"
+       "math"
+       "testing"
+)
+
+var (
+       minInt64  int64  = math.MinInt64
+       maxInt64  int64  = math.MaxInt64
+       maxUint64 uint64 = math.MaxUint64
+)
+
+func TestItoa(t *testing.T) {
+       tests := []int{int(minInt64), math.MinInt32, -999, -100, -1, 0, 1, 100, 999, math.MaxInt32, int(maxInt64)}
+       for _, tt := range tests {
+               got := itoa.Itoa(tt)
+               want := fmt.Sprint(tt)
+               if want != got {
+                       t.Fatalf("Itoa(%d) = %s, want %s", tt, got, want)
+               }
+       }
+}
+
+func TestUitoa(t *testing.T) {
+       tests := []uint{0, 1, 100, 999, math.MaxUint32, uint(maxUint64)}
+       for _, tt := range tests {
+               got := itoa.Uitoa(tt)
+               want := fmt.Sprint(tt)
+               if want != got {
+                       t.Fatalf("Uitoa(%d) = %s, want %s", tt, got, want)
+               }
+       }
+}
index 01b242a4ea4e8d8fe147fbd9b3fc785d81796e13..5b9e5d402068ee6610efea08e3697d582e275239 100644 (file)
@@ -78,7 +78,7 @@ func CopyFileRange(dst, src *FD, remain int64) (written int64, handled bool, err
                        // Go supports Linux >= 2.6.33, so the system call
                        // may not be present.
                        //
-                       // If we see ENOSYS, we have certainly not transfered
+                       // If we see ENOSYS, we have certainly not transferred
                        // any data, so we can tell the caller that we
                        // couldn't handle the transfer and let them fall
                        // back to more generic code.
@@ -91,13 +91,13 @@ func CopyFileRange(dst, src *FD, remain int64) (written int64, handled bool, err
                        // Prior to Linux 5.3, it was not possible to
                        // copy_file_range across file systems. Similarly to
                        // the ENOSYS case above, if we see EXDEV, we have
-                       // not transfered any data, and we can let the caller
+                       // not transferred any data, and we can let the caller
                        // fall back to generic code.
                        //
                        // As for EINVAL, that is what we see if, for example,
                        // dst or src refer to a pipe rather than a regular
                        // file. This is another case where no data has been
-                       // transfered, so we consider it unhandled.
+                       // transferred, so we consider it unhandled.
                        //
                        // If src and dst are on CIFS, we can see EIO.
                        // See issue #42334.
index 922230b7e8d5d307f0e3ac98d261863429e4cd08..d03a2d24a7150644c017f6c2564d9099560f4971 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package poll
index e3bddb4bb270edadcd2f4c49ab310f453f2f30f0..c55f5f0df5057da6c96a0a68f3865217bfcaaae0 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build windows
 // +build windows
 
 package poll
index c40ffcd20f33689b1f53b0c760a38b2d0d9bc2df..bcc25dd666a7b292b16ecbf1e27e3b4aa9a98cf7 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !linux
 // +build !linux
 
 package poll_test
diff --git a/libgo/go/internal/poll/export_linux_test.go b/libgo/go/internal/poll/export_linux_test.go
new file mode 100644 (file)
index 0000000..7fba793
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Export guts for testing on linux.
+// Since testing imports os and os imports internal/poll,
+// the internal/poll tests can not be in package poll.
+
+package poll
+
+var (
+       GetPipe     = getPipe
+       PutPipe     = putPipe
+       NewPipe     = newPipe
+       DestroyPipe = destroyPipe
+)
+
+func GetPipeFds(p *SplicePipe) (int, int) {
+       return p.rfd, p.wfd
+}
+
+type SplicePipe = splicePipe
index 8ab4fd63f152239d39885f8fa6a8f9982e9bd4cb..1e714cde1c211e4ea0d8f3c87b14e625d8869873 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris || windows
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris windows
 
 // Export guts for testing on posix.
index 02664d9ea30698a02d0a803c71925569b42c7daf..e1125cba6633141a2f6afc0a058ddb9555d534e1 100644 (file)
@@ -33,3 +33,5 @@ func (mu *FDMutex) RWLock(read bool) bool {
 func (mu *FDMutex) RWUnlock(read bool) bool {
        return mu.rwunlock(read)
 }
+
+var Fcntl = fcntl
index 120fc1195fe6ec1fc71a7f3550d2dd23f442cda9..7bf0ddc792f642c163581289bbb16f20ffffb49a 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build js && wasm
 // +build js,wasm
 
 package poll
index ed00f76ce586cb056d3e0b7c69c61bdbb48780b0..e9a98e38022c1f732e08a445167453564fda6c14 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || solaris
 // +build aix darwin solaris
 
 package poll
index fb82b9bd53b5cfaa9b9f41542021519527a976b9..cd0061f2416afa2e7919bd382b5e7354b5b488d5 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build dragonfly || freebsd || hurd || linux || netbsd || openbsd
 // +build dragonfly freebsd hurd linux netbsd openbsd
 
 package poll
index b72ea3d55c2450ac216a7e599e1dc59ee741aec9..69a90054d3575f988499b44ec9e1311bd643ffd1 100644 (file)
@@ -13,11 +13,22 @@ import (
        "errors"
 )
 
-// ErrNetClosing is returned when a network descriptor is used after
-// it has been closed. Keep this string consistent because of issue
-// #4373: since historically programs have not been able to detect
+// errNetClosing is the type of the variable ErrNetClosing.
+// This is used to implement the net.Error interface.
+type errNetClosing struct{}
+
+// Error returns the error message for ErrNetClosing.
+// Keep this string consistent because of issue #4373:
+// since historically programs have not been able to detect
 // this error, they look for the string.
-var ErrNetClosing = errors.New("use of closed network connection")
+func (e errNetClosing) Error() string { return "use of closed network connection" }
+
+func (e errNetClosing) Timeout() bool   { return false }
+func (e errNetClosing) Temporary() bool { return false }
+
+// ErrNetClosing is returned when a network descriptor is used after
+// it has been closed.
+var ErrNetClosing = errNetClosing{}
 
 // ErrFileClosing is returned when a file descriptor is used after it
 // has been closed.
index 9be0f5462ea19792ec1262bc00df184449ec3dea..21f1de4ee940c5751ca0f79e3c41ee278cee6a33 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris
 // +build aix dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris
 
 package poll
index 287d11bd8c29f6a0bc46225183a669b06c03275e..3205ac8513ee3966f08e2fe177bd0ba927bc057f 100644 (file)
@@ -5,6 +5,7 @@
 package poll
 
 import (
+       "internal/itoa"
        "runtime"
        "sync"
        "syscall"
@@ -71,7 +72,7 @@ func (aio *asyncIO) Cancel() {
        if aio.pid == -1 {
                return
        }
-       f, e := syscall.Open("/proc/"+itoa(aio.pid)+"/note", syscall.O_WRONLY)
+       f, e := syscall.Open("/proc/"+itoa.Itoa(aio.pid)+"/note", syscall.O_WRONLY)
        if e != nil {
                return
        }
index d6b28e503cda489362f9c92c2430d3b538095170..760e24802e3fbd625515d7fc7d556f960c336375 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build js && wasm
 // +build js,wasm
 
 package poll
index 55aa304834e4ab87a0df6f605c08b853b336153d..f40b84565a6aad6a2294c651bd4e8d2d4be600e0 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || windows || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd windows solaris
 
 package poll
@@ -38,10 +39,6 @@ func (pd *pollDesc) init(fd *FD) error {
        serverInit.Do(runtime_pollServerInit)
        ctx, errno := runtime_pollOpen(uintptr(fd.Sysfd))
        if errno != 0 {
-               if ctx != 0 {
-                       runtime_pollUnblock(ctx)
-                       runtime_pollClose(ctx)
-               }
                return errnoErr(syscall.Errno(errno))
        }
        pd.runtimeCtx = ctx
index 16c2e50057d45af965e1a909f52861326a4d9307..fd64e53f4fdb0b878ebd8d57b2954ff4a4ede6f9 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows
 
 package poll
index dfcfd5c2f5874ab7b2758d9b3e4f1aa4201a8cb3..1dc3f0fe8749e5b75b2fb6ae762bf75cae488c07 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris || windows
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris windows
 
 package poll_test
index 013b7e5457446a751eef826193122a44977962c3..d8861dec5717598b3be42540754ed494bb178225 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris
 
 package poll
@@ -230,7 +231,7 @@ func (fd *FD) ReadFrom(p []byte) (int, syscall.Sockaddr, error) {
 }
 
 // ReadMsg wraps the recvmsg network call.
-func (fd *FD) ReadMsg(p []byte, oob []byte) (int, int, int, syscall.Sockaddr, error) {
+func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.Sockaddr, error) {
        if err := fd.readLock(); err != nil {
                return 0, 0, 0, nil, err
        }
@@ -239,7 +240,7 @@ func (fd *FD) ReadMsg(p []byte, oob []byte) (int, int, int, syscall.Sockaddr, er
                return 0, 0, 0, nil, err
        }
        for {
-               n, oobn, flags, sa, err := syscall.Recvmsg(fd.Sysfd, p, oob, 0)
+               n, oobn, sysflags, sa, err := syscall.Recvmsg(fd.Sysfd, p, oob, flags)
                if err != nil {
                        if err == syscall.EINTR {
                                continue
@@ -252,7 +253,7 @@ func (fd *FD) ReadMsg(p []byte, oob []byte) (int, int, int, syscall.Sockaddr, er
                        }
                }
                err = fd.eofError(n, err)
-               return n, oobn, flags, sa, err
+               return n, oobn, sysflags, sa, err
        }
 }
 
index d8c834f92993fdfd070a92d497c1a5e44f5950a9..4a5169527c42b0592d13e6c75df3fc9773647347 100644 (file)
@@ -1013,7 +1013,7 @@ func sockaddrToRaw(sa syscall.Sockaddr) (unsafe.Pointer, int32, error) {
 }
 
 // ReadMsg wraps the WSARecvMsg network call.
-func (fd *FD) ReadMsg(p []byte, oob []byte) (int, int, int, syscall.Sockaddr, error) {
+func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.Sockaddr, error) {
        if err := fd.readLock(); err != nil {
                return 0, 0, 0, nil, err
        }
@@ -1028,6 +1028,7 @@ func (fd *FD) ReadMsg(p []byte, oob []byte) (int, int, int, syscall.Sockaddr, er
        o.rsa = new(syscall.RawSockaddrAny)
        o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
        o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa))
+       o.msg.Flags = uint32(flags)
        n, err := execIO(o, func(o *operation) error {
                return windows.WSARecvMsg(o.fd.Sysfd, &o.msg, &o.qty, &o.o, nil)
        })
index e2024471d4fb0b6f61e02e363501e72120c3f540..805fa2ccd9ae79e706e15569aca5018c86d89385 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin
 // +build darwin
 
 package poll
index 1fa47ab1a32d973bd71485a842767ef8d90b8078..a0b11ed5ae972c5337660291b52bf52c04177cdb 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build illumos
 // +build illumos
 
 package poll
index daeec96c3857d5538915b45be94f2e03149f7377..87f284a56a1b21d72c24b361287bb2c84c6313c7 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build dragonfly || freebsd || linux || netbsd || openbsd
 // +build dragonfly freebsd linux netbsd openbsd
 
 package poll
index b8ce58d6ec546146d59289a70e3830fd97c975f6..18b445a4de3a8095e7dcb12694fdefc05ccf8d95 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build dragonfly || freebsd || hurd || illumos || linux || netbsd || openbsd
 // +build dragonfly freebsd hurd illumos linux netbsd openbsd
 
 package poll
index 7bb6f880052073d0a8b36f34b875865b4632804d..5223fb7120c90765c68b2492785e3f6c315d63fa 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris
 
 package poll
index 057067465bf37cffacef3c18b3e2aaec76b0b71e..f4058b298f35c5ae73ba5c3ff56fa920abcda1bc 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build illumos
 // +build illumos
 
 package poll
index 6f98947866a99c2037ef4f26ecb42f9430e116ca..6fd5d86630b6aa45a2c6ebfb4e4d34984c8fa583 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd
 // +build darwin dragonfly freebsd linux netbsd openbsd
 
 package poll
index 66005a9f5c952a68574a50d64cecab36b13728f1..3ba30a2154cd545c8616138ba6998a52359f00bb 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build dragonfly || freebsd
 // +build dragonfly freebsd
 
 package poll
@@ -22,7 +23,7 @@ func SendFile(dstFD *FD, src int, pos, remain int64) (int64, error) {
                return 0, err
        }
 
-       dst := int(dstFD.Sysfd)
+       dst := dstFD.Sysfd
        var written int64
        var err error
        for remain > 0 {
index 748c85131e688da0c42eb4d8f8fd65195a587a77..0a884307bb15bfbb7f40b9c4798d3f3c809e1468 100644 (file)
@@ -24,7 +24,7 @@ func SendFile(dstFD *FD, src int, pos, remain int64) (int64, error) {
                return 0, err
        }
 
-       dst := int(dstFD.Sysfd)
+       dst := dstFD.Sysfd
        var written int64
        var err error
        for remain > 0 {
index 09bc4b6fd87cc25fbdc8fabebd6fc30409dd5282..7daa11e3e67b5414db936a00af3be80267920922 100644 (file)
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This file implements sysSocket and accept for platforms that
-// provide a fast path for setting SetNonblock and CloseOnExec.
+// This file implements accept for platforms that provide a fast path for
+// setting SetNonblock and CloseOnExec.
 
+//go:build dragonfly || freebsd || hurd || illumos || linux || netbsd || openbsd
 // +build dragonfly freebsd hurd illumos linux netbsd openbsd
 
 package poll
index 2c6b68b7d3ef9d547413dff6151b058cca8325eb..975f84b4e606547989fc8cfb4de600822ba9f05f 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris || windows
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris windows
 
 package poll
index ef266d05e1e309159b3a995375556b708f277420..02a7859183813b2122243873d4febb08488c2a29 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package poll
index fc476bd0fbdc2d1e37ef7417c92f8393158a47d5..bcefa6b4655eaa3e9bfcdf5eead9d75dfba8a6c4 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris || windows
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris windows
 
 package poll
index ca772e91e5960e35bd6fd226faef8f3ea5bdb329..c7114f2657c99a2a9f7119e981e1770acdb84025 100644 (file)
@@ -5,6 +5,8 @@
 package poll
 
 import (
+       "runtime"
+       "sync"
        "sync/atomic"
        "syscall"
        "unsafe"
@@ -22,23 +24,23 @@ const (
 // Splice transfers at most remain bytes of data from src to dst, using the
 // splice system call to minimize copies of data from and to userspace.
 //
-// Splice creates a temporary pipe, to serve as a buffer for the data transfer.
+// Splice gets a pipe buffer from the pool or creates a new one if needed, to serve as a buffer for the data transfer.
 // src and dst must both be stream-oriented sockets.
 //
 // If err != nil, sc is the system call which caused the error.
 func Splice(dst, src *FD, remain int64) (written int64, handled bool, sc string, err error) {
-       prfd, pwfd, sc, err := newTempPipe()
+       p, sc, err := getPipe()
        if err != nil {
                return 0, false, sc, err
        }
-       defer destroyTempPipe(prfd, pwfd)
+       defer putPipe(p)
        var inPipe, n int
        for err == nil && remain > 0 {
                max := maxSpliceSize
                if int64(max) > remain {
                        max = int(remain)
                }
-               inPipe, err = spliceDrain(pwfd, src, max)
+               inPipe, err = spliceDrain(p.wfd, src, max)
                // The operation is considered handled if splice returns no
                // error, or an error other than EINVAL. An EINVAL means the
                // kernel does not support splice for the socket type of src.
@@ -51,13 +53,16 @@ func Splice(dst, src *FD, remain int64) (written int64, handled bool, sc string,
                // If inPipe == 0 && err == nil, src is at EOF, and the
                // transfer is complete.
                handled = handled || (err != syscall.EINVAL)
-               if err != nil || (inPipe == 0 && err == nil) {
+               if err != nil || inPipe == 0 {
                        break
                }
-               n, err = splicePump(dst, prfd, inPipe)
+               p.data += inPipe
+
+               n, err = splicePump(dst, p.rfd, inPipe)
                if n > 0 {
                        written += int64(n)
                        remain -= int64(n)
+                       p.data -= n
                }
        }
        if err != nil {
@@ -148,13 +153,58 @@ func splice(out int, in int, max int, flags int) (int, error) {
        return int(n), err
 }
 
+type splicePipe struct {
+       rfd  int
+       wfd  int
+       data int
+}
+
+// splicePipePool caches pipes to avoid high-frequency construction and destruction of pipe buffers.
+// The garbage collector will free all pipes in the sync.Pool periodically, thus we need to set up
+// a finalizer for each pipe to close its file descriptors before the actual GC.
+var splicePipePool = sync.Pool{New: newPoolPipe}
+
+func newPoolPipe() interface{} {
+       // Discard the error which occurred during the creation of pipe buffer,
+       // redirecting the data transmission to the conventional way utilizing read() + write() as a fallback.
+       p := newPipe()
+       if p == nil {
+               return nil
+       }
+       runtime.SetFinalizer(p, destroyPipe)
+       return p
+}
+
+// getPipe tries to acquire a pipe buffer from the pool or create a new one with newPipe() if it gets nil from the cache.
+//
+// Note that it may fail to create a new pipe buffer by newPipe(), in which case getPipe() will return a generic error
+// and system call name splice in a string as the indication.
+func getPipe() (*splicePipe, string, error) {
+       v := splicePipePool.Get()
+       if v == nil {
+               return nil, "splice", syscall.EINVAL
+       }
+       return v.(*splicePipe), "", nil
+}
+
+func putPipe(p *splicePipe) {
+       // If there is still data left in the pipe,
+       // then close and discard it instead of putting it back into the pool.
+       if p.data != 0 {
+               runtime.SetFinalizer(p, nil)
+               destroyPipe(p)
+               return
+       }
+       splicePipePool.Put(p)
+}
+
 var disableSplice unsafe.Pointer
 
-// newTempPipe sets up a temporary pipe for a splice operation.
-func newTempPipe() (prfd, pwfd int, sc string, err error) {
+// newPipe sets up a pipe for a splice operation.
+func newPipe() (sp *splicePipe) {
        p := (*bool)(atomic.LoadPointer(&disableSplice))
        if p != nil && *p {
-               return -1, -1, "splice", syscall.EINVAL
+               return nil
        }
 
        var fds [2]int
@@ -164,9 +214,11 @@ func newTempPipe() (prfd, pwfd int, sc string, err error) {
        // closed.
        const flags = syscall.O_CLOEXEC | syscall.O_NONBLOCK
        if err := syscall.Pipe2(fds[:], flags); err != nil {
-               return -1, -1, "pipe2", err
+               return nil
        }
 
+       sp = &splicePipe{rfd: fds[0], wfd: fds[1]}
+
        if p == nil {
                p = new(bool)
                defer atomic.StorePointer(&disableSplice, unsafe.Pointer(p))
@@ -174,25 +226,21 @@ func newTempPipe() (prfd, pwfd int, sc string, err error) {
                // F_GETPIPE_SZ was added in 2.6.35, which does not have the -EAGAIN bug.
                if syscall.F_GETPIPE_SZ == 0 {
                        *p = true
-                       destroyTempPipe(fds[0], fds[1])
-                       return -1, -1, "fcntl", syscall.EINVAL
+                       destroyPipe(sp)
+                       return nil
                }
                if _, err := fcntl(fds[0], syscall.F_GETPIPE_SZ, 0); err != nil {
                        *p = true
-                       destroyTempPipe(fds[0], fds[1])
-                       return -1, -1, "fcntl", err
+                       destroyPipe(sp)
+                       return nil
                }
        }
 
-       return fds[0], fds[1], "", nil
+       return
 }
 
-// destroyTempPipe destroys a temporary pipe.
-func destroyTempPipe(prfd, pwfd int) error {
-       err := CloseFunc(prfd)
-       err1 := CloseFunc(pwfd)
-       if err == nil {
-               return err1
-       }
-       return err
+// destroyPipe destroys a pipe.
+func destroyPipe(p *splicePipe) {
+       CloseFunc(p.rfd)
+       CloseFunc(p.wfd)
 }
diff --git a/libgo/go/internal/poll/splice_linux_test.go b/libgo/go/internal/poll/splice_linux_test.go
new file mode 100644 (file)
index 0000000..206a027
--- /dev/null
@@ -0,0 +1,122 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package poll_test
+
+import (
+       "internal/poll"
+       "runtime"
+       "syscall"
+       "testing"
+       "time"
+)
+
+// checkPipes returns true if all pipes are closed properly, false otherwise.
+func checkPipes(fds []int) bool {
+       for _, fd := range fds {
+               // Check if each pipe fd has been closed.
+               _, err := poll.Fcntl(fd, syscall.F_GETPIPE_SZ, 0)
+               if err == nil {
+                       return false
+               }
+       }
+       return true
+}
+
+func TestSplicePipePool(t *testing.T) {
+       if runtime.Compiler == "gccgo" {
+               t.Skip("gofrontend conservative stack collection causes this test to fail")
+       }
+
+       const N = 64
+       var (
+               p   *poll.SplicePipe
+               ps  []*poll.SplicePipe
+               fds []int
+               err error
+       )
+       for i := 0; i < N; i++ {
+               p, _, err = poll.GetPipe()
+               if err != nil {
+                       t.Skip("failed to create pipe, skip this test")
+               }
+               _, pwfd := poll.GetPipeFds(p)
+               fds = append(fds, pwfd)
+               ps = append(ps, p)
+       }
+       for _, p = range ps {
+               poll.PutPipe(p)
+       }
+       ps = nil
+       p = nil
+
+       // Exploit the timeout of "go test" as a timer for the subsequent verification.
+       timeout := 5 * time.Minute
+       if deadline, ok := t.Deadline(); ok {
+               timeout = deadline.Sub(time.Now())
+               timeout -= timeout / 10 // Leave 10% headroom for cleanup.
+       }
+       expiredTime := time.NewTimer(timeout)
+       defer expiredTime.Stop()
+
+       // Trigger garbage collection repeatedly, waiting for all pipes in sync.Pool
+       // to either be deallocated and closed, or to time out.
+       for {
+               runtime.GC()
+               time.Sleep(10 * time.Millisecond)
+               if checkPipes(fds) {
+                       break
+               }
+               select {
+               case <-expiredTime.C:
+                       t.Fatal("at least one pipe is still open")
+               default:
+               }
+       }
+}
+
+func BenchmarkSplicePipe(b *testing.B) {
+       b.Run("SplicePipeWithPool", func(b *testing.B) {
+               for i := 0; i < b.N; i++ {
+                       p, _, err := poll.GetPipe()
+                       if err != nil {
+                               continue
+                       }
+                       poll.PutPipe(p)
+               }
+       })
+       b.Run("SplicePipeWithoutPool", func(b *testing.B) {
+               for i := 0; i < b.N; i++ {
+                       p := poll.NewPipe()
+                       if p == nil {
+                               b.Skip("newPipe returned nil")
+                       }
+                       poll.DestroyPipe(p)
+               }
+       })
+}
+
+func BenchmarkSplicePipePoolParallel(b *testing.B) {
+       b.RunParallel(func(pb *testing.PB) {
+               for pb.Next() {
+                       p, _, err := poll.GetPipe()
+                       if err != nil {
+                               continue
+                       }
+                       poll.PutPipe(p)
+               }
+       })
+}
+
+func BenchmarkSplicePipeNativeParallel(b *testing.B) {
+       b.RunParallel(func(pb *testing.PB) {
+               for pb.Next() {
+                       p := poll.NewPipe()
+                       if p == nil {
+                               b.Skip("newPipe returned nil")
+                       }
+                       poll.DestroyPipe(p)
+               }
+       })
+}
index 21cb40db70e8aa142797d28edcd890878c1c1cb7..c98332d3dac63713b4093e31dbcf477a9c3b7266 100644 (file)
@@ -2,38 +2,11 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build plan9
 // +build plan9
 
-// Simple conversions to avoid depending on strconv.
-
 package poll
 
-// Convert integer to decimal string
-func itoa(val int) string {
-       if val < 0 {
-               return "-" + uitoa(uint(-val))
-       }
-       return uitoa(uint(val))
-}
-
-// Convert unsigned integer to decimal string
-func uitoa(val uint) string {
-       if val == 0 { // avoid string allocation
-               return "0"
-       }
-       var buf [20]byte // big enough for 64bit value base 10
-       i := len(buf) - 1
-       for val >= 10 {
-               q := val / 10
-               buf[i] = byte('0' + val - q*10)
-               i--
-               val = q
-       }
-       // val < 10
-       buf[i] = byte('0' + val)
-       return string(buf[i:])
-}
-
 // stringsHasSuffix is strings.HasSuffix. It reports whether s ends in
 // suffix.
 func stringsHasSuffix(s, suffix string) bool {
index 4b3c642173177ca446566a891d9a54b42461a381..7e6d422d621cda8bf433e593d3e22f19a0f89d47 100644 (file)
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This file implements sysSocket and accept for platforms that do not
-// provide a fast path for setting SetNonblock and CloseOnExec.
+// This file implements accept for platforms that do not provide a fast path for
+// setting SetNonblock and CloseOnExec.
 
+//go:build aix || darwin || (js && wasm) || (solaris && !illumos)
 // +build aix darwin js,wasm solaris,!illumos
 
 package poll
index 0123fc33de720b228c1a49ce5482ad7fecfb96f8..824de7569e8a2cc96b7c430f52fceb17ab71ad21 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || illumos || linux || netbsd || openbsd
 // +build darwin dragonfly freebsd illumos linux netbsd openbsd
 
 package poll
index d83c0165b22a8e9ef7c94504efa4b96f68f0f4ee..67b13057131ead99c9c2d40d026f56bd92db681f 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !race
 // +build !race
 
 package race
index 2e7d97beaa2e1da7d20863db11c2998e25c50640..40f2c99383fa999eb0c6fdd46ec7012e2cc87f7a 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build race
 // +build race
 
 package race
index 2ea28e0e4bc045daa5133795510168a2405f049b..e15f364fcd33f3086edb8bfd78cfad862cf2c84a 100644 (file)
@@ -982,21 +982,6 @@ func TestNames(t *testing.T) {
        }
 }
 
-type embed struct {
-       EmbedWithUnexpMeth
-}
-
-/*
-func TestNameBytesAreAligned(t *testing.T) {
-       typ := TypeOf(embed{})
-       b := FirstMethodNameBytes(typ)
-       v := uintptr(unsafe.Pointer(b))
-       if v%unsafe.Alignof((*byte)(nil)) != 0 {
-               t.Errorf("reflect.name.bytes pointer is not aligned: %x", v)
-       }
-}
-*/
-
 // TestUnaddressableField tests that the reflect package will not allow
 // a type from another package to be used as a named type with an
 // unexported field.
index 0c1b9944b7e5d13eef1219cb320b887aae378640..db1469d83712c0a9a9a36a77bf518e5ec171ec38 100644 (file)
@@ -67,7 +67,7 @@ type Type interface {
 }
 
 /*
- * These data structures are known to the compiler (../../cmd/internal/gc/reflect.go).
+ * These data structures are known to the compiler (../../cmd/internal/reflectdata/reflect.go).
  * A few are known to ../runtime/type.go to convey to debuggers.
  * They are also known to ../runtime/type.go.
  */
index 4bdbb55edbf98b3059d88b93042ca726288976dc..73289f1cd05a89201c8c0db3d0d62081db0c6d86 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !windows
 // +build !windows
 
 package execenv
index b50029c19839bf9dc034487369121d5faf1edebe..6c0654943e690613175113c4a97abe1292927a0e 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build windows
 // +build windows
 
 package execenv
index a602d3ac5bf78efec20bd53faafc857f7b426956..5059af3c57faa77271cf18b9f1d90aa5e7314957 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//-go:build linux || openbsd || netbsd || dragonfly
 // -build linux openbsd netbsd dragonfly
 
 package unix
diff --git a/libgo/go/internal/syscall/unix/getentropy_darwin.go b/libgo/go/internal/syscall/unix/getentropy_darwin.go
new file mode 100644 (file)
index 0000000..e1a410a
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package unix
+
+import (
+       "internal/abi"
+       "syscall"
+       "unsafe"
+)
+
+//go:cgo_import_dynamic libc_getentropy getentropy "/usr/lib/libSystem.B.dylib"
+
+func libc_getentropy_trampoline()
+
+// GetEntropy calls the macOS getentropy system call.
+func GetEntropy(p []byte) error {
+       _, _, errno := syscall_syscall(abi.FuncPCABI0(libc_getentropy_trampoline),
+               uintptr(unsafe.Pointer(&p[0])),
+               uintptr(len(p)),
+               0)
+       if errno != 0 {
+               return errno
+       }
+       return nil
+}
+
+//go:linkname syscall_syscall syscall.syscall
+func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
diff --git a/libgo/go/internal/syscall/unix/getrandom.go b/libgo/go/internal/syscall/unix/getrandom.go
new file mode 100644 (file)
index 0000000..d2c58c0
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build dragonfly || freebsd || linux
+// +build dragonfly freebsd linux
+
+package unix
+
+import (
+       "sync/atomic"
+       "syscall"
+       "unsafe"
+)
+
+var getrandomUnsupported int32 // atomic
+
+// GetRandomFlag is a flag supported by the getrandom system call.
+type GetRandomFlag uintptr
+
+// GetRandom calls the getrandom system call.
+func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) {
+       if len(p) == 0 {
+               return 0, nil
+       }
+       if atomic.LoadInt32(&getrandomUnsupported) != 0 {
+               return 0, syscall.ENOSYS
+       }
+       r1, _, errno := syscall.Syscall(getrandomTrap,
+               uintptr(unsafe.Pointer(&p[0])),
+               uintptr(len(p)),
+               uintptr(flags))
+       if errno != 0 {
+               if errno == syscall.ENOSYS {
+                       atomic.StoreInt32(&getrandomUnsupported, 1)
+               }
+               return 0, errno
+       }
+       return int(r1), nil
+}
diff --git a/libgo/go/internal/syscall/unix/getrandom_dragonfly.go b/libgo/go/internal/syscall/unix/getrandom_dragonfly.go
new file mode 100644 (file)
index 0000000..fbf78f9
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package unix
+
+// DragonFlyBSD getrandom system call number.
+const getrandomTrap uintptr = 550
+
+const (
+       // GRND_RANDOM is only set for portability purpose, no-op on DragonFlyBSD.
+       GRND_RANDOM GetRandomFlag = 0x0001
+
+       // GRND_NONBLOCK means return EAGAIN rather than blocking.
+       GRND_NONBLOCK GetRandomFlag = 0x0002
+)
index f1ba5730c96953281b37c276d307aac548bf12da..8c4f3dff82377e5324c400fb98fd3f5a9b1b4681 100644 (file)
@@ -4,19 +4,8 @@
 
 package unix
 
-import (
-       "sync/atomic"
-       "syscall"
-       "unsafe"
-)
-
-var randomUnsupported int32 // atomic
-
 // FreeBSD getrandom system call number.
-const randomTrap uintptr = 563
-
-// GetRandomFlag is a flag supported by the getrandom system call.
-type GetRandomFlag uintptr
+const getrandomTrap uintptr = 563
 
 const (
        // GRND_NONBLOCK means return EAGAIN rather than blocking.
@@ -25,24 +14,3 @@ const (
        // GRND_RANDOM is only set for portability purpose, no-op on FreeBSD.
        GRND_RANDOM GetRandomFlag = 0x0002
 )
-
-// GetRandom calls the FreeBSD getrandom system call.
-func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) {
-       if len(p) == 0 {
-               return 0, nil
-       }
-       if atomic.LoadInt32(&randomUnsupported) != 0 {
-               return 0, syscall.ENOSYS
-       }
-       r1, _, errno := syscall.Syscall(randomTrap,
-               uintptr(unsafe.Pointer(&p[0])),
-               uintptr(len(p)),
-               uintptr(flags))
-       if errno != 0 {
-               if errno == syscall.ENOSYS {
-                       atomic.StoreInt32(&randomUnsupported, 1)
-               }
-               return 0, errno
-       }
-       return int(r1), nil
-}
index 490d516978daea8b9e2f7facbfdc44a4e60d2df3..8ccd8d328af1feb980ac35c062f944ca3c0219f6 100644 (file)
@@ -4,17 +4,6 @@
 
 package unix
 
-import (
-       "sync/atomic"
-       "syscall"
-       "unsafe"
-)
-
-var randomUnsupported int32 // atomic
-
-// GetRandomFlag is a flag supported by the getrandom system call.
-type GetRandomFlag uintptr
-
 const (
        // GRND_NONBLOCK means return EAGAIN rather than blocking.
        GRND_NONBLOCK GetRandomFlag = 0x0001
@@ -22,25 +11,3 @@ const (
        // GRND_RANDOM means use the /dev/random pool instead of /dev/urandom.
        GRND_RANDOM GetRandomFlag = 0x0002
 )
-
-// GetRandom calls the Linux getrandom system call.
-// See https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=c6e9d6f38894798696f23c8084ca7edbf16ee895
-func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) {
-       if len(p) == 0 {
-               return 0, nil
-       }
-       if atomic.LoadInt32(&randomUnsupported) != 0 {
-               return 0, syscall.ENOSYS
-       }
-       r1, _, errno := syscall.Syscall(getrandomTrap,
-               uintptr(unsafe.Pointer(&p[0])),
-               uintptr(len(p)),
-               uintptr(flags))
-       if errno != 0 {
-               if errno == syscall.ENOSYS {
-                       atomic.StoreInt32(&randomUnsupported, 1)
-               }
-               return 0, errno
-       }
-       return int(r1), nil
-}
diff --git a/libgo/go/internal/syscall/unix/getrandom_solaris.go b/libgo/go/internal/syscall/unix/getrandom_solaris.go
new file mode 100644 (file)
index 0000000..caf9b60
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package unix
+
+import (
+       "sync/atomic"
+       "syscall"
+       "unsafe"
+)
+
+//extern getrandom
+func libc_getrandom(*byte, uintptr, uint32) uintptr
+
+// GetRandomFlag is a flag supported by the getrandom system call.
+type GetRandomFlag uintptr
+
+const (
+       // GRND_NONBLOCK means return EAGAIN rather than blocking.
+       GRND_NONBLOCK GetRandomFlag = 0x0001
+
+       // GRND_RANDOM means use the /dev/random pool instead of /dev/urandom.
+       GRND_RANDOM GetRandomFlag = 0x0002
+)
+
+// GetRandom calls the getrandom system call.
+func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) {
+       if len(p) == 0 {
+               return 0, nil
+       }
+       if atomic.LoadInt32(&getrandomUnsupported) != 0 {
+               return 0, syscall.ENOSYS
+       }
+       syscall.Entersyscall()
+       r1 := libc_getrandom(&p[0], uintptr(len(p)), uint32(flags))
+       syscall.Exitsyscall()
+       if r1 == 0 {
+               errno := syscall.GetErrno()
+               if errno == syscall.ENOSYS {
+                       atomic.StoreInt32(&getrandomUnsupported, 1)
+               }
+               return 0, errno
+       }
+       return int(r1), nil
+}
index 1734cdc5124f2ef8e3fc2d6ab368968a4b8d74a8..dc2e107885bc7778bc0c5caaccdb5e2007bc08ce 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build dragonfly || freebsd || hurd || linux || netbsd || openbsd
 // +build dragonfly freebsd hurd linux netbsd openbsd
 
 package unix
index a360b53c3dbfac3f89b1da05465bf8e481d0c2d1..a5a5080d46153a9bed00ede4cfd324b177b11e4d 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build js && wasm
 // +build js,wasm
 
 package unix
index 464314d31976df61895acce89b5a7ca08d048a75..876fb16d8c267d5f8657668616293082352ae2a9 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || solaris
 // +build aix darwin solaris
 
 package unix
index 3d34fdb73e38e2dae6563d68572666a62d20ce27..d8db1bbeff1e3d494c25dd3ad862cba4b43664a8 100644 (file)
@@ -2,8 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build linux && (arm64 || riscv64 || arm64be || nios2 || riscv)
 // +build linux
-// +build arm64 arm64be nios2 riscv riscv64
+// +build arm64 riscv64 arm64be nios2 riscv
 
 package unix
 
index 6680942cb8be1626babfff9a885ce3873ae5581f..f353d4d73e48f606c6e04b6565ad8985941f55c6 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build mips64 || mips64le
 // +build mips64 mips64le
 
 package unix
index 185d8320c9e039b4cebaef55edc614a767fa3d9e..4ed471532a2a415edb4bd26a1808557720d8f9a1 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build mips || mipsle
 // +build mips mipsle
 
 package unix
index aa2e81a667e6e7ab870c600329f5da20c0b6344d..5befa08e40304fd1402851feda2365b533c7caca 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ppc || ppc64 || ppc64le
 // +build ppc ppc64 ppc64le
 
 package unix
index e3d4d16b33e5fc152fb12c9bee41aa563b05da3e..02f08f57c717c590bc370457b47534e11c07f0ab 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build cgo
 // +build cgo
 
 package testenv
index ccb5d5585f6d971846b36e36c5bd8bd5d29f2317..846ec9385647efabf512f47b8b9361d6b2a8ae95 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !windows
 // +build !windows
 
 package testenv
index c371ff3092a776aebcb4e527ecaa966ab8894fe1..254f20137b4ee771ae8530579ff9259da876922e 100644 (file)
@@ -1042,8 +1042,8 @@ const (
        EvGoSysBlock        = 30 // syscall blocks [timestamp]
        EvGoWaiting         = 31 // denotes that goroutine is blocked when tracing starts [timestamp, goroutine id]
        EvGoInSyscall       = 32 // denotes that goroutine is in syscall when tracing starts [timestamp, goroutine id]
-       EvHeapAlloc         = 33 // memstats.heap_live change [timestamp, heap_alloc]
-       EvNextGC            = 34 // memstats.next_gc change [timestamp, next_gc]
+       EvHeapAlloc         = 33 // gcController.heapLive change [timestamp, heap live bytes]
+       EvHeapGoal          = 34 // gcController.heapGoal change [timestamp, heap goal bytes]
        EvTimerGoroutine    = 35 // denotes timer goroutine [timer goroutine id]
        EvFutileWakeup      = 36 // denotes that the previous wakeup of this goroutine was futile [timestamp]
        EvString            = 37 // string dictionary entry [ID, length, string]
@@ -1102,7 +1102,7 @@ var EventDescriptions = [EvCount]struct {
        EvGoWaiting:         {"GoWaiting", 1005, false, []string{"g"}, nil},
        EvGoInSyscall:       {"GoInSyscall", 1005, false, []string{"g"}, nil},
        EvHeapAlloc:         {"HeapAlloc", 1005, false, []string{"mem"}, nil},
-       EvNextGC:            {"NextGC", 1005, false, []string{"mem"}, nil},
+       EvHeapGoal:          {"HeapGoal", 1005, false, []string{"mem"}, nil},
        EvTimerGoroutine:    {"TimerGoroutine", 1005, false, []string{"g"}, nil}, // in 1.5 format it was {"g", "unused"}
        EvFutileWakeup:      {"FutileWakeup", 1005, false, []string{}, nil},
        EvString:            {"String", 1007, false, []string{}, nil},
index 6d338acd1401354187a66f16625e443359204591..a18df9feff696510d54adc9f53d135d15f07b23e 100644 (file)
@@ -103,7 +103,9 @@ func ExampleReadFull() {
 }
 
 func ExampleWriteString() {
-       io.WriteString(os.Stdout, "Hello World")
+       if _, err := io.WriteString(os.Stdout, "Hello World"); err != nil {
+               log.Fatal(err)
+       }
 
        // Output: Hello World
 }
diff --git a/libgo/go/io/fs/example_test.go b/libgo/go/io/fs/example_test.go
new file mode 100644 (file)
index 0000000..c902703
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package fs_test
+
+import (
+       "fmt"
+       "io/fs"
+       "log"
+       "os"
+)
+
+func ExampleWalkDir() {
+       root := "/usr/local/go/bin"
+       fileSystem := os.DirFS(root)
+
+       fs.WalkDir(fileSystem, ".", func(path string, d fs.DirEntry, err error) error {
+               if err != nil {
+                       log.Fatal(err)
+               }
+               fmt.Println(path)
+               return nil
+       })
+}
index 3d2e2ee2ac953020780614885c0279705f56dbbe..e1be32478e02986b59ba7f57945df7cfdd784391 100644 (file)
@@ -73,8 +73,8 @@ func ValidPath(name string) bool {
 
 // A File provides access to a single file.
 // The File interface is the minimum implementation required of the file.
-// A file may implement additional interfaces, such as
-// ReadDirFile, ReaderAt, or Seeker, to provide additional or optimized functionality.
+// Directory files should also implement ReadDirFile.
+// A file may implement io.ReaderAt or io.Seeker as optimizations.
 type File interface {
        Stat() (FileInfo, error)
        Read([]byte) (int, error)
index 3a5aa6d86a6d73adb98ec4983e8b8215a836fb9a..2b10ddb0a3f407dd5c08387f1d8d1902d5eeace1 100644 (file)
@@ -45,3 +45,33 @@ func ReadDir(fsys FS, name string) ([]DirEntry, error) {
        sort.Slice(list, func(i, j int) bool { return list[i].Name() < list[j].Name() })
        return list, err
 }
+
+// dirInfo is a DirEntry based on a FileInfo.
+type dirInfo struct {
+       fileInfo FileInfo
+}
+
+func (di dirInfo) IsDir() bool {
+       return di.fileInfo.IsDir()
+}
+
+func (di dirInfo) Type() FileMode {
+       return di.fileInfo.Mode().Type()
+}
+
+func (di dirInfo) Info() (FileInfo, error) {
+       return di.fileInfo, nil
+}
+
+func (di dirInfo) Name() string {
+       return di.fileInfo.Name()
+}
+
+// FileInfoToDirEntry returns a DirEntry that returns information from info.
+// If info is nil, FileInfoToDirEntry returns nil.
+func FileInfoToDirEntry(info FileInfo) DirEntry {
+       if info == nil {
+               return nil
+       }
+       return dirInfo{fileInfo: info}
+}
index 405bfa67ca40583bcb096e06e09e6f9893d728c5..a2b2c121ffadbd32280630a75df42d6b2e12e581 100644 (file)
@@ -6,7 +6,10 @@ package fs_test
 
 import (
        . "io/fs"
+       "os"
        "testing"
+       "testing/fstest"
+       "time"
 )
 
 type readDirOnly struct{ ReadDirFS }
@@ -41,3 +44,50 @@ func TestReadDir(t *testing.T) {
        dirs, err = ReadDir(sub, ".")
        check("sub(.)", dirs, err)
 }
+
+func TestFileInfoToDirEntry(t *testing.T) {
+       testFs := fstest.MapFS{
+               "notadir.txt": {
+                       Data:    []byte("hello, world"),
+                       Mode:    0,
+                       ModTime: time.Now(),
+                       Sys:     &sysValue,
+               },
+               "adir": {
+                       Data:    nil,
+                       Mode:    os.ModeDir,
+                       ModTime: time.Now(),
+                       Sys:     &sysValue,
+               },
+       }
+
+       tests := []struct {
+               path     string
+               wantMode FileMode
+               wantDir  bool
+       }{
+               {path: "notadir.txt", wantMode: 0, wantDir: false},
+               {path: "adir", wantMode: os.ModeDir, wantDir: true},
+       }
+
+       for _, test := range tests {
+               test := test
+               t.Run(test.path, func(t *testing.T) {
+                       fi, err := Stat(testFs, test.path)
+                       if err != nil {
+                               t.Fatal(err)
+                       }
+
+                       dirEntry := FileInfoToDirEntry(fi)
+                       if g, w := dirEntry.Type(), test.wantMode; g != w {
+                               t.Errorf("FileMode mismatch: got=%v, want=%v", g, w)
+                       }
+                       if g, w := dirEntry.Name(), test.path; g != w {
+                               t.Errorf("Name mismatch: got=%v, want=%v", g, w)
+                       }
+                       if g, w := dirEntry.IsDir(), test.wantDir; g != w {
+                               t.Errorf("IsDir mismatch: got=%v, want=%v", g, w)
+                       }
+               })
+       }
+}
index 7ee9eadac4d92226c6cd203a6d5491c0ccd4ccb4..d3c181c0a9e60461acdeac9877e81d73f8d0ab83 100644 (file)
@@ -15,6 +15,9 @@ type ReadFileFS interface {
        // A successful call returns a nil error, not io.EOF.
        // (Because ReadFile reads the whole file, the expected EOF
        // from the final Read is not treated as an error to be reported.)
+       //
+       // The caller is permitted to modify the returned byte slice.
+       // This method should return a copy of the underlying data.
        ReadFile(name string) ([]byte, error)
 }
 
index 64cdffe6dec76251fc682dd7ec488f19365d2b7e..ae20e030a93de2f761e00744d14992065b0dfb66 100644 (file)
@@ -19,10 +19,10 @@ type SubFS interface {
 
 // Sub returns an FS corresponding to the subtree rooted at fsys's dir.
 //
-// If fs implements SubFS, Sub calls returns fsys.Sub(dir).
-// Otherwise, if dir is ".", Sub returns fsys unchanged.
+// If dir is ".", Sub returns fsys unchanged.
+// Otherwise, if fs implements SubFS, Sub returns fsys.Sub(dir).
 // Otherwise, Sub returns a new FS implementation sub that,
-// in effect, implements sub.Open(dir) as fsys.Open(path.Join(dir, name)).
+// in effect, implements sub.Open(name) as fsys.Open(path.Join(dir, name)).
 // The implementation also translates calls to ReadDir, ReadFile, and Glob appropriately.
 //
 // Note that Sub(os.DirFS("/"), "prefix") is equivalent to os.DirFS("/prefix")
@@ -68,7 +68,7 @@ func (f *subFS) shorten(name string) (rel string, ok bool) {
        return "", false
 }
 
-// fixErr shortens any reported names in PathErrors by stripping dir.
+// fixErr shortens any reported names in PathErrors by stripping f.dir.
 func (f *subFS) fixErr(err error) error {
        if e, ok := err.(*PathError); ok {
                if short, ok := f.shorten(e.Path); ok {
@@ -125,3 +125,14 @@ func (f *subFS) Glob(pattern string) ([]string, error) {
        }
        return list, f.fixErr(err)
 }
+
+func (f *subFS) Sub(dir string) (FS, error) {
+       if dir == "." {
+               return f, nil
+       }
+       full, err := f.fullName("sub", dir)
+       if err != nil {
+               return nil, err
+       }
+       return &subFS{f.fsys, full}, nil
+}
index ebc4e50fb319deaa05241ab84a04266742a0d08e..5e127e71cd96da16f324b6cb90a7e185cc61bc87 100644 (file)
@@ -6,7 +6,6 @@ package fs_test
 
 import (
        . "io/fs"
-       "io/ioutil"
        "os"
        pathpkg "path"
        "testing"
@@ -96,11 +95,7 @@ func mark(entry DirEntry, err error, errors *[]error, clear bool) error {
 }
 
 func TestWalkDir(t *testing.T) {
-       tmpDir, err := ioutil.TempDir("", "TestWalk")
-       if err != nil {
-               t.Fatal("creating temp dir:", err)
-       }
-       defer os.RemoveAll(tmpDir)
+       tmpDir := t.TempDir()
 
        origDir, err := os.Getwd()
        if err != nil {
index ffd3cedc254ee8b71cd6e7de18b9abdf8ffb42b6..2724321ed9d42012e2e0d3de78c673fd4a063fcc 100644 (file)
@@ -566,7 +566,7 @@ func (t *teeReader) Read(p []byte) (n int, err error) {
        return
 }
 
-// Discard is an Writer on which all Write calls succeed
+// Discard is a Writer on which all Write calls succeed
 // without doing anything.
 var Discard Writer = discard{}
 
index af7c6fd7c1a2dd5a5ec2c31786eeed44409b9395..c43db2c080d69e01c5eb2eee869b877ca3aa07b8 100644 (file)
@@ -5,38 +5,9 @@
 package ioutil
 
 import (
-       "errors"
        "os"
-       "path/filepath"
-       "strconv"
-       "strings"
-       "sync"
-       "time"
 )
 
-// Random number state.
-// We generate random temporary file names so that there's a good
-// chance the file doesn't exist yet - keeps the number of tries in
-// TempFile to a minimum.
-var rand uint32
-var randmu sync.Mutex
-
-func reseed() uint32 {
-       return uint32(time.Now().UnixNano() + int64(os.Getpid()))
-}
-
-func nextRandom() string {
-       randmu.Lock()
-       r := rand
-       if r == 0 {
-               r = reseed()
-       }
-       r = r*1664525 + 1013904223 // constants from Numerical Recipes
-       rand = r
-       randmu.Unlock()
-       return strconv.Itoa(int(1e9 + r%1e9))[1:]
-}
-
 // TempFile creates a new temporary file in the directory dir,
 // opens the file for reading and writing, and returns the resulting *os.File.
 // The filename is generated by taking pattern and adding a random
@@ -48,48 +19,10 @@ func nextRandom() string {
 // will not choose the same file. The caller can use f.Name()
 // to find the pathname of the file. It is the caller's responsibility
 // to remove the file when no longer needed.
+//
+// As of Go 1.17, this function simply calls os.CreateTemp.
 func TempFile(dir, pattern string) (f *os.File, err error) {
-       if dir == "" {
-               dir = os.TempDir()
-       }
-
-       prefix, suffix, err := prefixAndSuffix(pattern)
-       if err != nil {
-               return
-       }
-
-       nconflict := 0
-       for i := 0; i < 10000; i++ {
-               name := filepath.Join(dir, prefix+nextRandom()+suffix)
-               f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
-               if os.IsExist(err) {
-                       if nconflict++; nconflict > 10 {
-                               randmu.Lock()
-                               rand = reseed()
-                               randmu.Unlock()
-                       }
-                       continue
-               }
-               break
-       }
-       return
-}
-
-var errPatternHasSeparator = errors.New("pattern contains path separator")
-
-// prefixAndSuffix splits pattern by the last wildcard "*", if applicable,
-// returning prefix as the part before "*" and suffix as the part after "*".
-func prefixAndSuffix(pattern string) (prefix, suffix string, err error) {
-       if strings.ContainsRune(pattern, os.PathSeparator) {
-               err = errPatternHasSeparator
-               return
-       }
-       if pos := strings.LastIndex(pattern, "*"); pos != -1 {
-               prefix, suffix = pattern[:pos], pattern[pos+1:]
-       } else {
-               prefix = pattern
-       }
-       return
+       return os.CreateTemp(dir, pattern)
 }
 
 // TempDir creates a new temporary directory in the directory dir.
@@ -101,37 +34,8 @@ func prefixAndSuffix(pattern string) (prefix, suffix string, err error) {
 // Multiple programs calling TempDir simultaneously
 // will not choose the same directory. It is the caller's responsibility
 // to remove the directory when no longer needed.
+//
+// As of Go 1.17, this function simply calls os.MkdirTemp.
 func TempDir(dir, pattern string) (name string, err error) {
-       if dir == "" {
-               dir = os.TempDir()
-       }
-
-       prefix, suffix, err := prefixAndSuffix(pattern)
-       if err != nil {
-               return
-       }
-
-       nconflict := 0
-       for i := 0; i < 10000; i++ {
-               try := filepath.Join(dir, prefix+nextRandom()+suffix)
-               err = os.Mkdir(try, 0700)
-               if os.IsExist(err) {
-                       if nconflict++; nconflict > 10 {
-                               randmu.Lock()
-                               rand = reseed()
-                               randmu.Unlock()
-                       }
-                       continue
-               }
-               if os.IsNotExist(err) {
-                       if _, err := os.Stat(dir); os.IsNotExist(err) {
-                               return "", err
-                       }
-               }
-               if err == nil {
-                       name = try
-               }
-               break
-       }
-       return
+       return os.MkdirTemp(dir, pattern)
 }
index 440c7cffc67d32b127deab57b003199149744767..5cef18c33b0c1eaebb29ab3a1b2c9fbe0619f2d5 100644 (file)
@@ -50,6 +50,9 @@ func TestTempFile_pattern(t *testing.T) {
        }
 }
 
+// This string is from os.errPatternHasSeparator.
+const patternHasSeparator = "pattern contains path separator"
+
 func TestTempFile_BadPattern(t *testing.T) {
        tmpDir, err := TempDir("", t.Name())
        if err != nil {
@@ -81,9 +84,8 @@ func TestTempFile_BadPattern(t *testing.T) {
                        if tt.wantErr {
                                if err == nil {
                                        t.Errorf("Expected an error for pattern %q", tt.pattern)
-                               }
-                               if g, w := err, ErrPatternHasSeparator; g != w {
-                                       t.Errorf("Error mismatch: got %#v, want %#v for pattern %q", g, w, tt.pattern)
+                               } else if !strings.Contains(err.Error(), patternHasSeparator) {
+                                       t.Errorf("Error mismatch: got %#v, want %q for pattern %q", err, patternHasSeparator, tt.pattern)
                                }
                        } else if err != nil {
                                t.Errorf("Unexpected error %v for pattern %q", err, tt.pattern)
@@ -183,9 +185,8 @@ func TestTempDir_BadPattern(t *testing.T) {
                        if tt.wantErr {
                                if err == nil {
                                        t.Errorf("Expected an error for pattern %q", tt.pattern)
-                               }
-                               if g, w := err, ErrPatternHasSeparator; g != w {
-                                       t.Errorf("Error mismatch: got %#v, want %#v for pattern %q", g, w, tt.pattern)
+                               } else if !strings.Contains(err.Error(), patternHasSeparator) {
+                                       t.Errorf("Error mismatch: got %#v, want %q for pattern %q", err, patternHasSeparator, tt.pattern)
                                }
                        } else if err != nil {
                                t.Errorf("Unexpected error %v for pattern %q", err, tt.pattern)
index 4288d37dee03ab13c137f2539cf083721afbf09c..993976569e2423b1e9649cb5151486eb289e6ce4 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !windows && !plan9
 // +build !windows,!plan9
 
 package syslog_test
index 97c10f31df37de41fa7da9d13f5c434165065e33..6abd4ad124863d014de91a3a1e2037a121b65f32 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !windows && !plan9
 // +build !windows,!plan9
 
 package syslog
index 207bcf57c17ced1dec0c97a2d84e07e60fe933d9..62c62508452a06dcbf10905f9aa09035f52dfe02 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !windows && !plan9 && !js
 // +build !windows,!plan9,!js
 
 package syslog
index 940e92e5e66dbebc9302ea2b141fe41ec54b123c..a3654c59d2eadff537c65422a202f0004100f31f 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !windows && !plan9 && !solaris && !irix
 // +build !windows,!plan9,!solaris,!irix
 
 package syslog
index 3aae0373c76ec7fcb4e0f75054f431f8eb4c27a1..55c805e199ed9cd200c3a5322e5a3b11ce917f9e 100644 (file)
@@ -2067,6 +2067,21 @@ var fmaC = []struct{ x, y, z, want float64 }{
        {-7.751454006381804e-05, 5.588653777189071e-308, -2.2207280111272877e-308, -2.2211612130544025e-308},
 }
 
+var sqrt32 = []float32{
+       0,
+       float32(Copysign(0, -1)),
+       float32(NaN()),
+       float32(Inf(1)),
+       float32(Inf(-1)),
+       1,
+       2,
+       -2,
+       4.9790119248836735e+00,
+       7.7388724745781045e+00,
+       -2.7688005719200159e-01,
+       -5.0106036182710749e+00,
+}
+
 func tolerance(a, b, e float64) bool {
        // Multiplying by e here can underflow denormal values to zero.
        // Check a==b so that at least if a and b are small and identical
@@ -3181,6 +3196,34 @@ func TestFloatMinMax(t *testing.T) {
        }
 }
 
+func TestFloatMinima(t *testing.T) {
+       if q := float32(SmallestNonzeroFloat32 / 2); q != 0 {
+               t.Errorf("float32(SmallestNonzeroFloat32 / 2) = %g, want 0", q)
+       }
+       if q := float64(SmallestNonzeroFloat64 / 2); q != 0 {
+               t.Errorf("float64(SmallestNonzeroFloat64 / 2) = %g, want 0", q)
+       }
+}
+
+var indirectSqrt = Sqrt
+
+// TestFloat32Sqrt checks the correctness of the float32 square root optimization result.
+func TestFloat32Sqrt(t *testing.T) {
+       for _, v := range sqrt32 {
+               want := float32(indirectSqrt(float64(v)))
+               got := float32(Sqrt(float64(v)))
+               if IsNaN(float64(want)) {
+                       if !IsNaN(float64(got)) {
+                               t.Errorf("got=%#v want=NaN, v=%#v", got, v)
+                       }
+                       continue
+               }
+               if got != want {
+                       t.Errorf("got=%#v want=%#v, v=%#v", got, want, v)
+               }
+       }
+}
+
 // Benchmarks
 
 // Global exported variables are used to store the
index c28651e5f9f2c31ab3381a5a86efa1caaaf5878e..635273421eed1df15cd65e1841fa34bf150603ef 100644 (file)
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 package math
 
 import "internal/cpu"
 
+func expTrampolineSetup(x float64) float64
+func expAsm(x float64) float64
+
+func logTrampolineSetup(x float64) float64
+func logAsm(x float64) float64
+
+// Below here all functions are grouped in stubs.go for other
+// architectures.
+
+const haveArchLog10 = true
+
+func archLog10(x float64) float64
 func log10TrampolineSetup(x float64) float64
 func log10Asm(x float64) float64
 
+const haveArchCos = true
+
+func archCos(x float64) float64
 func cosTrampolineSetup(x float64) float64
 func cosAsm(x float64) float64
 
+const haveArchCosh = true
+
+func archCosh(x float64) float64
 func coshTrampolineSetup(x float64) float64
 func coshAsm(x float64) float64
 
+const haveArchSin = true
+
+func archSin(x float64) float64
 func sinTrampolineSetup(x float64) float64
 func sinAsm(x float64) float64
 
+const haveArchSinh = true
+
+func archSinh(x float64) float64
 func sinhTrampolineSetup(x float64) float64
 func sinhAsm(x float64) float64
 
+const haveArchTanh = true
+
+func archTanh(x float64) float64
 func tanhTrampolineSetup(x float64) float64
 func tanhAsm(x float64) float64
 
+const haveArchLog1p = true
+
+func archLog1p(x float64) float64
 func log1pTrampolineSetup(x float64) float64
 func log1pAsm(x float64) float64
 
+const haveArchAtanh = true
+
+func archAtanh(x float64) float64
 func atanhTrampolineSetup(x float64) float64
 func atanhAsm(x float64) float64
 
+const haveArchAcos = true
+
+func archAcos(x float64) float64
 func acosTrampolineSetup(x float64) float64
 func acosAsm(x float64) float64
 
+const haveArchAcosh = true
+
+func archAcosh(x float64) float64
 func acoshTrampolineSetup(x float64) float64
 func acoshAsm(x float64) float64
 
+const haveArchAsin = true
+
+func archAsin(x float64) float64
 func asinTrampolineSetup(x float64) float64
 func asinAsm(x float64) float64
 
+const haveArchAsinh = true
+
+func archAsinh(x float64) float64
 func asinhTrampolineSetup(x float64) float64
 func asinhAsm(x float64) float64
 
+const haveArchErf = true
+
+func archErf(x float64) float64
 func erfTrampolineSetup(x float64) float64
 func erfAsm(x float64) float64
 
+const haveArchErfc = true
+
+func archErfc(x float64) float64
 func erfcTrampolineSetup(x float64) float64
 func erfcAsm(x float64) float64
 
+const haveArchAtan = true
+
+func archAtan(x float64) float64
 func atanTrampolineSetup(x float64) float64
 func atanAsm(x float64) float64
 
+const haveArchAtan2 = true
+
+func archAtan2(y, x float64) float64
 func atan2TrampolineSetup(x, y float64) float64
 func atan2Asm(x, y float64) float64
 
+const haveArchCbrt = true
+
+func archCbrt(x float64) float64
 func cbrtTrampolineSetup(x float64) float64
 func cbrtAsm(x float64) float64
 
-func logTrampolineSetup(x float64) float64
-func logAsm(x float64) float64
+const haveArchTan = true
 
+func archTan(x float64) float64
 func tanTrampolineSetup(x float64) float64
 func tanAsm(x float64) float64
 
-func expTrampolineSetup(x float64) float64
-func expAsm(x float64) float64
+const haveArchExpm1 = true
 
+func archExpm1(x float64) float64
 func expm1TrampolineSetup(x float64) float64
 func expm1Asm(x float64) float64
 
+const haveArchPow = true
+
+func archPow(x, y float64) float64
 func powTrampolineSetup(x, y float64) float64
 func powAsm(x, y float64) float64
 
+const haveArchFrexp = false
+
+func archFrexp(x float64) (float64, int) {
+       panic("not implemented")
+}
+
+const haveArchLdexp = false
+
+func archLdexp(frac float64, exp int) float64 {
+       panic("not implemented")
+}
+
+const haveArchLog2 = false
+
+func archLog2(x float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchMod = false
+
+func archMod(x, y float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchRemainder = false
+
+func archRemainder(x, y float64) float64 {
+       panic("not implemented")
+}
+
 // hasVX reports whether the machine has the z/Architecture
 // vector facility installed and enabled.
 var hasVX = cpu.S390X.HasVX
index 46a5fe9d808793a2bb1734eaa86cf2d46e4dcd2f..ac70bcb3a11122c300db50c7c44c0d83d903b6c6 100644 (file)
@@ -16,14 +16,13 @@ package math
 // Special cases are:
 //     Asin(±0) = ±0
 //     Asin(x) = NaN if x < -1 or x > 1
-
-//extern asin
-func libc_asin(float64) float64
-
 func Asin(x float64) float64 {
        return libc_asin(x)
 }
 
+//extern asin
+func libc_asin(float64) float64
+
 func asin(x float64) float64 {
        if x == 0 {
                return x // special case
@@ -54,14 +53,13 @@ func asin(x float64) float64 {
 //
 // Special case is:
 //     Acos(x) = NaN if x < -1 or x > 1
-
-//extern acos
-func libc_acos(float64) float64
-
 func Acos(x float64) float64 {
        return libc_acos(x)
 }
 
+//extern acos
+func libc_acos(float64) float64
+
 func acos(x float64) float64 {
        return Pi/2 - Asin(x)
 }
index 4c9eda4d7313a18022d6f4ff9c70fc6d2a1a70a7..e4c997eeda65267f9f027e20e5cf8f63928fbea1 100644 (file)
@@ -90,12 +90,8 @@ func satan(x float64) float64 {
 // Atan returns the arctangent, in radians, of x.
 //
 // Special cases are:
-//     Atan(±0) = ±0
-//     Atan(±Inf) = ±Pi/2
-
-//extern atan
-func libc_atan(float64) float64
-
+//      Atan(±0) = ±0
+//      Atan(±Inf) = ±Pi/2
 func Atan(x float64) float64 {
        if x == 0 {
                return x
@@ -103,6 +99,9 @@ func Atan(x float64) float64 {
        return libc_atan(x)
 }
 
+//extern atan
+func libc_atan(float64) float64
+
 func atan(x float64) float64 {
        if x == 0 {
                return x
index 750ce8aa398df4ba6d32244ea9e211c592e38821..8f55c195d4bf26e494cd98fc5e4e71c6fe9dd4e8 100644 (file)
@@ -170,12 +170,16 @@ func shrVU_g(z, x []Word, s uint) (c Word) {
        if len(z) == 0 {
                return
        }
+       if len(x) != len(z) {
+               // This is an invariant guaranteed by the caller.
+               panic("len(x) != len(z)")
+       }
        s &= _W - 1 // hint to the compiler that shifts by s don't need guard code
        ŝ := _W - s
        ŝ &= _W - 1 // ditto
        c = x[0] << ŝ
-       for i := 0; i < len(z)-1; i++ {
-               z[i] = x[i]>>s | x[i+1]<<ŝ
+       for i := 1; i < len(z); i++ {
+               z[i-1] = x[i-1]>>s | x[i]<<ŝ
        }
        z[len(z)-1] = x[len(z)-1] >> s
        return
@@ -263,20 +267,6 @@ func divWW(x1, x0, y, m Word) (q, r Word) {
        return Word(qq), Word(r0 >> s)
 }
 
-func divWVW(z []Word, xn Word, x []Word, y Word) (r Word) {
-       r = xn
-       if len(x) == 1 {
-               qq, rr := bits.Div(uint(r), uint(x[0]), uint(y))
-               z[0] = Word(qq)
-               return Word(rr)
-       }
-       rec := reciprocalWord(y)
-       for i := len(z) - 1; i >= 0; i-- {
-               z[i], r = divWW(r, x[i], y, rec)
-       }
-       return r
-}
-
 // reciprocalWord return the reciprocal of the divisor. rec = floor(( _B^2 - 1 ) / u - _B). u = d1 << nlz(d1).
 func reciprocalWord(d1 Word) Word {
        u := uint(d1 << nlz(d1))
index 35164f33ac760ecfd46d06c3aab3b8038a860c1c..8e4e1a9840f0ece02b7f5cfa0dded5975960750e 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build ignore_for_gccgo
-// +build !math_big_pure_go
+//go:build ignore
+// +build ignore
 
 package big
 
index a14fda3087aecb1d754dcf9a19cb8e3df14dc4c4..d80b92b1ae7770e778ef06d40a2c1c2054d6ad05 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
-// +build !math_big_pure_go
 
 package big
 
index ac789850389165120af2f4a82fb4e3a04e84b4ed..cbfd1ddb8f691ddbd7b16bb1b01a2176adccd3e3 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//-go:build math_big_pure_go
 // -build math_big_pure_go
 
 package big
index 712f115e7d1217cb6b00c22be65a0a3929eb815e..96445b071524555ec4aaeed52313fcb405d5b75b 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
-// +build !math_big_pure_go
 
 package big
 
index be1ca7dda364f5f956a112c0f49a7ec4c99ffd8b..bda4811ed6a306d2e29c7a1a916f0f8b3854f39a 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
-// +build s390x,!math_big_pure_go
 
 package big
 
index 2aca0effde212842cca83b74473f538b66ca7562..7b3427f83415ba49d8350e4e835781577269be07 100644 (file)
@@ -671,3 +671,27 @@ func BenchmarkDivWVW(b *testing.B) {
                })
        }
 }
+
+func BenchmarkNonZeroShifts(b *testing.B) {
+       for _, n := range benchSizes {
+               if isRaceBuilder && n > 1e3 {
+                       continue
+               }
+               x := rndV(n)
+               s := uint(rand.Int63n(_W-2)) + 1 // avoid 0 and over-large shifts
+               z := make([]Word, n)
+               b.Run(fmt.Sprint(n), func(b *testing.B) {
+                       b.SetBytes(int64(n * _W))
+                       b.Run("shrVU", func(b *testing.B) {
+                               for i := 0; i < b.N; i++ {
+                                       _ = shrVU(z, x, s)
+                               }
+                       })
+                       b.Run("shlVU", func(b *testing.B) {
+                               for i := 0; i < b.N; i++ {
+                                       _ = shlVU(z, x, s)
+                               }
+                       })
+               })
+       }
+}
index 65f32487b58c017c8aa224c7e805cf0d2fcd20b0..7647346486c4cb02c7fcbec6558c3b7b1841f755 100644 (file)
@@ -425,7 +425,7 @@ func (z *Int) SetString(s string, base int) (*Int, bool) {
        return z.setFromScanner(strings.NewReader(s), base)
 }
 
-// setFromScanner implements SetString given an io.BytesScanner.
+// setFromScanner implements SetString given an io.ByteScanner.
 // For documentation see comments of SetString.
 func (z *Int) setFromScanner(r io.ByteScanner, base int) (*Int, bool) {
        if _, _, err := z.scan(r, base); err != nil {
index 42f9cefca07798f2a586546c5c02b69aa72b7f93..6e33aa5e5e571bad8ba11f8928e86b1056ca64df 100644 (file)
@@ -42,7 +42,7 @@ func main() {}
        if err != nil {
                t.Fatalf("nm: %v, %s", err, nm)
        }
-       const want = "runtime.(*Frames).Next"
+       const want = "runtime.main"
        if !bytes.Contains(nm, []byte(want)) {
                // Test the test.
                t.Errorf("expected symbol %q not found", want)
index bbd6c8850b604b365011144e9ab8e6744ee27354..140c619c8ca7113ff2986d472d31dd202d44bc07 100644 (file)
@@ -631,48 +631,6 @@ func (z nat) mulRange(a, b uint64) nat {
        return z.mul(nat(nil).mulRange(a, m), nat(nil).mulRange(m+1, b))
 }
 
-// q = (x-r)/y, with 0 <= r < y
-func (z nat) divW(x nat, y Word) (q nat, r Word) {
-       m := len(x)
-       switch {
-       case y == 0:
-               panic("division by zero")
-       case y == 1:
-               q = z.set(x) // result is x
-               return
-       case m == 0:
-               q = z[:0] // result is 0
-               return
-       }
-       // m > 0
-       z = z.make(m)
-       r = divWVW(z, 0, x, y)
-       q = z.norm()
-       return
-}
-
-func (z nat) div(z2, u, v nat) (q, r nat) {
-       if len(v) == 0 {
-               panic("division by zero")
-       }
-
-       if u.cmp(v) < 0 {
-               q = z[:0]
-               r = z2.set(u)
-               return
-       }
-
-       if len(v) == 1 {
-               var r2 Word
-               q, r2 = z.divW(u, v[0])
-               r = z2.setWord(r2)
-               return
-       }
-
-       q, r = z.divLarge(z2, u, v)
-       return
-}
-
 // getNat returns a *nat of len n. The contents may not be zero.
 // The pool holds *nat to avoid allocation when converting to interface{}.
 func getNat(n int) *nat {
@@ -693,276 +651,6 @@ func putNat(x *nat) {
 
 var natPool sync.Pool
 
-// q = (uIn-r)/vIn, with 0 <= r < vIn
-// Uses z as storage for q, and u as storage for r if possible.
-// See Knuth, Volume 2, section 4.3.1, Algorithm D.
-// Preconditions:
-//    len(vIn) >= 2
-//    len(uIn) >= len(vIn)
-//    u must not alias z
-func (z nat) divLarge(u, uIn, vIn nat) (q, r nat) {
-       n := len(vIn)
-       m := len(uIn) - n
-
-       // D1.
-       shift := nlz(vIn[n-1])
-       // do not modify vIn, it may be used by another goroutine simultaneously
-       vp := getNat(n)
-       v := *vp
-       shlVU(v, vIn, shift)
-
-       // u may safely alias uIn or vIn, the value of uIn is used to set u and vIn was already used
-       u = u.make(len(uIn) + 1)
-       u[len(uIn)] = shlVU(u[0:len(uIn)], uIn, shift)
-
-       // z may safely alias uIn or vIn, both values were used already
-       if alias(z, u) {
-               z = nil // z is an alias for u - cannot reuse
-       }
-       q = z.make(m + 1)
-
-       if n < divRecursiveThreshold {
-               q.divBasic(u, v)
-       } else {
-               q.divRecursive(u, v)
-       }
-       putNat(vp)
-
-       q = q.norm()
-       shrVU(u, u, shift)
-       r = u.norm()
-
-       return q, r
-}
-
-// divBasic performs word-by-word division of u by v.
-// The quotient is written in pre-allocated q.
-// The remainder overwrites input u.
-//
-// Precondition:
-// - q is large enough to hold the quotient u / v
-//   which has a maximum length of len(u)-len(v)+1.
-func (q nat) divBasic(u, v nat) {
-       n := len(v)
-       m := len(u) - n
-
-       qhatvp := getNat(n + 1)
-       qhatv := *qhatvp
-
-       // D2.
-       vn1 := v[n-1]
-       rec := reciprocalWord(vn1)
-       for j := m; j >= 0; j-- {
-               // D3.
-               qhat := Word(_M)
-               var ujn Word
-               if j+n < len(u) {
-                       ujn = u[j+n]
-               }
-               if ujn != vn1 {
-                       var rhat Word
-                       qhat, rhat = divWW(ujn, u[j+n-1], vn1, rec)
-
-                       // x1 | x2 = q̂v_{n-2}
-                       vn2 := v[n-2]
-                       x1, x2 := mulWW(qhat, vn2)
-                       // test if q̂v_{n-2} > br̂ + u_{j+n-2}
-                       ujn2 := u[j+n-2]
-                       for greaterThan(x1, x2, rhat, ujn2) {
-                               qhat--
-                               prevRhat := rhat
-                               rhat += vn1
-                               // v[n-1] >= 0, so this tests for overflow.
-                               if rhat < prevRhat {
-                                       break
-                               }
-                               x1, x2 = mulWW(qhat, vn2)
-                       }
-               }
-
-               // D4.
-               // Compute the remainder u - (q̂*v) << (_W*j).
-               // The subtraction may overflow if q̂ estimate was off by one.
-               qhatv[n] = mulAddVWW(qhatv[0:n], v, qhat, 0)
-               qhl := len(qhatv)
-               if j+qhl > len(u) && qhatv[n] == 0 {
-                       qhl--
-               }
-               c := subVV(u[j:j+qhl], u[j:], qhatv)
-               if c != 0 {
-                       c := addVV(u[j:j+n], u[j:], v)
-                       // If n == qhl, the carry from subVV and the carry from addVV
-                       // cancel out and don't affect u[j+n].
-                       if n < qhl {
-                               u[j+n] += c
-                       }
-                       qhat--
-               }
-
-               if j == m && m == len(q) && qhat == 0 {
-                       continue
-               }
-               q[j] = qhat
-       }
-
-       putNat(qhatvp)
-}
-
-const divRecursiveThreshold = 100
-
-// divRecursive performs word-by-word division of u by v.
-// The quotient is written in pre-allocated z.
-// The remainder overwrites input u.
-//
-// Precondition:
-// - len(z) >= len(u)-len(v)
-//
-// See Burnikel, Ziegler, "Fast Recursive Division", Algorithm 1 and 2.
-func (z nat) divRecursive(u, v nat) {
-       // Recursion depth is less than 2 log2(len(v))
-       // Allocate a slice of temporaries to be reused across recursion.
-       recDepth := 2 * bits.Len(uint(len(v)))
-       // large enough to perform Karatsuba on operands as large as v
-       tmp := getNat(3 * len(v))
-       temps := make([]*nat, recDepth)
-       z.clear()
-       z.divRecursiveStep(u, v, 0, tmp, temps)
-       for _, n := range temps {
-               if n != nil {
-                       putNat(n)
-               }
-       }
-       putNat(tmp)
-}
-
-// divRecursiveStep computes the division of u by v.
-// - z must be large enough to hold the quotient
-// - the quotient will overwrite z
-// - the remainder will overwrite u
-func (z nat) divRecursiveStep(u, v nat, depth int, tmp *nat, temps []*nat) {
-       u = u.norm()
-       v = v.norm()
-
-       if len(u) == 0 {
-               z.clear()
-               return
-       }
-       n := len(v)
-       if n < divRecursiveThreshold {
-               z.divBasic(u, v)
-               return
-       }
-       m := len(u) - n
-       if m < 0 {
-               return
-       }
-
-       // Produce the quotient by blocks of B words.
-       // Division by v (length n) is done using a length n/2 division
-       // and a length n/2 multiplication for each block. The final
-       // complexity is driven by multiplication complexity.
-       B := n / 2
-
-       // Allocate a nat for qhat below.
-       if temps[depth] == nil {
-               temps[depth] = getNat(n)
-       } else {
-               *temps[depth] = temps[depth].make(B + 1)
-       }
-
-       j := m
-       for j > B {
-               // Divide u[j-B:j+n] by vIn. Keep remainder in u
-               // for next block.
-               //
-               // The following property will be used (Lemma 2):
-               // if u = u1 << s + u0
-               //    v = v1 << s + v0
-               // then floor(u1/v1) >= floor(u/v)
-               //
-               // Moreover, the difference is at most 2 if len(v1) >= len(u/v)
-               // We choose s = B-1 since len(v)-s >= B+1 >= len(u/v)
-               s := (B - 1)
-               // Except for the first step, the top bits are always
-               // a division remainder, so the quotient length is <= n.
-               uu := u[j-B:]
-
-               qhat := *temps[depth]
-               qhat.clear()
-               qhat.divRecursiveStep(uu[s:B+n], v[s:], depth+1, tmp, temps)
-               qhat = qhat.norm()
-               // Adjust the quotient:
-               //    u = u_h << s + u_l
-               //    v = v_h << s + v_l
-               //  u_h = q̂ v_h + rh
-               //    u = q̂ (v - v_l) + rh << s + u_l
-               // After the above step, u contains a remainder:
-               //    u = rh << s + u_l
-               // and we need to subtract q̂ v_l
-               //
-               // But it may be a bit too large, in which case q̂ needs to be smaller.
-               qhatv := tmp.make(3 * n)
-               qhatv.clear()
-               qhatv = qhatv.mul(qhat, v[:s])
-               for i := 0; i < 2; i++ {
-                       e := qhatv.cmp(uu.norm())
-                       if e <= 0 {
-                               break
-                       }
-                       subVW(qhat, qhat, 1)
-                       c := subVV(qhatv[:s], qhatv[:s], v[:s])
-                       if len(qhatv) > s {
-                               subVW(qhatv[s:], qhatv[s:], c)
-                       }
-                       addAt(uu[s:], v[s:], 0)
-               }
-               if qhatv.cmp(uu.norm()) > 0 {
-                       panic("impossible")
-               }
-               c := subVV(uu[:len(qhatv)], uu[:len(qhatv)], qhatv)
-               if c > 0 {
-                       subVW(uu[len(qhatv):], uu[len(qhatv):], c)
-               }
-               addAt(z, qhat, j-B)
-               j -= B
-       }
-
-       // Now u < (v<<B), compute lower bits in the same way.
-       // Choose shift = B-1 again.
-       s := B - 1
-       qhat := *temps[depth]
-       qhat.clear()
-       qhat.divRecursiveStep(u[s:].norm(), v[s:], depth+1, tmp, temps)
-       qhat = qhat.norm()
-       qhatv := tmp.make(3 * n)
-       qhatv.clear()
-       qhatv = qhatv.mul(qhat, v[:s])
-       // Set the correct remainder as before.
-       for i := 0; i < 2; i++ {
-               if e := qhatv.cmp(u.norm()); e > 0 {
-                       subVW(qhat, qhat, 1)
-                       c := subVV(qhatv[:s], qhatv[:s], v[:s])
-                       if len(qhatv) > s {
-                               subVW(qhatv[s:], qhatv[s:], c)
-                       }
-                       addAt(u[s:], v[s:], 0)
-               }
-       }
-       if qhatv.cmp(u.norm()) > 0 {
-               panic("impossible")
-       }
-       c := subVV(u[0:len(qhatv)], u[0:len(qhatv)], qhatv)
-       if c > 0 {
-               c = subVW(u[len(qhatv):], u[len(qhatv):], c)
-       }
-       if c > 0 {
-               panic("impossible")
-       }
-
-       // Done!
-       addAt(z, qhat.norm(), 0)
-}
-
 // Length of x in bits. x must be normalized.
 func (x nat) bitLen() int {
        if i := len(x) - 1; i >= 0 {
@@ -1170,19 +858,6 @@ func (z nat) xor(x, y nat) nat {
        return z.norm()
 }
 
-// greaterThan reports whether (x1<<_W + x2) > (y1<<_W + y2)
-func greaterThan(x1, x2, y1, y2 Word) bool {
-       return x1 > y1 || x1 == y1 && x2 > y2
-}
-
-// modW returns x % d.
-func (x nat) modW(d Word) (r Word) {
-       // TODO(agl): we don't actually need to store the q value.
-       var q nat
-       q = q.make(len(x))
-       return divWVW(q, 0, x, d)
-}
-
 // random creates a random integer in [0..limit), using the space in z if
 // possible. n is the bit length of limit.
 func (z nat) random(rand *rand.Rand, limit nat, n int) nat {
diff --git a/libgo/go/math/big/natdiv.go b/libgo/go/math/big/natdiv.go
new file mode 100644 (file)
index 0000000..882bb6d
--- /dev/null
@@ -0,0 +1,884 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+
+Multi-precision division. Here be dragons.
+
+Given u and v, where u is n+m digits, and v is n digits (with no leading zeros),
+the goal is to return quo, rem such that u = quo*v + rem, where 0 ≤ rem < v.
+That is, quo = ⌊u/v⌋ where ⌊x⌋ denotes the floor (truncation to integer) of x,
+and rem = u - quo·v.
+
+
+Long Division
+
+Division in a computer proceeds the same as long division in elementary school,
+but computers are not as good as schoolchildren at following vague directions,
+so we have to be much more precise about the actual steps and what can happen.
+
+We work from most to least significant digit of the quotient, doing:
+
+ • Guess a digit q, the number of v to subtract from the current
+   section of u to zero out the topmost digit.
+ • Check the guess by multiplying q·v and comparing it against
+   the current section of u, adjusting the guess as needed.
+ • Subtract q·v from the current section of u.
+ • Add q to the corresponding section of the result quo.
+
+When all digits have been processed, the final remainder is left in u
+and returned as rem.
+
+For example, here is a sketch of dividing 5 digits by 3 digits (n=3, m=2).
+
+                        q₂ q₁ q₀
+                _________________
+       v₂ v₁ v₀ ) u₄ u₃ u₂ u₁ u₀
+                  ↓  ↓  ↓  |  |
+                 [u₄ u₃ u₂]|  |
+               - [  q₂·v  ]|  |
+               ----------- ↓  |
+                 [  rem  | u₁]|
+               - [    q₁·v   ]|
+                  ----------- ↓
+                    [  rem  | u₀]
+                  - [    q₀·v   ]
+                     ------------
+                       [  rem   ]
+
+Instead of creating new storage for the remainders and copying digits from u
+as indicated by the arrows, we use u's storage directly as both the source
+and destination of the subtractions, so that the remainders overwrite
+successive overlapping sections of u as the division proceeds, using a slice
+of u to identify the current section. This avoids all the copying as well as
+shifting of remainders.
+
+Division of u with n+m digits by v with n digits (in base B) can in general
+produce at most m+1 digits, because:
+
+  • u < B^(n+m)               [B^(n+m) has n+m+1 digits]
+  • v ≥ B^(n-1)               [B^(n-1) is the smallest n-digit number]
+  • u/v < B^(n+m) / B^(n-1)   [divide bounds for u, v]
+  • u/v < B^(m+1)             [simplify]
+
+The first step is special: it takes the top n digits of u and divides them by
+the n digits of v, producing the first quotient digit and an n-digit remainder.
+In the example, q₂ = ⌊u₄u₃u₂ / v⌋.
+
+The first step divides n digits by n digits to ensure that it produces only a
+single digit.
+
+Each subsequent step appends the next digit from u to the remainder and divides
+those n+1 digits by the n digits of v, producing another quotient digit and a
+new n-digit remainder.
+
+Subsequent steps divide n+1 digits by n digits, an operation that in general
+might produce two digits. However, as used in the algorithm, that division is
+guaranteed to produce only a single digit. The dividend is of the form
+rem·B + d, where rem is a remainder from the previous step and d is a single
+digit, so:
+
+ • rem ≤ v - 1                 [rem is a remainder from dividing by v]
+ • rem·B ≤ v·B - B             [multiply by B]
+ • d ≤ B - 1                   [d is a single digit]
+ • rem·B + d ≤ v·B - 1         [add]
+ • rem·B + d < v·B             [change ≤ to <]
+ • (rem·B + d)/v < B           [divide by v]
+
+
+Guess and Check
+
+At each step we need to divide n+1 digits by n digits, but this is for the
+implementation of division by n digits, so we can't just invoke a division
+routine: we _are_ the division routine. Instead, we guess at the answer and
+then check it using multiplication. If the guess is wrong, we correct it.
+
+How can this guessing possibly be efficient? It turns out that the following
+statement (let's call it the Good Guess Guarantee) is true.
+
+If
+
+ • q = ⌊u/v⌋ where u is n+1 digits and v is n digits,
+ • q < B, and
+ • the topmost digit of v = vₙ₋₁ ≥ B/2,
+
+then q̂ = ⌊uₙuₙ₋₁ / vₙ₋₁⌋ satisfies q ≤ q̂ ≤ q+2. (Proof below.)
+
+That is, if we know the answer has only a single digit and we guess an answer
+by ignoring the bottom n-1 digits of u and v, using a 2-by-1-digit division,
+then that guess is at least as large as the correct answer. It is also not
+too much larger: it is off by at most two from the correct answer.
+
+Note that in the first step of the overall division, which is an n-by-n-digit
+division, the 2-by-1 guess uses an implicit uₙ = 0.
+
+Note that using a 2-by-1-digit division here does not mean calling ourselves
+recursively. Instead, we use an efficient direct hardware implementation of
+that operation.
+
+Note that because q is u/v rounded down, q·v must not exceed u: u ≥ q·v.
+If a guess q̂ is too big, it will not satisfy this test. Viewed a different way,
+the remainder r̂ for a given q̂ is u - q̂·v, which must be positive. If it is
+negative, then the guess q̂ is too big.
+
+This gives us a way to compute q. First compute q̂ with 2-by-1-digit division.
+Then, while u < q̂·v, decrement q̂; this loop executes at most twice, because
+q̂ ≤ q+2.
+
+
+Scaling Inputs
+
+The Good Guess Guarantee requires that the top digit of v (vₙ₋₁) be at least B/2.
+For example in base 10, ⌊172/19⌋ = 9, but ⌊18/1⌋ = 18: the guess is wildly off
+because the first digit 1 is smaller than B/2 = 5.
+
+We can ensure that v has a large top digit by multiplying both u and v by the
+right amount. Continuing the example, if we multiply both 172 and 19 by 3, we
+now have ⌊516/57⌋, the leading digit of v is now ≥ 5, and sure enough
+⌊51/5⌋ = 10 is much closer to the correct answer 9. It would be easier here
+to multiply by 4, because that can be done with a shift. Specifically, we can
+always count the number of leading zeros i in the first digit of v and then
+shift both u and v left by i bits.
+
+Having scaled u and v, the value ⌊u/v⌋ is unchanged, but the remainder will
+be scaled: 172 mod 19 is 1, but 516 mod 57 is 3. We have to divide the remainder
+by the scaling factor (shifting right i bits) when we finish.
+
+Note that these shifts happen before and after the entire division algorithm,
+not at each step in the per-digit iteration.
+
+Note the effect of scaling inputs on the size of the possible quotient.
+In the scaled u/v, u can gain a digit from scaling; v never does, because we
+pick the scaling factor to make v's top digit larger but without overflowing.
+If u and v have n+m and n digits after scaling, then:
+
+  • u < B^(n+m)               [B^(n+m) has n+m+1 digits]
+  • v ≥ B^n / 2               [vₙ₋₁ ≥ B/2, so vₙ₋₁·B^(n-1) ≥ B^n/2]
+  • u/v < B^(n+m) / (B^n / 2) [divide bounds for u, v]
+  • u/v < 2 B^m               [simplify]
+
+The quotient can still have m+1 significant digits, but if so the top digit
+must be a 1. This provides a different way to handle the first digit of the
+result: compare the top n digits of u against v and fill in either a 0 or a 1.
+
+
+Refining Guesses
+
+Before we check whether u < q̂·v, we can adjust our guess to change it from
+q̂ = ⌊uₙuₙ₋₁ / vₙ₋₁⌋ into the refined guess ⌊uₙuₙ₋₁uₙ₋₂ / vₙ₋₁vₙ₋₂⌋.
+Although not mentioned above, the Good Guess Guarantee also promises that this
+3-by-2-digit division guess is more precise and at most one away from the real
+answer q. The improvement from the 2-by-1 to the 3-by-2 guess can also be done
+without n-digit math.
+
+If we have a guess q̂ = ⌊uₙuₙ₋₁ / vₙ₋₁⌋ and we want to see if it also equal to
+⌊uₙuₙ₋₁uₙ₋₂ / vₙ₋₁vₙ₋₂⌋, we can use the same check we would for the full division:
+if uₙuₙ₋₁uₙ₋₂ < q̂·vₙ₋₁vₙ₋₂, then the guess is too large and should be reduced.
+
+Checking uₙuₙ₋₁uₙ₋₂ < q̂·vₙ₋₁vₙ₋₂ is the same as uₙuₙ₋₁uₙ₋₂ - q̂·vₙ₋₁vₙ₋₂ < 0,
+and
+
+       uₙuₙ₋₁uₙ₋₂ - q̂·vₙ₋₁vₙ₋₂ = (uₙuₙ₋₁·B + uₙ₋₂) - q̂·(vₙ₋₁·B + vₙ₋₂)
+                                 [splitting off the bottom digit]
+                             = (uₙuₙ₋₁ - q̂·vₙ₋₁)·B + uₙ₋₂ - q̂·vₙ₋₂
+                                 [regrouping]
+
+The expression (uₙuₙ₋₁ - q̂·vₙ₋₁) is the remainder of uₙuₙ₋₁ / vₙ₋₁.
+If the initial guess returns both q̂ and its remainder r̂, then checking
+whether uₙuₙ₋₁uₙ₋₂ < q̂·vₙ₋₁vₙ₋₂ is the same as checking r̂·B + uₙ₋₂ < q̂·vₙ₋₂.
+
+If we find that r̂·B + uₙ₋₂ < q̂·vₙ₋₂, then we can adjust the guess by
+decrementing q̂ and adding vₙ₋₁ to r̂. We repeat until r̂·B + uₙ₋₂ ≥ q̂·vₙ₋₂.
+(As before, this fixup is only needed at most twice.)
+
+Now that q̂ = ⌊uₙuₙ₋₁uₙ₋₂ / vₙ₋₁vₙ₋₂⌋, as mentioned above it is at most one
+away from the correct q, and we've avoided doing any n-digit math.
+(If we need the new remainder, it can be computed as r̂·B + uₙ₋₂ - q̂·vₙ₋₂.)
+
+The final check u < q̂·v and the possible fixup must be done at full precision.
+For random inputs, a fixup at this step is exceedingly rare: the 3-by-2 guess
+is not often wrong at all. But still we must do the check. Note that since the
+3-by-2 guess is off by at most 1, it can be convenient to perform the final
+u < q̂·v as part of the computation of the remainder r = u - q̂·v. If the
+subtraction underflows, decremeting q̂ and adding one v back to r is enough to
+arrive at the final q, r.
+
+That's the entirety of long division: scale the inputs, and then loop over
+each output position, guessing, checking, and correcting the next output digit.
+
+For a 2n-digit number divided by an n-digit number (the worst size-n case for
+division complexity), this algorithm uses n+1 iterations, each of which must do
+at least the 1-by-n-digit multiplication q̂·v. That's O(n) iterations of
+O(n) time each, so O(n²) time overall.
+
+
+Recursive Division
+
+For very large inputs, it is possible to improve on the O(n²) algorithm.
+Let's call a group of n/2 real digits a (very) “wide digit”. We can run the
+standard long division algorithm explained above over the wide digits instead of
+the actual digits. This will result in many fewer steps, but the math involved in
+each step is more work.
+
+Where basic long division uses a 2-by-1-digit division to guess the initial q̂,
+the new algorithm must use a 2-by-1-wide-digit division, which is of course
+really an n-by-n/2-digit division. That's OK: if we implement n-digit division
+in terms of n/2-digit division, the recursion will terminate when the divisor
+becomes small enough to handle with standard long division or even with the
+2-by-1 hardware instruction.
+
+For example, here is a sketch of dividing 10 digits by 4, proceeding with
+wide digits corresponding to two regular digits. The first step, still special,
+must leave off a (regular) digit, dividing 5 by 4 and producing a 4-digit
+remainder less than v. The middle steps divide 6 digits by 4, guaranteed to
+produce two output digits each (one wide digit) with 4-digit remainders.
+The final step must use what it has: the 4-digit remainder plus one more,
+5 digits to divide by 4.
+
+                              q₆ q₅ q₄ q₃ q₂ q₁ q₀
+                   _______________________________
+       v₃ v₂ v₁ v₀ ) u₉ u₈ u₇ u₆ u₅ u₄ u₃ u₂ u₁ u₀
+                     ↓  ↓  ↓  ↓  ↓  |  |  |  |  |
+                    [u₉ u₈ u₇ u₆ u₅]|  |  |  |  |
+                  - [    q₆q₅·v    ]|  |  |  |  |
+                  ----------------- ↓  ↓  |  |  |
+                       [    rem    |u₄ u₃]|  |  |
+                     - [     q₄q₃·v      ]|  |  |
+                     -------------------- ↓  ↓  |
+                             [    rem    |u₂ u₁]|
+                           - [     q₂q₁·v      ]|
+                           -------------------- ↓
+                                   [    rem    |u₀]
+                                 - [     q₀·v     ]
+                                 ------------------
+                                      [    rem    ]
+
+An alternative would be to look ahead to how well n/2 divides into n+m and
+adjust the first step to use fewer digits as needed, making the first step
+more special to make the last step not special at all. For example, using the
+same input, we could choose to use only 4 digits in the first step, leaving
+a full wide digit for the last step:
+
+                              q₆ q₅ q₄ q₃ q₂ q₁ q₀
+                   _______________________________
+       v₃ v₂ v₁ v₀ ) u₉ u₈ u₇ u₆ u₅ u₄ u₃ u₂ u₁ u₀
+                     ↓  ↓  ↓  ↓  |  |  |  |  |  |
+                    [u₉ u₈ u₇ u₆]|  |  |  |  |  |
+                  - [    q₆·v   ]|  |  |  |  |  |
+                  -------------- ↓  ↓  |  |  |  |
+                    [    rem    |u₅ u₄]|  |  |  |
+                  - [     q₅q₄·v      ]|  |  |  |
+                  -------------------- ↓  ↓  |  |
+                          [    rem    |u₃ u₂]|  |
+                        - [     q₃q₂·v      ]|  |
+                        -------------------- ↓  ↓
+                                [    rem    |u₁ u₀]
+                              - [     q₁q₀·v      ]
+                              ---------------------
+                                      [    rem    ]
+
+Today, the code in divRecursiveStep works like the first example. Perhaps in
+the future we will make it work like the alternative, to avoid a special case
+in the final iteration.
+
+Either way, each step is a 3-by-2-wide-digit division approximated first by
+a 2-by-1-wide-digit division, just as we did for regular digits in long division.
+Because the actual answer we want is a 3-by-2-wide-digit division, instead of
+multiplying q̂·v directly during the fixup, we can use the quick refinement
+from long division (an n/2-by-n/2 multiply) to correct q to its actual value
+and also compute the remainder (as mentioned above), and then stop after that,
+never doing a full n-by-n multiply.
+
+Instead of using an n-by-n/2-digit division to produce n/2 digits, we can add
+(not discard) one more real digit, doing an (n+1)-by-(n/2+1)-digit division that
+produces n/2+1 digits. That single extra digit tightens the Good Guess Guarantee
+to q ≤ q̂ ≤ q+1 and lets us drop long division's special treatment of the first
+digit. These benefits are discussed more after the Good Guess Guarantee proof
+below.
+
+
+How Fast is Recursive Division?
+
+For a 2n-by-n-digit division, this algorithm runs a 4-by-2 long division over
+wide digits, producing two wide digits plus a possible leading regular digit 1,
+which can be handled without a recursive call. That is, the algorithm uses two
+full iterations, each using an n-by-n/2-digit division and an n/2-by-n/2-digit
+multiplication, along with a few n-digit additions and subtractions. The standard
+n-by-n-digit multiplication algorithm requires O(n²) time, making the overall
+algorithm require time T(n) where
+
+       T(n) = 2T(n/2) + O(n) + O(n²)
+
+which, by the Bentley-Haken-Saxe theorem, ends up reducing to T(n) = O(n²).
+This is not an improvement over regular long division.
+
+When the number of digits n becomes large enough, Karatsuba's algorithm for
+multiplication can be used instead, which takes O(n^log₂3) = O(n^1.6) time.
+(Karatsuba multiplication is implemented in func karatsuba in nat.go.)
+That makes the overall recursive division algorithm take O(n^1.6) time as well,
+which is an improvement, but again only for large enough numbers.
+
+It is not critical to make sure that every recursion does only two recursive
+calls. While in general the number of recursive calls can change the time
+analysis, in this case doing three calls does not change the analysis:
+
+       T(n) = 3T(n/2) + O(n) + O(n^log₂3)
+
+ends up being T(n) = O(n^log₂3). Because the Karatsuba multiplication taking
+time O(n^log₂3) is itself doing 3 half-sized recursions, doing three for the
+division does not hurt the asymptotic performance. Of course, it is likely
+still faster in practice to do two.
+
+
+Proof of the Good Guess Guarantee
+
+Given numbers x, y, let us break them into the quotients and remainders when
+divided by some scaling factor S, with the added constraints that the quotient
+x/y and the high part of y are both less than some limit T, and that the high
+part of y is at least half as big as T.
+
+       x₁ = ⌊x/S⌋        y₁ = ⌊y/S⌋
+       x₀ = x mod S      y₀ = y mod S
+
+       x  = x₁·S + x₀    0 ≤ x₀ < S    x/y < T
+       y  = y₁·S + y₀    0 ≤ y₀ < S    T/2 ≤ y₁ < T
+
+And consider the two truncated quotients:
+
+       q = ⌊x/y⌋
+       q̂ = ⌊x₁/y₁⌋
+
+We will prove that q ≤ q̂ ≤ q+2.
+
+The guarantee makes no real demands on the scaling factor S: it is simply the
+magnitude of the digits cut from both x and y to produce x₁ and y₁.
+The guarantee makes only limited demands on T: it must be large enough to hold
+the quotient x/y, and y₁ must have roughly the same size.
+
+To apply to the earlier discussion of 2-by-1 guesses in long division,
+we would choose:
+
+       S  = Bⁿ⁻¹
+       T  = B
+       x  = u
+       x₁ = uₙuₙ₋₁
+       x₀ = uₙ₋₂...u₀
+       y  = v
+       y₁ = vₙ₋₁
+       y₀ = vₙ₋₂...u₀
+
+These simpler variables avoid repeating those longer expressions in the proof.
+
+Note also that, by definition, truncating division ⌊x/y⌋ satisfies
+
+       x/y - 1 < ⌊x/y⌋ ≤ x/y.
+
+This fact will be used a few times in the proofs.
+
+Proof that q ≤ q̂:
+
+       q̂·y₁ = ⌊x₁/y₁⌋·y₁                      [by definition, q̂ = ⌊x₁/y₁⌋]
+            > (x₁/y₁ - 1)·y₁                  [x₁/y₁ - 1 < ⌊x₁/y₁⌋]
+            = x₁ - y₁                         [distribute y₁]
+
+       So q̂·y₁ > x₁ - y₁.
+       Since q̂·y₁ is an integer, q̂·y₁ ≥ x₁ - y₁ + 1.
+
+       q̂ - q = q̂ - ⌊x/y⌋                      [by definition, q = ⌊x/y⌋]
+             ≥ q̂ - x/y                        [⌊x/y⌋ < x/y]
+             = (1/y)·(q̂·y - x)                [factor out 1/y]
+             ≥ (1/y)·(q̂·y₁·S - x)             [y = y₁·S + y₀ ≥ y₁·S]
+             ≥ (1/y)·((x₁ - y₁ + 1)·S - x)    [above: q̂·y₁ ≥ x₁ - y₁ + 1]
+             = (1/y)·(x₁·S - y₁·S + S - x)    [distribute S]
+             = (1/y)·(S - x₀ - y₁·S)          [-x = -x₁·S - x₀]
+             > -y₁·S / y                      [x₀ < S, so S - x₀ < 0; drop it]
+             ≥ -1                             [y₁·S ≤ y]
+
+       So q̂ - q > -1.
+       Since q̂ - q is an integer, q̂ - q ≥ 0, or equivalently q ≤ q̂.
+
+Proof that q̂ ≤ q+2:
+
+       x₁/y₁ - x/y = x₁·S/y₁·S - x/y          [multiply left term by S/S]
+                   ≤ x/y₁·S - x/y             [x₁S ≤ x]
+                   = (x/y)·(y/y₁·S - 1)       [factor out x/y]
+                   = (x/y)·((y - y₁·S)/y₁·S)  [move -1 into y/y₁·S fraction]
+                   = (x/y)·(y₀/y₁·S)          [y - y₁·S = y₀]
+                   = (x/y)·(1/y₁)·(y₀/S)      [factor out 1/y₁]
+                   < (x/y)·(1/y₁)             [y₀ < S, so y₀/S < 1]
+                   ≤ (x/y)·(2/T)              [y₁ ≥ T/2, so 1/y₁ ≤ 2/T]
+                   < T·(2/T)                  [x/y < T]
+                   = 2                        [T·(2/T) = 2]
+
+       So x₁/y₁ - x/y < 2.
+
+       q̂ - q = ⌊x₁/y₁⌋ - q                    [by definition, q̂ = ⌊x₁/y₁⌋]
+             = ⌊x₁/y₁⌋ - ⌊x/y⌋                [by definition, q = ⌊x/y⌋]
+             ≤ x₁/y₁ - ⌊x/y⌋                  [⌊x₁/y₁⌋ ≤ x₁/y₁]
+             < x₁/y₁ - (x/y - 1)              [⌊x/y⌋ > x/y - 1]
+             = (x₁/y₁ - x/y) + 1              [regrouping]
+             < 2 + 1                          [above: x₁/y₁ - x/y < 2]
+             = 3
+
+       So q̂ - q < 3.
+       Since q̂ - q is an integer, q̂ - q ≤ 2.
+
+Note that when x/y < T/2, the bounds tighten to x₁/y₁ - x/y < 1 and therefore
+q̂ - q ≤ 1.
+
+Note also that in the general case 2n-by-n division where we don't know that
+x/y < T, we do know that x/y < 2T, yielding the bound q̂ - q ≤ 4. So we could
+remove the special case first step of long division as long as we allow the
+first fixup loop to run up to four times. (Using a simple comparison to decide
+whether the first digit is 0 or 1 is still more efficient, though.)
+
+Finally, note that when dividing three leading base-B digits by two (scaled),
+we have T = B² and x/y < B = T/B, a much tighter bound than x/y < T.
+This in turn yields the much tighter bound x₁/y₁ - x/y < 2/B. This means that
+⌊x₁/y₁⌋ and ⌊x/y⌋ can only differ when x/y is less than 2/B greater than an
+integer. For random x and y, the chance of this is 2/B, or, for large B,
+approximately zero. This means that after we produce the 3-by-2 guess in the
+long division algorithm, the fixup loop essentially never runs.
+
+In the recursive algorithm, the extra digit in (2·⌊n/2⌋+1)-by-(⌊n/2⌋+1)-digit
+division has exactly the same effect: the probability of needing a fixup is the
+same 2/B. Even better, we can allow the general case x/y < 2T and the fixup
+probability only grows to 4/B, still essentially zero.
+
+
+References
+
+There are no great references for implementing long division; thus this comment.
+Here are some notes about what to expect from the obvious references.
+
+Knuth Volume 2 (Seminumerical Algorithms) section 4.3.1 is the usual canonical
+reference for long division, but that entire series is highly compressed, never
+repeating a necessary fact and leaving important insights to the exercises.
+For example, no rationale whatsoever is given for the calculation that extends
+q̂ from a 2-by-1 to a 3-by-2 guess, nor why it reduces the error bound.
+The proof that the calculation even has the desired effect is left to exercises.
+The solutions to those exercises provided at the back of the book are entirely
+calculations, still with no explanation as to what is going on or how you would
+arrive at the idea of doing those exact calculations. Nowhere is it mentioned
+that this test extends the 2-by-1 guess into a 3-by-2 guess. The proof of the
+Good Guess Guarantee is only for the 2-by-1 guess and argues by contradiction,
+making it difficult to understand how modifications like adding another digit
+or adjusting the quotient range affects the overall bound.
+
+All that said, Knuth remains the canonical reference. It is dense but packed
+full of information and references, and the proofs are simpler than many other
+presentations. The proofs above are reworkings of Knuth's to remove the
+arguments by contradiction and add explanations or steps that Knuth omitted.
+But beware of errors in older printings. Take the published errata with you.
+
+Brinch Hansen's “Multiple-length Division Revisited: a Tour of the Minefield”
+starts with a blunt critique of Knuth's presentation (among others) and then
+presents a more detailed and easier to follow treatment of long division,
+including an implementation in Pascal. But the algorithm and implementation
+work entirely in terms of 3-by-2 division, which is much less useful on modern
+hardware than an algorithm using 2-by-1 division. The proofs are a bit too
+focused on digit counting and seem needlessly complex, especially compared to
+the ones given above.
+
+Burnikel and Ziegler's “Fast Recursive Division” introduced the key insight of
+implementing division by an n-digit divisor using recursive calls to division
+by an n/2-digit divisor, relying on Karatsuba multiplication to yield a
+sub-quadratic run time. However, the presentation decisions are made almost
+entirely for the purpose of simplifying the run-time analysis, rather than
+simplifying the presentation. Instead of a single algorithm that loops over
+quotient digits, the paper presents two mutually-recursive algorithms, for
+2n-by-n and 3n-by-2n. The paper also does not present any general (n+m)-by-n
+algorithm.
+
+The proofs in the paper are remarkably complex, especially considering that
+the algorithm is at its core just long division on wide digits, so that the
+usual long division proofs apply essentially unaltered.
+*/
+
+package big
+
+import "math/bits"
+
+// div returns q, r such that q = ⌊u/v⌋ and r = u%v = u - q·v.
+// It uses z and z2 as the storage for q and r.
+func (z nat) div(z2, u, v nat) (q, r nat) {
+       if len(v) == 0 {
+               panic("division by zero")
+       }
+
+       if u.cmp(v) < 0 {
+               q = z[:0]
+               r = z2.set(u)
+               return
+       }
+
+       if len(v) == 1 {
+               // Short division: long optimized for a single-word divisor.
+               // In that case, the 2-by-1 guess is all we need at each step.
+               var r2 Word
+               q, r2 = z.divW(u, v[0])
+               r = z2.setWord(r2)
+               return
+       }
+
+       q, r = z.divLarge(z2, u, v)
+       return
+}
+
+// divW returns q, r such that q = ⌊x/y⌋ and r = x%y = x - q·y.
+// It uses z as the storage for q.
+// Note that y is a single digit (Word), not a big number.
+func (z nat) divW(x nat, y Word) (q nat, r Word) {
+       m := len(x)
+       switch {
+       case y == 0:
+               panic("division by zero")
+       case y == 1:
+               q = z.set(x) // result is x
+               return
+       case m == 0:
+               q = z[:0] // result is 0
+               return
+       }
+       // m > 0
+       z = z.make(m)
+       r = divWVW(z, 0, x, y)
+       q = z.norm()
+       return
+}
+
+// modW returns x % d.
+func (x nat) modW(d Word) (r Word) {
+       // TODO(agl): we don't actually need to store the q value.
+       var q nat
+       q = q.make(len(x))
+       return divWVW(q, 0, x, d)
+}
+
+// divWVW overwrites z with ⌊x/y⌋, returning the remainder r.
+// The caller must ensure that len(z) = len(x).
+func divWVW(z []Word, xn Word, x []Word, y Word) (r Word) {
+       r = xn
+       if len(x) == 1 {
+               qq, rr := bits.Div(uint(r), uint(x[0]), uint(y))
+               z[0] = Word(qq)
+               return Word(rr)
+       }
+       rec := reciprocalWord(y)
+       for i := len(z) - 1; i >= 0; i-- {
+               z[i], r = divWW(r, x[i], y, rec)
+       }
+       return r
+}
+
+// div returns q, r such that q = ⌊uIn/vIn⌋ and r = uIn%vIn = uIn - q·vIn.
+// It uses z and u as the storage for q and r.
+// The caller must ensure that len(vIn) ≥ 2 (use divW otherwise)
+// and that len(uIn) ≥ len(vIn) (the answer is 0, uIn otherwise).
+func (z nat) divLarge(u, uIn, vIn nat) (q, r nat) {
+       n := len(vIn)
+       m := len(uIn) - n
+
+       // Scale the inputs so vIn's top bit is 1 (see “Scaling Inputs” above).
+       // vIn is treated as a read-only input (it may be in use by another
+       // goroutine), so we must make a copy.
+       // uIn is copied to u.
+       shift := nlz(vIn[n-1])
+       vp := getNat(n)
+       v := *vp
+       shlVU(v, vIn, shift)
+       u = u.make(len(uIn) + 1)
+       u[len(uIn)] = shlVU(u[0:len(uIn)], uIn, shift)
+
+       // The caller should not pass aliased z and u, since those are
+       // the two different outputs, but correct just in case.
+       if alias(z, u) {
+               z = nil
+       }
+       q = z.make(m + 1)
+
+       // Use basic or recursive long division depending on size.
+       if n < divRecursiveThreshold {
+               q.divBasic(u, v)
+       } else {
+               q.divRecursive(u, v)
+       }
+       putNat(vp)
+
+       q = q.norm()
+
+       // Undo scaling of remainder.
+       shrVU(u, u, shift)
+       r = u.norm()
+
+       return q, r
+}
+
+// divBasic implements long division as described above.
+// It overwrites q with ⌊u/v⌋ and overwrites u with the remainder r.
+// q must be large enough to hold ⌊u/v⌋.
+func (q nat) divBasic(u, v nat) {
+       n := len(v)
+       m := len(u) - n
+
+       qhatvp := getNat(n + 1)
+       qhatv := *qhatvp
+
+       // Set up for divWW below, precomputing reciprocal argument.
+       vn1 := v[n-1]
+       rec := reciprocalWord(vn1)
+
+       // Compute each digit of quotient.
+       for j := m; j >= 0; j-- {
+               // Compute the 2-by-1 guess q̂.
+               // The first iteration must invent a leading 0 for u.
+               qhat := Word(_M)
+               var ujn Word
+               if j+n < len(u) {
+                       ujn = u[j+n]
+               }
+
+               // ujn ≤ vn1, or else q̂ would be more than one digit.
+               // For ujn == vn1, we set q̂ to the max digit M above.
+               // Otherwise, we compute the 2-by-1 guess.
+               if ujn != vn1 {
+                       var rhat Word
+                       qhat, rhat = divWW(ujn, u[j+n-1], vn1, rec)
+
+                       // Refine q̂ to a 3-by-2 guess. See “Refining Guesses” above.
+                       vn2 := v[n-2]
+                       x1, x2 := mulWW(qhat, vn2)
+                       ujn2 := u[j+n-2]
+                       for greaterThan(x1, x2, rhat, ujn2) { // x1x2 > r̂ u[j+n-2]
+                               qhat--
+                               prevRhat := rhat
+                               rhat += vn1
+                               // If r̂  overflows, then
+                               // r̂ u[j+n-2]v[n-1] is now definitely > x1 x2.
+                               if rhat < prevRhat {
+                                       break
+                               }
+                               // TODO(rsc): No need for a full mulWW.
+                               // x2 += vn2; if x2 overflows, x1++
+                               x1, x2 = mulWW(qhat, vn2)
+                       }
+               }
+
+               // Compute q̂·v.
+               qhatv[n] = mulAddVWW(qhatv[0:n], v, qhat, 0)
+               qhl := len(qhatv)
+               if j+qhl > len(u) && qhatv[n] == 0 {
+                       qhl--
+               }
+
+               // Subtract q̂·v from the current section of u.
+               // If it underflows, q̂·v > u, which we fix up
+               // by decrementing q̂ and adding v back.
+               c := subVV(u[j:j+qhl], u[j:], qhatv)
+               if c != 0 {
+                       c := addVV(u[j:j+n], u[j:], v)
+                       // If n == qhl, the carry from subVV and the carry from addVV
+                       // cancel out and don't affect u[j+n].
+                       if n < qhl {
+                               u[j+n] += c
+                       }
+                       qhat--
+               }
+
+               // Save quotient digit.
+               // Caller may know the top digit is zero and not leave room for it.
+               if j == m && m == len(q) && qhat == 0 {
+                       continue
+               }
+               q[j] = qhat
+       }
+
+       putNat(qhatvp)
+}
+
+// greaterThan reports whether the two digit numbers x1 x2 > y1 y2.
+// TODO(rsc): In contradiction to most of this file, x1 is the high
+// digit and x2 is the low digit. This should be fixed.
+func greaterThan(x1, x2, y1, y2 Word) bool {
+       return x1 > y1 || x1 == y1 && x2 > y2
+}
+
+// divRecursiveThreshold is the number of divisor digits
+// at which point divRecursive is faster than divBasic.
+const divRecursiveThreshold = 100
+
+// divRecursive implements recursive division as described above.
+// It overwrites z with ⌊u/v⌋ and overwrites u with the remainder r.
+// z must be large enough to hold ⌊u/v⌋.
+// This function is just for allocating and freeing temporaries
+// around divRecursiveStep, the real implementation.
+func (z nat) divRecursive(u, v nat) {
+       // Recursion depth is (much) less than 2 log₂(len(v)).
+       // Allocate a slice of temporaries to be reused across recursion,
+       // plus one extra temporary not live across the recursion.
+       recDepth := 2 * bits.Len(uint(len(v)))
+       tmp := getNat(3 * len(v))
+       temps := make([]*nat, recDepth)
+
+       z.clear()
+       z.divRecursiveStep(u, v, 0, tmp, temps)
+
+       // Free temporaries.
+       for _, n := range temps {
+               if n != nil {
+                       putNat(n)
+               }
+       }
+       putNat(tmp)
+}
+
+// divRecursiveStep is the actual implementation of recursive division.
+// It adds ⌊u/v⌋ to z and overwrites u with the remainder r.
+// z must be large enough to hold ⌊u/v⌋.
+// It uses temps[depth] (allocating if needed) as a temporary live across
+// the recursive call. It also uses tmp, but not live across the recursion.
+func (z nat) divRecursiveStep(u, v nat, depth int, tmp *nat, temps []*nat) {
+       // u is a subsection of the original and may have leading zeros.
+       // TODO(rsc): The v = v.norm() is useless and should be removed.
+       // We know (and require) that v's top digit is ≥ B/2.
+       u = u.norm()
+       v = v.norm()
+       if len(u) == 0 {
+               z.clear()
+               return
+       }
+
+       // Fall back to basic division if the problem is now small enough.
+       n := len(v)
+       if n < divRecursiveThreshold {
+               z.divBasic(u, v)
+               return
+       }
+
+       // Nothing to do if u is shorter than v (implies u < v).
+       m := len(u) - n
+       if m < 0 {
+               return
+       }
+
+       // We consider B digits in a row as a single wide digit.
+       // (See “Recursive Division” above.)
+       //
+       // TODO(rsc): rename B to Wide, to avoid confusion with _B,
+       // which is something entirely different.
+       // TODO(rsc): Look into whether using ⌈n/2⌉ is better than ⌊n/2⌋.
+       B := n / 2
+
+       // Allocate a nat for qhat below.
+       if temps[depth] == nil {
+               temps[depth] = getNat(n) // TODO(rsc): Can be just B+1.
+       } else {
+               *temps[depth] = temps[depth].make(B + 1)
+       }
+
+       // Compute each wide digit of the quotient.
+       //
+       // TODO(rsc): Change the loop to be
+       //      for j := (m+B-1)/B*B; j > 0; j -= B {
+       // which will make the final step a regular step, letting us
+       // delete what amounts to an extra copy of the loop body below.
+       j := m
+       for j > B {
+               // Divide u[j-B:j+n] (3 wide digits) by v (2 wide digits).
+               // First make the 2-by-1-wide-digit guess using a recursive call.
+               // Then extend the guess to the full 3-by-2 (see “Refining Guesses”).
+               //
+               // For the 2-by-1-wide-digit guess, instead of doing 2B-by-B-digit,
+               // we use a (2B+1)-by-(B+1) digit, which handles the possibility that
+               // the result has an extra leading 1 digit as well as guaranteeing
+               // that the computed q̂ will be off by at most 1 instead of 2.
+
+               // s is the number of digits to drop from the 3B- and 2B-digit chunks.
+               // We drop B-1 to be left with 2B+1 and B+1.
+               s := (B - 1)
+
+               // uu is the up-to-3B-digit section of u we are working on.
+               uu := u[j-B:]
+
+               // Compute the 2-by-1 guess q̂, leaving r̂ in uu[s:B+n].
+               qhat := *temps[depth]
+               qhat.clear()
+               qhat.divRecursiveStep(uu[s:B+n], v[s:], depth+1, tmp, temps)
+               qhat = qhat.norm()
+
+               // Extend to a 3-by-2 quotient and remainder.
+               // Because divRecursiveStep overwrote the top part of uu with
+               // the remainder r̂, the full uu already contains the equivalent
+               // of r̂·B + uₙ₋₂ from the “Refining Guesses” discussion.
+               // Subtracting q̂·vₙ₋₂ from it will compute the full-length remainder.
+               // If that subtraction underflows, q̂·v > u, which we fix up
+               // by decrementing q̂ and adding v back, same as in long division.
+
+               // TODO(rsc): Instead of subtract and fix-up, this code is computing
+               // q̂·vₙ₋₂ and decrementing q̂ until that product is ≤ u.
+               // But we can do the subtraction directly, as in the comment above
+               // and in long division, because we know that q̂ is wrong by at most one.
+               qhatv := tmp.make(3 * n)
+               qhatv.clear()
+               qhatv = qhatv.mul(qhat, v[:s])
+               for i := 0; i < 2; i++ {
+                       e := qhatv.cmp(uu.norm())
+                       if e <= 0 {
+                               break
+                       }
+                       subVW(qhat, qhat, 1)
+                       c := subVV(qhatv[:s], qhatv[:s], v[:s])
+                       if len(qhatv) > s {
+                               subVW(qhatv[s:], qhatv[s:], c)
+                       }
+                       addAt(uu[s:], v[s:], 0)
+               }
+               if qhatv.cmp(uu.norm()) > 0 {
+                       panic("impossible")
+               }
+               c := subVV(uu[:len(qhatv)], uu[:len(qhatv)], qhatv)
+               if c > 0 {
+                       subVW(uu[len(qhatv):], uu[len(qhatv):], c)
+               }
+               addAt(z, qhat, j-B)
+               j -= B
+       }
+
+       // TODO(rsc): Rewrite loop as described above and delete all this code.
+
+       // Now u < (v<<B), compute lower bits in the same way.
+       // Choose shift = B-1 again.
+       s := B - 1
+       qhat := *temps[depth]
+       qhat.clear()
+       qhat.divRecursiveStep(u[s:].norm(), v[s:], depth+1, tmp, temps)
+       qhat = qhat.norm()
+       qhatv := tmp.make(3 * n)
+       qhatv.clear()
+       qhatv = qhatv.mul(qhat, v[:s])
+       // Set the correct remainder as before.
+       for i := 0; i < 2; i++ {
+               if e := qhatv.cmp(u.norm()); e > 0 {
+                       subVW(qhat, qhat, 1)
+                       c := subVV(qhatv[:s], qhatv[:s], v[:s])
+                       if len(qhatv) > s {
+                               subVW(qhatv[s:], qhatv[s:], c)
+                       }
+                       addAt(u[s:], v[s:], 0)
+               }
+       }
+       if qhatv.cmp(u.norm()) > 0 {
+               panic("impossible")
+       }
+       c := subVV(u[0:len(qhatv)], u[0:len(qhatv)], qhatv)
+       if c > 0 {
+               c = subVW(u[len(qhatv):], u[len(qhatv):], c)
+       }
+       if c > 0 {
+               panic("impossible")
+       }
+
+       // Done!
+       addAt(z, qhat.norm(), 0)
+}
index 0bfe90c45523b363bc62db260ab7daca053cee48..d8fd6aefe23ef40bd4a6736f7f5335feca5e98a9 100644 (file)
@@ -8,7 +8,7 @@
 // functions for the predeclared unsigned integer types.
 package bits
 
-const uintSize = 32 << (^uint(0) >> 32 & 1) // 32 or 64
+const uintSize = 32 << (^uint(0) >> 63) // 32 or 64
 
 // UintSize is the size of a uint in bits.
 const UintSize = uintSize
index f174bd14a6fa7644d1cc931dc9f1d2a209840ef3..53dc1130279537deae5cb27760c266e3ac9014b3 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !compiler_bootstrap
 // +build !compiler_bootstrap
 
 package bits
index 5df5738848a68cd41e8da28fc45f4bd81c69db4e..4d610d33b8bb399a123540cc8a30293ace326732 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build compiler_bootstrap
 // +build compiler_bootstrap
 
 // This version used only for bootstrap (on this path we want
index f1e15a0d0ea506d3c3c99423ea69befca64ffe7d..f869b8d5c377d5540ec2208ba9321cf48bbcf316 100644 (file)
@@ -6,78 +6,74 @@
 
 package bits
 
-var ntz8tab = [256]uint8{
-       0x08, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
-       0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
-       0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
-       0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
-       0x06, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
-       0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
-       0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
-       0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
-       0x07, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
-       0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
-       0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
-       0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
-       0x06, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
-       0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
-       0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
-       0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
-}
+const ntz8tab = "" +
+       "\x08\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
+       "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
+       "\x05\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
+       "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
+       "\x06\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
+       "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
+       "\x05\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
+       "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
+       "\x07\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
+       "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
+       "\x05\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
+       "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
+       "\x06\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
+       "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
+       "\x05\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
+       "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00"
 
-var pop8tab = [256]uint8{
-       0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
-       0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
-       0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
-       0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
-       0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
-       0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
-       0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
-       0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
-       0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
-       0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
-       0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
-       0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
-       0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
-       0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
-       0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
-       0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08,
-}
+const pop8tab = "" +
+       "\x00\x01\x01\x02\x01\x02\x02\x03\x01\x02\x02\x03\x02\x03\x03\x04" +
+       "\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05" +
+       "\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05" +
+       "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" +
+       "\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05" +
+       "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" +
+       "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" +
+       "\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07" +
+       "\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05" +
+       "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" +
+       "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" +
+       "\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07" +
+       "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" +
+       "\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07" +
+       "\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07" +
+       "\x04\x05\x05\x06\x05\x06\x06\x07\x05\x06\x06\x07\x06\x07\x07\x08"
 
-var rev8tab = [256]uint8{
-       0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
-       0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
-       0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
-       0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
-       0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
-       0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
-       0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
-       0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
-       0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
-       0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
-       0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
-       0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
-       0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
-       0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
-       0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
-       0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
-}
+const rev8tab = "" +
+       "\x00\x80\x40\xc0\x20\xa0\x60\xe0\x10\x90\x50\xd0\x30\xb0\x70\xf0" +
+       "\x08\x88\x48\xc8\x28\xa8\x68\xe8\x18\x98\x58\xd8\x38\xb8\x78\xf8" +
+       "\x04\x84\x44\xc4\x24\xa4\x64\xe4\x14\x94\x54\xd4\x34\xb4\x74\xf4" +
+       "\x0c\x8c\x4c\xcc\x2c\xac\x6c\xec\x1c\x9c\x5c\xdc\x3c\xbc\x7c\xfc" +
+       "\x02\x82\x42\xc2\x22\xa2\x62\xe2\x12\x92\x52\xd2\x32\xb2\x72\xf2" +
+       "\x0a\x8a\x4a\xca\x2a\xaa\x6a\xea\x1a\x9a\x5a\xda\x3a\xba\x7a\xfa" +
+       "\x06\x86\x46\xc6\x26\xa6\x66\xe6\x16\x96\x56\xd6\x36\xb6\x76\xf6" +
+       "\x0e\x8e\x4e\xce\x2e\xae\x6e\xee\x1e\x9e\x5e\xde\x3e\xbe\x7e\xfe" +
+       "\x01\x81\x41\xc1\x21\xa1\x61\xe1\x11\x91\x51\xd1\x31\xb1\x71\xf1" +
+       "\x09\x89\x49\xc9\x29\xa9\x69\xe9\x19\x99\x59\xd9\x39\xb9\x79\xf9" +
+       "\x05\x85\x45\xc5\x25\xa5\x65\xe5\x15\x95\x55\xd5\x35\xb5\x75\xf5" +
+       "\x0d\x8d\x4d\xcd\x2d\xad\x6d\xed\x1d\x9d\x5d\xdd\x3d\xbd\x7d\xfd" +
+       "\x03\x83\x43\xc3\x23\xa3\x63\xe3\x13\x93\x53\xd3\x33\xb3\x73\xf3" +
+       "\x0b\x8b\x4b\xcb\x2b\xab\x6b\xeb\x1b\x9b\x5b\xdb\x3b\xbb\x7b\xfb" +
+       "\x07\x87\x47\xc7\x27\xa7\x67\xe7\x17\x97\x57\xd7\x37\xb7\x77\xf7" +
+       "\x0f\x8f\x4f\xcf\x2f\xaf\x6f\xef\x1f\x9f\x5f\xdf\x3f\xbf\x7f\xff"
 
-var len8tab = [256]uint8{
-       0x00, 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-       0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-       0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-       0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-       0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-       0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-       0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-       0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-       0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-       0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-       0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-       0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-       0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-       0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-       0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-       0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-}
+const len8tab = "" +
+       "\x00\x01\x02\x02\x03\x03\x03\x03\x04\x04\x04\x04\x04\x04\x04\x04" +
+       "\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" +
+       "\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06" +
+       "\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06" +
+       "\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07" +
+       "\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07" +
+       "\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07" +
+       "\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07" +
+       "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" +
+       "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" +
+       "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" +
+       "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" +
+       "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" +
+       "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" +
+       "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" +
+       "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08"
index 1d3ad53fe67cb04e4cf90bcff8ecf2a26afe6d25..ac4004df4149033a96febdbd0358a68f46b1cf3c 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 // This program generates example_test.go.
index b068d5e0e399cacbc34c80dffa09472697839a89..867025ea61dfe59303c32bea50e3abb64f1c1928 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 // This program generates bits_tables.go.
@@ -47,16 +48,15 @@ func main() {
 }
 
 func gen(w io.Writer, name string, f func(uint8) uint8) {
-       fmt.Fprintf(w, "var %s = [256]uint8{", name)
+       // Use a const string to allow the compiler to constant-evaluate lookups at constant index.
+       fmt.Fprintf(w, "const %s = \"\"+\n\"", name)
        for i := 0; i < 256; i++ {
-               if i%16 == 0 {
-                       fmt.Fprint(w, "\n\t")
-               } else {
-                       fmt.Fprint(w, " ")
+               fmt.Fprintf(w, "\\x%02x", f(uint8(i)))
+               if i%16 == 15 && i != 255 {
+                       fmt.Fprint(w, "\"+\n\"")
                }
-               fmt.Fprintf(w, "%#02x,", f(uint8(i)))
        }
-       fmt.Fprint(w, "\n}\n\n")
+       fmt.Fprint(w, "\"\n\n")
 }
 
 func ntz8(x uint8) (n uint8) {
index f8e60c265f609d6f3c3d60fae88c648b918965ed..78b42316de59d998eea787f476a40a7a2976365d 100644 (file)
@@ -5,6 +5,7 @@
 // Disabled for s390x because it uses assembly routines that are not
 // accurate for huge arguments.
 
+//go:build !s390x
 // +build !s390x
 
 package cmplx
index 0fc8715dd07ce0e38c307956a99b20184ff01316..5ea935fb42539d9787629ba8d1b2db4482db4895 100644 (file)
@@ -28,15 +28,19 @@ const (
 // Max is the largest finite value representable by the type.
 // SmallestNonzero is the smallest positive, non-zero value representable by the type.
 const (
-       MaxFloat32             = 3.40282346638528859811704183484516925440e+38  // 2**127 * (2**24 - 1) / 2**23
-       SmallestNonzeroFloat32 = 1.401298464324817070923729583289916131280e-45 // 1 / 2**(127 - 1 + 23)
+       MaxFloat32             = 0x1p127 * (1 + (1 - 0x1p-23)) // 3.40282346638528859811704183484516925440e+38
+       SmallestNonzeroFloat32 = 0x1p-126 * 0x1p-23            // 1.401298464324817070923729583289916131280e-45
 
-       MaxFloat64             = 1.797693134862315708145274237317043567981e+308 // 2**1023 * (2**53 - 1) / 2**52
-       SmallestNonzeroFloat64 = 4.940656458412465441765687928682213723651e-324 // 1 / 2**(1023 - 1 + 52)
+       MaxFloat64             = 0x1p1023 * (1 + (1 - 0x1p-52)) // 1.79769313486231570814527423731704356798070e+308
+       SmallestNonzeroFloat64 = 0x1p-1022 * 0x1p-52            // 4.9406564584124654417656879286822137236505980e-324
 )
 
 // Integer limit values.
 const (
+       intSize = 32 << (^uint(0) >> 63) // 32 or 64
+
+       MaxInt    = 1<<(intSize-1) - 1
+       MinInt    = -1 << (intSize - 1)
        MaxInt8   = 1<<7 - 1
        MinInt8   = -1 << 7
        MaxInt16  = 1<<15 - 1
@@ -45,6 +49,7 @@ const (
        MinInt32  = -1 << 31
        MaxInt64  = 1<<63 - 1
        MinInt64  = -1 << 63
+       MaxUint   = 1<<intSize - 1
        MaxUint8  = 1<<8 - 1
        MaxUint16 = 1<<16 - 1
        MaxUint32 = 1<<32 - 1
diff --git a/libgo/go/math/const_test.go b/libgo/go/math/const_test.go
new file mode 100644 (file)
index 0000000..170ba6a
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package math_test
+
+import (
+       "testing"
+
+       . "math"
+)
+
+func TestMaxUint(t *testing.T) {
+       if v := uint(MaxUint); v+1 != 0 {
+               t.Errorf("MaxUint should wrap around to zero: %d", v+1)
+       }
+       if v := uint8(MaxUint8); v+1 != 0 {
+               t.Errorf("MaxUint8 should wrap around to zero: %d", v+1)
+       }
+       if v := uint16(MaxUint16); v+1 != 0 {
+               t.Errorf("MaxUint16 should wrap around to zero: %d", v+1)
+       }
+       if v := uint32(MaxUint32); v+1 != 0 {
+               t.Errorf("MaxUint32 should wrap around to zero: %d", v+1)
+       }
+       if v := uint64(MaxUint64); v+1 != 0 {
+               t.Errorf("MaxUint64 should wrap around to zero: %d", v+1)
+       }
+}
+
+func TestMaxInt(t *testing.T) {
+       if v := int(MaxInt); v+1 != MinInt {
+               t.Errorf("MaxInt should wrap around to MinInt: %d", v+1)
+       }
+       if v := int8(MaxInt8); v+1 != MinInt8 {
+               t.Errorf("MaxInt8 should wrap around to MinInt8: %d", v+1)
+       }
+       if v := int16(MaxInt16); v+1 != MinInt16 {
+               t.Errorf("MaxInt16 should wrap around to MinInt16: %d", v+1)
+       }
+       if v := int32(MaxInt32); v+1 != MinInt32 {
+               t.Errorf("MaxInt32 should wrap around to MinInt32: %d", v+1)
+       }
+       if v := int64(MaxInt64); v+1 != MinInt64 {
+               t.Errorf("MaxInt64 should wrap around to MinInt64: %d", v+1)
+       }
+}
index cf06f30d562e209ffc329701a379bec863772c91..6a857bbe41fc0cfcbfeb1e45ea7cae1b652b34f7 100644 (file)
@@ -33,6 +33,9 @@ func Dim(x, y float64) float64 {
 //     Max(+0, ±0) = Max(±0, +0) = +0
 //     Max(-0, -0) = -0
 func Max(x, y float64) float64 {
+       if haveArchMax {
+               return archMax(x, y)
+       }
        return max(x, y)
 }
 
@@ -62,6 +65,9 @@ func max(x, y float64) float64 {
 //     Min(x, NaN) = Min(NaN, x) = NaN
 //     Min(-0, ±0) = Min(±0, -0) = -0
 func Min(x, y float64) float64 {
+       if haveArchMin {
+               return archMin(x, y)
+       }
        return min(x, y)
 }
 
diff --git a/libgo/go/math/dim_noasm.go b/libgo/go/math/dim_noasm.go
new file mode 100644 (file)
index 0000000..9a052c0
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//-go:build !amd64 && !arm64 && !riscv64 && !s390x
+// -build !amd64,!arm64,!riscv64,!s390x
+
+package math
+
+const haveArchMax = false
+
+func archMax(x, y float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchMin = false
+
+func archMin(x, y float64) float64 {
+       panic("not implemented")
+}
index f3d3cb6dbba282bda15a6d0a7010e26dc2e68d46..7ab80b4aa7c4dd30eca9544c57ff22a4e4c6f371 100644 (file)
@@ -11,14 +11,13 @@ package math
 //     Exp(NaN) = NaN
 // Very large values overflow to 0 or +Inf.
 // Very small values underflow to 1.
-
-//extern exp
-func libc_exp(float64) float64
-
 func Exp(x float64) float64 {
        return libc_exp(x)
 }
 
+//extern exp
+func libc_exp(float64) float64
+
 // The original C code, the long comment, and the constants
 // below are from FreeBSD's /usr/src/lib/msun/src/e_exp.c
 // and came with this notice. The go code is a simplified
@@ -139,6 +138,9 @@ func exp(x float64) float64 {
 //
 // Special cases are the same as Exp.
 func Exp2(x float64) float64 {
+       if haveArchExp2 {
+               return archExp2(x)
+       }
        return exp2(x)
 }
 
diff --git a/libgo/go/math/exp2_noasm.go b/libgo/go/math/exp2_noasm.go
new file mode 100644 (file)
index 0000000..9b81544
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//-go:build !arm64
+// -build !arm64
+
+package math
+
+const haveArchExp2 = false
+
+func archExp2(x float64) float64 {
+       panic("not implemented")
+}
similarity index 93%
rename from libgo/go/math/exp_asm.go
rename to libgo/go/math/exp_amd64.go
index 11e0a611cddaca475cdc02b606a307e9d57836d4..654ccce48103508d82d091a1e9e32fa1060a9a24 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build amd64
 // +build amd64
-// +build ignore
 
 package math
 
diff --git a/libgo/go/math/exp_noasm.go b/libgo/go/math/exp_noasm.go
new file mode 100644 (file)
index 0000000..4f90604
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//-go:build !amd64 && !arm64 && !s390x
+// -build !amd64,!arm64,!s390x
+
+package math
+
+const haveArchExp = false
+
+func archExp(x float64) float64 {
+       panic("not implemented")
+}
index 9c6e0809f3fab15c6563235f0e7d12e5504c3706..bf685ae96e6dab177142e2103dca940ad0694243 100644 (file)
@@ -121,10 +121,6 @@ package math
 //     Expm1(-Inf) = -1
 //     Expm1(NaN) = NaN
 // Very large values overflow to -1 or +Inf.
-
-//extern expm1
-func libc_expm1(float64) float64
-
 func Expm1(x float64) float64 {
        if x == 0 {
                return x
@@ -132,6 +128,9 @@ func Expm1(x float64) float64 {
        return libc_expm1(x)
 }
 
+//extern expm1
+func libc_expm1(float64) float64
+
 func expm1(x float64) float64 {
        const (
                Othreshold = 7.09782712893383973096e+02 // 0x40862E42FEFA39EF
index 9115968c74a12ccda29b7ba7eda5098fdec1bd80..963c858e18ff2d2f600d342ebea6e31103dc7f63 100644 (file)
@@ -57,8 +57,10 @@ func ceil(x float64) float64 {
 //     Trunc(±0) = ±0
 //     Trunc(±Inf) = ±Inf
 //     Trunc(NaN) = NaN
-
 func Trunc(x float64) float64 {
+       if haveArchTrunc {
+               return archTrunc(x)
+       }
        return trunc(x)
 }
 
diff --git a/libgo/go/math/floor_noasm.go b/libgo/go/math/floor_noasm.go
new file mode 100644 (file)
index 0000000..bcdc5b0
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//-go:build !386 && !amd64 && !arm64 && !ppc64 && !ppc64le && !s390x && !wasm
+// -build !386,!amd64,!arm64,!ppc64,!ppc64le,!s390x,!wasm
+
+package math
+
+const haveArchFloor = false
+
+func archFloor(x float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchCeil = false
+
+func archCeil(x float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchTrunc = false
+
+func archTrunc(x float64) float64 {
+       panic("not implemented")
+}
index db78dfa5e15ccfe413ba39a99e4cb70f5a9e89fa..ca0bf99f215603579286bf250cf6ae31c51cb193 100644 (file)
@@ -128,7 +128,7 @@ func FMA(x, y, z float64) float64 {
        pe -= int32(is62zero)
 
        // Swap addition operands so |p| >= |z|
-       if pe < ze || (pe == ze && (pm1 < zm1 || (pm1 == zm1 && pm2 < zm2))) {
+       if pe < ze || pe == ze && pm1 < zm1 {
                ps, pe, pm1, pm2, zs, ze, zm1, zm2 = zs, ze, zm1, zm2, ps, pe, pm1, pm2
        }
 
index 4ad0aee54a42f80f0e4dbf0e3359c87043ac47a9..3c8a909ed0cf4d18fb8ea6ea3ae5574dc84142be 100644 (file)
@@ -14,6 +14,9 @@ package math
 //     Frexp(±Inf) = ±Inf, 0
 //     Frexp(NaN) = NaN, 0
 func Frexp(f float64) (frac float64, exp int) {
+       if haveArchFrexp {
+               return archFrexp(f)
+       }
        return frexp(f)
 }
 
index 9448edc3394a9a4924def1c456b4f22c012cdea2..ec81a4a31da396fe4e9000f996a2dfe9aa6f1624 100644 (file)
@@ -5,6 +5,7 @@
 // Disabled for s390x because it uses assembly routines that are not
 // accurate for huge arguments.
 
+//go:build !s390x
 // +build !s390x
 
 package math_test
index cf242e86fdd9ade351cf9e54dd5131550ecd8c5c..f1c609d1381db48e3adf6c06f17ddd136f7e118f 100644 (file)
@@ -77,14 +77,13 @@ package math
 //     Log(0) = -Inf
 //     Log(x < 0) = NaN
 //     Log(NaN) = NaN
-
-//extern log
-func libc_log(float64) float64
-
 func Log(x float64) float64 {
        return libc_log(x)
 }
 
+//extern log
+func libc_log(float64) float64
+
 func log(x float64) float64 {
        const (
                Ln2Hi = 6.93147180369123816490e-01 /* 3fe62e42 fee00000 */
index 436788ff45372b8bf7a33600916c5118f1d616df..e223c7a1a00c4c391ff4f97b822b375d2e130bd8 100644 (file)
@@ -18,14 +18,13 @@ package math
 //     Mod(x, 0) = NaN
 //     Mod(x, ±Inf) = x
 //     Mod(x, NaN) = NaN
-
-//extern fmod
-func libc_fmod(float64, float64) float64
-
 func Mod(x, y float64) float64 {
        return libc_fmod(x, y)
 }
 
+//extern fmod
+func libc_fmod(float64, float64) float64
+
 func mod(x, y float64) float64 {
        if y == 0 || IsInf(x, 0) || IsNaN(x) || IsNaN(y) {
                return NaN()
index b59d4b7fd5a720892c8d654a3f7b28756dc0e3ac..bf08dc65568b7f2ea8963cd310671de20b373c42 100644 (file)
@@ -11,6 +11,9 @@ package math
 //     Modf(±Inf) = ±Inf, NaN
 //     Modf(NaN) = NaN, NaN
 func Modf(f float64) (int float64, frac float64) {
+       if haveArchModf {
+               return archModf(f)
+       }
        return modf(f)
 }
 
diff --git a/libgo/go/math/modf_noasm.go b/libgo/go/math/modf_noasm.go
new file mode 100644 (file)
index 0000000..42d4734
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//-go:build !arm64 && !ppc64 && !ppc64le
+// -build !arm64,!ppc64,!ppc64le
+
+package math
+
+const haveArchModf = false
+
+func archModf(f float64) (int float64, frac float64) {
+       panic("not implemented")
+}
diff --git a/libgo/go/math/rand/export_test.go b/libgo/go/math/rand/export_test.go
new file mode 100644 (file)
index 0000000..560010b
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rand
+
+func Int31nForTest(r *Rand, n int32) int32 {
+       return r.int31n(n)
+}
+
+func GetNormalDistributionParameters() (float64, [128]uint32, [128]float32, [128]float32) {
+       return rn, kn, wn, fn
+}
+
+func GetExponentialDistributionParameters() (float64, [256]uint32, [256]float32, [256]float32) {
+       return re, ke, we, fe
+}
index 0afc10d727ecd11e122cca61d6bd9d769bfd8572..7950e09fd7c3f2b7a99a1e093b831c2d154e96ce 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 // This program computes the value of rngCooked in rng.go,
index 186c7169d82ca901004d390d2e5362554b7b0912..e7d103664bba6fd7aca911c14eb3b8ac2a297596 100644 (file)
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package rand
+package rand_test
 
 import (
+       . "math/rand"
        "sync"
        "testing"
 )
index d6422c914d87afe1bcd5158a6fb384024981b045..13f20ca5efb28271d13f242a566ceaf5ff36be60 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Package rand implements pseudo-random number generators.
+// Package rand implements pseudo-random number generators unsuitable for
+// security-sensitive work.
 //
 // Random numbers are generated by a Source. Top-level functions, such as
 // Float64 and Int, use a default shared Source that produces a deterministic
 // The default Source is safe for concurrent use by multiple goroutines, but
 // Sources created by NewSource are not.
 //
-// Mathematical interval notation such as [0, n) is used throughout the
-// documentation for this package.
-//
-// For random numbers suitable for security-sensitive work, see the crypto/rand
-// package.
+// This package's outputs might be easily predictable regardless of how it's
+// seeded. For random numbers suitable for security-sensitive work, see the
+// crypto/rand package.
 package rand
 
 import "sync"
@@ -104,7 +103,7 @@ func (r *Rand) Int() int {
        return int(u << 1 >> 1) // clear sign bit if int == int32
 }
 
-// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n).
+// Int63n returns, as an int64, a non-negative pseudo-random number in the half-open interval [0,n).
 // It panics if n <= 0.
 func (r *Rand) Int63n(n int64) int64 {
        if n <= 0 {
@@ -121,7 +120,7 @@ func (r *Rand) Int63n(n int64) int64 {
        return v % n
 }
 
-// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n).
+// Int31n returns, as an int32, a non-negative pseudo-random number in the half-open interval [0,n).
 // It panics if n <= 0.
 func (r *Rand) Int31n(n int32) int32 {
        if n <= 0 {
@@ -138,7 +137,7 @@ func (r *Rand) Int31n(n int32) int32 {
        return v % n
 }
 
-// int31n returns, as an int32, a non-negative pseudo-random number in [0,n).
+// int31n returns, as an int32, a non-negative pseudo-random number in the half-open interval [0,n).
 // n must be > 0, but int31n does not check this; the caller must ensure it.
 // int31n exists because Int31n is inefficient, but Go 1 compatibility
 // requires that the stream of values produced by math/rand remain unchanged.
@@ -162,7 +161,7 @@ func (r *Rand) int31n(n int32) int32 {
        return int32(prod >> 32)
 }
 
-// Intn returns, as an int, a non-negative pseudo-random number in [0,n).
+// Intn returns, as an int, a non-negative pseudo-random number in the half-open interval [0,n).
 // It panics if n <= 0.
 func (r *Rand) Intn(n int) int {
        if n <= 0 {
@@ -174,7 +173,7 @@ func (r *Rand) Intn(n int) int {
        return int(r.Int63n(int64(n)))
 }
 
-// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0).
+// Float64 returns, as a float64, a pseudo-random number in the half-open interval [0.0,1.0).
 func (r *Rand) Float64() float64 {
        // A clearer, simpler implementation would be:
        //      return float64(r.Int63n(1<<53)) / (1<<53)
@@ -200,7 +199,7 @@ again:
        return f
 }
 
-// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0).
+// Float32 returns, as a float32, a pseudo-random number in the half-open interval [0.0,1.0).
 func (r *Rand) Float32() float32 {
        // Same rationale as in Float64: we want to preserve the Go 1 value
        // stream except we want to fix it not to return 1.0
@@ -213,7 +212,8 @@ again:
        return f
 }
 
-// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
+// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers
+// in the half-open interval [0,n).
 func (r *Rand) Perm(n int) []int {
        m := make([]int, n)
        // In the following loop, the iteration when i=0 always swaps m[0] with m[0].
@@ -321,31 +321,31 @@ func Int31() int32 { return globalRand.Int31() }
 // Int returns a non-negative pseudo-random int from the default Source.
 func Int() int { return globalRand.Int() }
 
-// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n)
+// Int63n returns, as an int64, a non-negative pseudo-random number in the half-open interval [0,n)
 // from the default Source.
 // It panics if n <= 0.
 func Int63n(n int64) int64 { return globalRand.Int63n(n) }
 
-// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n)
+// Int31n returns, as an int32, a non-negative pseudo-random number in the half-open interval [0,n)
 // from the default Source.
 // It panics if n <= 0.
 func Int31n(n int32) int32 { return globalRand.Int31n(n) }
 
-// Intn returns, as an int, a non-negative pseudo-random number in [0,n)
+// Intn returns, as an int, a non-negative pseudo-random number in the half-open interval [0,n)
 // from the default Source.
 // It panics if n <= 0.
 func Intn(n int) int { return globalRand.Intn(n) }
 
-// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0)
+// Float64 returns, as a float64, a pseudo-random number in the half-open interval [0.0,1.0)
 // from the default Source.
 func Float64() float64 { return globalRand.Float64() }
 
-// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0)
+// Float32 returns, as a float32, a pseudo-random number in the half-open interval [0.0,1.0)
 // from the default Source.
 func Float32() float32 { return globalRand.Float32() }
 
-// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n)
-// from the default Source.
+// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers
+// in the half-open interval [0,n) from the default Source.
 func Perm(n int) []int { return globalRand.Perm(n) }
 
 // Shuffle pseudo-randomizes the order of elements using the default Source.
index e037aaed0ea178402cff2a91312404bbd3b18290..462de8b73b4d574597984a4cf5da6f6b2078fbd6 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package rand
+package rand_test
 
 import (
        "bytes"
@@ -11,6 +11,7 @@ import (
        "internal/testenv"
        "io"
        "math"
+       . "math/rand"
        "os"
        "runtime"
        "testing"
@@ -21,6 +22,9 @@ const (
        numTestSamples = 10000
 )
 
+var rn, kn, wn, fn = GetNormalDistributionParameters()
+var re, ke, we, fe = GetExponentialDistributionParameters()
+
 type statsResults struct {
        mean        float64
        stddev      float64
@@ -503,7 +507,7 @@ func TestUniformFactorial(t *testing.T) {
                                fn   func() int
                        }{
                                {name: "Int31n", fn: func() int { return int(r.Int31n(int32(nfact))) }},
-                               {name: "int31n", fn: func() int { return int(r.int31n(int32(nfact))) }},
+                               {name: "int31n", fn: func() int { return int(Int31nForTest(r, int32(nfact))) }},
                                {name: "Perm", fn: func() int { return encodePerm(r.Perm(n)) }},
                                {name: "Shuffle", fn: func() int {
                                        // Generate permutation using Shuffle.
index 0e2903e109b55f98e6eac335e9035f65b0807d12..bf8bfd5553a7aca38a3955c0c3606d5c83e77f8a 100644 (file)
@@ -35,6 +35,9 @@ package math
 //     Remainder(x, ±Inf) = x
 //     Remainder(x, NaN) = NaN
 func Remainder(x, y float64) float64 {
+       if haveArchRemainder {
+               return archRemainder(x, y)
+       }
        return remainder(x, y)
 }
 
index 03fd14c8b27bfced5ae4930ad721820ba70763d4..bd8b9a7fd6fd7c28045d75ea688f8f4739eace0d 100644 (file)
@@ -114,14 +114,13 @@ var _cos = [...]float64{
 // Special cases are:
 //     Cos(±Inf) = NaN
 //     Cos(NaN) = NaN
-
-//extern cos
-func libc_cos(float64) float64
-
 func Cos(x float64) float64 {
        return libc_cos(x)
 }
 
+//extern cos
+func libc_cos(float64) float64
+
 func cos(x float64) float64 {
        const (
                PI4A = 7.85398125648498535156e-1  // 0x3fe921fb40000000, Pi/4 split into three parts
@@ -181,14 +180,13 @@ func cos(x float64) float64 {
 //     Sin(±0) = ±0
 //     Sin(±Inf) = NaN
 //     Sin(NaN) = NaN
-
-//extern sin
-func libc_sin(float64) float64
-
 func Sin(x float64) float64 {
        return libc_sin(x)
 }
 
+//extern sin
+func libc_sin(float64) float64
+
 func sin(x float64) float64 {
        const (
                PI4A = 7.85398125648498535156e-1  // 0x3fe921fb40000000, Pi/4 split into three parts
index 993424d5abad61451baf3ddb3bc65e9821886890..9fe9b4e17a15a28a41c2f7a997637cdf0eb8c220 100644 (file)
@@ -23,6 +23,13 @@ package math
 //     Sinh(±Inf) = ±Inf
 //     Sinh(NaN) = NaN
 func Sinh(x float64) float64 {
+       if haveArchSinh {
+               return archSinh(x)
+       }
+       return sinh(x)
+}
+
+func sinh(x float64) float64 {
        // The coefficients are #2029 from Hart & Cheney. (20.36D)
        const (
                P0 = -0.6307673640497716991184787251e+6
@@ -68,6 +75,13 @@ func Sinh(x float64) float64 {
 //     Cosh(±Inf) = +Inf
 //     Cosh(NaN) = NaN
 func Cosh(x float64) float64 {
+       if haveArchCosh {
+               return archCosh(x)
+       }
+       return cosh(x)
+}
+
+func cosh(x float64) float64 {
        x = Abs(x)
        if x > 21 {
                return Exp(x) * 0.5
diff --git a/libgo/go/math/stubs.go b/libgo/go/math/stubs.go
new file mode 100644 (file)
index 0000000..fe56800
--- /dev/null
@@ -0,0 +1,161 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//-go:build !s390x
+// -build !s390x
+
+// This is a large group of functions that most architectures don't
+// implement in assembly.
+
+package math
+
+const haveArchAcos = false
+
+func archAcos(x float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchAcosh = false
+
+func archAcosh(x float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchAsin = false
+
+func archAsin(x float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchAsinh = false
+
+func archAsinh(x float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchAtan = false
+
+func archAtan(x float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchAtan2 = false
+
+func archAtan2(y, x float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchAtanh = false
+
+func archAtanh(x float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchCbrt = false
+
+func archCbrt(x float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchCos = false
+
+func archCos(x float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchCosh = false
+
+func archCosh(x float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchErf = false
+
+func archErf(x float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchErfc = false
+
+func archErfc(x float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchExpm1 = false
+
+func archExpm1(x float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchFrexp = false
+
+func archFrexp(x float64) (float64, int) {
+       panic("not implemented")
+}
+
+const haveArchLdexp = false
+
+func archLdexp(frac float64, exp int) float64 {
+       panic("not implemented")
+}
+
+const haveArchLog10 = false
+
+func archLog10(x float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchLog2 = false
+
+func archLog2(x float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchLog1p = false
+
+func archLog1p(x float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchMod = false
+
+func archMod(x, y float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchPow = false
+
+func archPow(x, y float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchRemainder = false
+
+func archRemainder(x, y float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchSin = false
+
+func archSin(x float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchSinh = false
+
+func archSinh(x float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchTan = false
+
+func archTan(x float64) float64 {
+       panic("not implemented")
+}
+
+const haveArchTanh = false
+
+func archTanh(x float64) float64 {
+       panic("not implemented")
+}
index ca91d7149b520836e5cca809fc8f4683060d9e6f..eea29d34fb245b0a5132a94d8227daab13be33a8 100644 (file)
@@ -79,14 +79,13 @@ var _tanQ = [...]float64{
 //     Tan(±0) = ±0
 //     Tan(±Inf) = NaN
 //     Tan(NaN) = NaN
-
-//extern tan
-func libc_tan(float64) float64
-
 func Tan(x float64) float64 {
        return libc_tan(x)
 }
 
+//extern tan
+func libc_tan(float64) float64
+
 func tan(x float64) float64 {
        const (
                PI4A = 7.85398125648498535156e-1  // 0x3fe921fb40000000, Pi/4 split into three parts
index 009a206d3721ce768f58f89670d067fd16b7a905..a825678424648de5ea2ce41685939bf708fdec1c 100644 (file)
@@ -72,6 +72,13 @@ var tanhQ = [...]float64{
 //     Tanh(±Inf) = ±1
 //     Tanh(NaN) = NaN
 func Tanh(x float64) float64 {
+       if haveArchTanh {
+               return archTanh(x)
+       }
+       return tanh(x)
+}
+
+func tanh(x float64) float64 {
        const MAXLOG = 8.8029691931113054295988e+01 // log(2**127)
        z := Abs(x)
        switch {
index cb8bf393383cdd3e13eec778edb7ca21343bfe91..81bf722d4ee5fd79df3986c0ab1136e8491b7396 100644 (file)
@@ -20,6 +20,7 @@ import (
        "mime"
        "mime/quotedprintable"
        "net/textproto"
+       "path/filepath"
        "strings"
 )
 
@@ -67,13 +68,20 @@ func (p *Part) FormName() string {
        return p.dispositionParams["name"]
 }
 
-// FileName returns the filename parameter of the Part's
-// Content-Disposition header.
+// FileName returns the filename parameter of the Part's Content-Disposition
+// header. If not empty, the filename is passed through filepath.Base (which is
+// platform dependent) before being returned.
 func (p *Part) FileName() string {
        if p.dispositionParams == nil {
                p.parseContentDisposition()
        }
-       return p.dispositionParams["filename"]
+       filename := p.dispositionParams["filename"]
+       if filename == "" {
+               return ""
+       }
+       // RFC 7578, Section 4.2 requires that if a filename is provided, the
+       // directory path information must not be used.
+       return filepath.Base(filename)
 }
 
 func (p *Part) parseContentDisposition() {
diff --git a/libgo/go/mime/testdata/test.types.globs2 b/libgo/go/mime/testdata/test.types.globs2
new file mode 100644 (file)
index 0000000..cb5b789
--- /dev/null
@@ -0,0 +1,9 @@
+# Copyright 2021 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+
+# mime package test for globs2
+50:document/test:*.t3
+50:example/test:*.t4
+30:example/do-not-use:*.t4
index 6d2b89e405960e2f3d72a45d9612db428e743379..26424339af8d03b319c5dbb870f3562e80cde891 100644 (file)
@@ -58,6 +58,7 @@ func setMimeTypes(lowerExt, mixExt map[string]string) {
 }
 
 var builtinTypesLower = map[string]string{
+       ".avif": "image/avif",
        ".css":  "text/css; charset=utf-8",
        ".gif":  "image/gif",
        ".htm":  "text/html; charset=utf-8",
@@ -95,9 +96,11 @@ func initMime() {
 // Extensions are looked up first case-sensitively, then case-insensitively.
 //
 // The built-in table is small but on unix it is augmented by the local
-// system's mime.types file(s) if available under one or more of these
-// names:
+// system's MIME-info database or mime.types file(s) if available under one or
+// more of these names:
 //
+//   /usr/local/share/mime/globs2
+//   /usr/share/mime/globs2
 //   /etc/mime.types
 //   /etc/apache2/mime.types
 //   /etc/apache/mime.types
index 6ac056c7e2b81b4be6d05e5ad40659298a0ea492..753e9898fe4d48d54c556888ddd3280b769f0764 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris
 
 package mime
@@ -16,6 +17,14 @@ func init() {
        osInitMime = initMimeUnix
 }
 
+// See https://specifications.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-0.21.html
+// for the FreeDesktop Shared MIME-info Database specification.
+var mimeGlobs = []string{
+       "/usr/local/share/mime/globs2",
+       "/usr/share/mime/globs2",
+}
+
+// Common locations for mime.types files on unix.
 var typeFiles = []string{
        "/etc/mime.types",
        "/etc/apache2/mime.types",
@@ -23,6 +32,39 @@ var typeFiles = []string{
        "/etc/httpd/conf/mime.types",
 }
 
+func loadMimeGlobsFile(filename string) error {
+       f, err := os.Open(filename)
+       if err != nil {
+               return err
+       }
+       defer f.Close()
+
+       scanner := bufio.NewScanner(f)
+       for scanner.Scan() {
+               // Each line should be of format: weight:mimetype:*.ext
+               fields := strings.Split(scanner.Text(), ":")
+               if len(fields) < 3 || len(fields[0]) < 1 || len(fields[2]) < 2 {
+                       continue
+               } else if fields[0][0] == '#' || fields[2][0] != '*' {
+                       continue
+               }
+
+               extension := fields[2][1:]
+               if _, ok := mimeTypes.Load(extension); ok {
+                       // We've already seen this extension.
+                       // The file is in weight order, so we keep
+                       // the first entry that we see.
+                       continue
+               }
+
+               setExtensionType(extension, fields[1])
+       }
+       if err := scanner.Err(); err != nil {
+               panic(err)
+       }
+       return nil
+}
+
 func loadMimeFile(filename string) {
        f, err := os.Open(filename)
        if err != nil {
@@ -50,12 +92,20 @@ func loadMimeFile(filename string) {
 }
 
 func initMimeUnix() {
+       for _, filename := range mimeGlobs {
+               if err := loadMimeGlobsFile(filename); err == nil {
+                       return // Stop checking more files if mimetype database is found.
+               }
+       }
+
+       // Fallback if no system-generated mimetype database exists.
        for _, filename := range typeFiles {
                loadMimeFile(filename)
        }
 }
 
 func initMimeForTests() map[string]string {
+       mimeGlobs = []string{""}
        typeFiles = []string{"testdata/test.types"}
        return map[string]string{
                ".T1":  "application/test",
diff --git a/libgo/go/mime/type_unix_test.go b/libgo/go/mime/type_unix_test.go
new file mode 100644 (file)
index 0000000..6e29882
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris
+// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris
+
+package mime
+
+import (
+       "testing"
+)
+
+func initMimeUnixTest(t *testing.T) {
+       err := loadMimeGlobsFile("testdata/test.types.globs2")
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       loadMimeFile("testdata/test.types")
+}
+
+func TestTypeByExtensionUNIX(t *testing.T) {
+       initMimeUnixTest(t)
+       typeTests := map[string]string{
+               ".T1":  "application/test",
+               ".t2":  "text/test; charset=utf-8",
+               ".t3":  "document/test",
+               ".t4":  "example/test",
+               ".png": "image/png",
+       }
+
+       for ext, want := range typeTests {
+               val := TypeByExtension(ext)
+               if val != want {
+                       t.Errorf("TypeByExtension(%q) = %q, want %q", ext, val, want)
+               }
+       }
+}
index 6fb6bafdb4a546a3cc1953ff5dfa701bdcb7cc1f..4603c5591d832b4b73c56c95641dcd313f0beb39 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 // Minimal RFC 6724 address selection.
index a43ac5e5e755e70d0c37b603443ab81eec2d73ae..18784fec12cc288447ef590d7585f37cc282510f 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package net
index 4f23d9b1771ba3cc9f2516c4e2e9ff3d485141a0..577649f806360ccaa396f2eaea671ebe1c953ce0 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build cgo && !netgo
 // +build cgo,!netgo
 
 package net
index ab0368d14b5dba8424f2dc876c853de199b45501..4b1a2e3e1d44bdcd737708b58ef15bac41125b98 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build cgo && !netgo
 // +build cgo,!netgo
 
 package net
index c1adf20cd90d8e0c78f8ebfd6104d7a704c79885..1268c89dcc5316d330d2d3eff2f873834a8c6162 100644 (file)
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build cgo,!netgo
+//go:build cgo && !netgo && (darwin || dragonfly || freebsd)
+// +build cgo
+// +build !netgo
 // +build darwin dragonfly freebsd
 
 package net
index 36bac3439f8b96dfbc9c0750895923714b40a1f0..4b45daddcf7016333286bc7fba68a8947367e9d8 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !android && cgo && !netgo
 // +build !android,cgo,!netgo
 
 package net
index 1ce0139237b2f9f5e6211371bbbb19aaca46a4ce..e23899d325d55ec0bd3c65ab06a34255fbec2330 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build cgo && !netgo
 // +build cgo,!netgo
 
 package net
index 4610246561ef1f490c35a9a6672db0734f791346..3714793a52f3c5373f5346f56dd4b06f9d2e74da 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build cgo && !netgo
 // +build cgo,!netgo
 
 package net
index 8bc1c1cabb30c7bc76c6ed54f73556a518c03249..6611fd7a3bea7d6073ddc1f4f1e0ef1236f846b7 100644 (file)
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build cgo,!netgo
+//go:build cgo && !netgo && (aix || darwin || hurd || (linux && !android) || netbsd || solaris)
+// +build cgo
+// +build !netgo
 // +build aix darwin hurd linux,!android netbsd solaris
 
 package net
index 8e13e4156d0c78545783196b6c6ade7282277073..33f664c6644bd262b87d6dcae02d8d8e137f199e 100644 (file)
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build cgo,!netgo
+//go:build cgo && !netgo && (android || freebsd || dragonfly || openbsd)
+// +build cgo
+// +build !netgo
 // +build android freebsd dragonfly openbsd
 
 package net
index 9dcd15883e4d55da40e80aa93068105d17cce4eb..84b40c928d682cfbba5a888a4c967fe7ebeddcd4 100644 (file)
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build cgo,!netgo
+//go:build cgo && !netgo && (android || linux || solaris)
+// +build cgo
+// +build !netgo
 // +build android linux solaris
 
 package net
index f51467932feeb666ddfa140307f35f2fe85b94cc..703b41bafc919a7728340aa89f8e35de5b76be6d 100644 (file)
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build cgo,!netgo
+//go:build cgo && !netgo && (aix || darwin || dragonfly || freebsd || hurd || netbsd || openbsd)
+// +build cgo
+// +build !netgo
 // +build aix darwin dragonfly freebsd hurd netbsd openbsd
 
 package net
index bd1e8f3ae84e963e5dbdfdf6e4eaa898c5d66c79..95d5db5f9f4d49e564d5dc58c12b4a12c26f7248 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build cgo && !netgo
 // +build cgo,!netgo
 
 package net
index 041f8af12966a4363c3c4822061f7b956e478b40..039e4be88b908a257dd426daba8d6616a1d39421 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !cgo || netgo
 // +build !cgo netgo
 
 package net
index 0c9a488811b47531d29ecc9b86f38c3c2e25c0ba..462bf12f92f3a1ce5e8791deaecb08ecd852b3b8 100644 (file)
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build cgo,!netgo
+//go:build cgo && !netgo && (aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris)
+// +build cgo
+// +build !netgo
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package net
index e844ef57c5cb5fe8421e737f9f12cf5a28b567a8..98b3b4a3c13c87ee0eef77796d0ed105be74e17f 100644 (file)
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build cgo,!netgo
+//go:build cgo && !netgo && (aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris)
+// +build cgo
+// +build !netgo
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package net
index 8968b757a905791724b898af09b3a89cf2bdbe49..1fd1f29787c8601a4875143da36d5e91fdbb21cc 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build cgo && !netgo
 // +build cgo,!netgo
 
 package net
index b0f1b7968adf2ecfeea1b85ffc91ff1f26fa1f2e..fe7ebf18f32ec7643fa89ab67c5f61341cfae66d 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package net
index abc33cee475c042eaf5d6e9156df71d8f8fec2a9..c705152c97316d52c735b9385fb37e115ecc12ba 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build netcgo
 // +build netcgo
 
 package net
index a8e18070f4ad44833c209bdffa4cd78d20ba17ca..f5e4d86c5d30ce5227e19b592c566d5d319f61f0 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package net
index 771cabcd3cd331d34e1958fdb05cb8b33952d596..45e271c264267ae10f1ed58bc2d40f1d04c8fa3a 100644 (file)
@@ -5,6 +5,7 @@
 // This file implements API tests across platforms and will never have a build
 // tag.
 
+//go:build !js
 // +build !js
 
 package net
index 13a312a91ae06b41a6a119d064a55b0a57bc2437..486ced0f2a99c2775ceeca78c648ab7678e7d680 100644 (file)
@@ -344,6 +344,9 @@ type sysDialer struct {
 //
 // See func Dial for a description of the network and address
 // parameters.
+//
+// Dial uses context.Background internally; to specify the context, use
+// DialContext.
 func (d *Dialer) Dial(network, address string) (Conn, error) {
        return d.DialContext(context.Background(), network, address)
 }
@@ -701,6 +704,9 @@ type sysListener struct {
 //
 // See func Dial for a description of the network and address
 // parameters.
+//
+// Listen uses context.Background internally; to specify the context, use
+// ListenConfig.Listen.
 func Listen(network, address string) (Listener, error) {
        var lc ListenConfig
        return lc.Listen(context.Background(), network, address)
@@ -728,6 +734,9 @@ func Listen(network, address string) (Listener, error) {
 //
 // See func Dial for a description of the network and address
 // parameters.
+//
+// ListenPacket uses context.Background internally; to specify the context, use
+// ListenConfig.ListenPacket.
 func ListenPacket(network, address string) (PacketConn, error) {
        var lc ListenConfig
        return lc.ListenPacket(context.Background(), network, address)
index 57cf5554ad2c69e980ec3f46b8614de16e8e3e68..723038c7a22a44b6dfc73443ca6b344b855f096f 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js
 // +build !js
 
 package net
@@ -154,40 +155,27 @@ func slowDialTCP(ctx context.Context, network string, laddr, raddr *TCPAddr) (*T
        return c, err
 }
 
-func dialClosedPort(t *testing.T) (actual, expected time.Duration) {
-       // Estimate the expected time for this platform.
-       // On Windows, dialing a closed port takes roughly 1 second,
-       // but other platforms should be instantaneous.
-       if runtime.GOOS == "windows" {
-               expected = 1500 * time.Millisecond
-       } else if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
-               expected = 150 * time.Millisecond
-       } else {
-               expected = 95 * time.Millisecond
-       }
+func dialClosedPort(t *testing.T) (dialLatency time.Duration) {
+       // On most platforms, dialing a closed port should be nearly instantaneous —
+       // less than a few hundred milliseconds. However, on some platforms it may be
+       // much slower: on Windows and OpenBSD, it has been observed to take up to a
+       // few seconds.
 
        l, err := Listen("tcp", "127.0.0.1:0")
        if err != nil {
-               t.Logf("dialClosedPort: Listen failed: %v", err)
-               return 999 * time.Hour, expected
+               t.Fatalf("dialClosedPort: Listen failed: %v", err)
        }
        addr := l.Addr().String()
        l.Close()
-       // On OpenBSD, interference from TestTCPSelfConnect is mysteriously
-       // causing the first attempt to hang for a few seconds, so we throw
-       // away the first result and keep the second.
-       for i := 1; ; i++ {
-               startTime := time.Now()
-               c, err := Dial("tcp", addr)
-               if err == nil {
-                       c.Close()
-               }
-               elapsed := time.Now().Sub(startTime)
-               if i == 2 {
-                       t.Logf("dialClosedPort: measured delay %v", elapsed)
-                       return elapsed, expected
-               }
+
+       startTime := time.Now()
+       c, err := Dial("tcp", addr)
+       if err == nil {
+               c.Close()
        }
+       elapsed := time.Now().Sub(startTime)
+       t.Logf("dialClosedPort: measured delay %v", elapsed)
+       return elapsed
 }
 
 func TestDialParallel(t *testing.T) {
@@ -197,10 +185,7 @@ func TestDialParallel(t *testing.T) {
                t.Skip("both IPv4 and IPv6 are required")
        }
 
-       closedPortDelay, expectClosedPortDelay := dialClosedPort(t)
-       if closedPortDelay > expectClosedPortDelay {
-               t.Errorf("got %v; want <= %v", closedPortDelay, expectClosedPortDelay)
-       }
+       closedPortDelay := dialClosedPort(t)
 
        const instant time.Duration = 0
        const fallbackDelay = 200 * time.Millisecond
@@ -655,15 +640,7 @@ func TestDialerLocalAddr(t *testing.T) {
                }
                c, err := d.Dial(tt.network, addr)
                if err == nil && tt.error != nil || err != nil && tt.error == nil {
-                       // A suspected kernel bug in macOS 10.12 occasionally results in
-                       // timeout errors when dialing address ::1. The errors have not
-                       // been observed on newer versions of the OS, so we don't plan to work
-                       // around them. See https://golang.org/issue/22019.
-                       if tt.raddr == "::1" && os.Getenv("GO_BUILDER_NAME") == "darwin-amd64-10_12" && os.IsTimeout(err) {
-                               t.Logf("ignoring timeout error on Darwin; see https://golang.org/issue/22019")
-                       } else {
-                               t.Errorf("%s %v->%s: got %v; want %v", tt.network, tt.laddr, tt.raddr, err, tt.error)
-                       }
+                       t.Errorf("%s %v->%s: got %v; want %v", tt.network, tt.laddr, tt.raddr, err, tt.error)
                }
                if err != nil {
                        if perr := parseDialError(err); perr != nil {
@@ -682,10 +659,7 @@ func TestDialerDualStack(t *testing.T) {
                t.Skip("both IPv4 and IPv6 are required")
        }
 
-       closedPortDelay, expectClosedPortDelay := dialClosedPort(t)
-       if closedPortDelay > expectClosedPortDelay {
-               t.Errorf("got %v; want <= %v", closedPortDelay, expectClosedPortDelay)
-       }
+       closedPortDelay := dialClosedPort(t)
 
        origTestHookLookupIP := testHookLookupIP
        defer func() { testHookLookupIP = origTestHookLookupIP }()
index 1891d8c44301c84cbf54f0d28b342b47768d1075..4b9bc2792057042cdf500adbfb8c3383c25b12ba 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package net
index e9c73845d78d7eee4bacc8645ec33685f70cc4cb..1bbe39650bbac2f7ec755d8de90c2ccae3845632 100644 (file)
@@ -5,6 +5,7 @@
 package net
 
 import (
+       "internal/itoa"
        "sort"
 
        "golang.org/x/net/dns/dnsmessage"
@@ -33,7 +34,7 @@ func reverseaddr(addr string) (arpa string, err error) {
                return "", &DNSError{Err: "unrecognized address", Name: addr}
        }
        if ip.To4() != nil {
-               return uitoa(uint(ip[15])) + "." + uitoa(uint(ip[14])) + "." + uitoa(uint(ip[13])) + "." + uitoa(uint(ip[12])) + ".in-addr.arpa.", nil
+               return itoa.Uitoa(uint(ip[15])) + "." + itoa.Uitoa(uint(ip[14])) + "." + itoa.Uitoa(uint(ip[13])) + "." + itoa.Uitoa(uint(ip[12])) + ".in-addr.arpa.", nil
        }
        // Must be IPv6
        buf := make([]byte, 0, len(ip)*4+len("ip6.arpa."))
index c5bfab92a0f5f51c2a59fc2e83d3700059de753e..a326319649a6dd31060140ead06553698b37e3a0 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 // DNS client: see RFC 1035.
@@ -17,6 +18,7 @@ package net
 import (
        "context"
        "errors"
+       "internal/itoa"
        "io"
        "os"
        "sync"
@@ -509,7 +511,7 @@ func (o hostLookupOrder) String() string {
        if s, ok := lookupOrderName[o]; ok {
                return s
        }
-       return "hostLookupOrder=" + itoa(int(o)) + "??"
+       return "hostLookupOrder=" + itoa.Itoa(int(o)) + "??"
 }
 
 // goLookupHost is the native Go implementation of LookupHost.
@@ -530,7 +532,7 @@ func (r *Resolver) goLookupHostOrder(ctx context.Context, name string, order hos
                        return
                }
        }
-       ips, _, err := r.goLookupIPCNAMEOrder(ctx, name, order)
+       ips, _, err := r.goLookupIPCNAMEOrder(ctx, "ip", name, order)
        if err != nil {
                return
        }
@@ -556,13 +558,13 @@ func goLookupIPFiles(name string) (addrs []IPAddr) {
 
 // goLookupIP is the native Go implementation of LookupIP.
 // The libc versions are in cgo_*.go.
-func (r *Resolver) goLookupIP(ctx context.Context, host string) (addrs []IPAddr, err error) {
+func (r *Resolver) goLookupIP(ctx context.Context, network, host string) (addrs []IPAddr, err error) {
        order := systemConf().hostLookupOrder(r, host)
-       addrs, _, err = r.goLookupIPCNAMEOrder(ctx, host, order)
+       addrs, _, err = r.goLookupIPCNAMEOrder(ctx, network, host, order)
        return
 }
 
-func (r *Resolver) goLookupIPCNAMEOrder(ctx context.Context, name string, order hostLookupOrder) (addrs []IPAddr, cname dnsmessage.Name, err error) {
+func (r *Resolver) goLookupIPCNAMEOrder(ctx context.Context, network, name string, order hostLookupOrder) (addrs []IPAddr, cname dnsmessage.Name, err error) {
        if order == hostLookupFilesDNS || order == hostLookupFiles {
                addrs = goLookupIPFiles(name)
                if len(addrs) > 0 || order == hostLookupFiles {
@@ -583,7 +585,13 @@ func (r *Resolver) goLookupIPCNAMEOrder(ctx context.Context, name string, order
                error
        }
        lane := make(chan result, 1)
-       qtypes := [...]dnsmessage.Type{dnsmessage.TypeA, dnsmessage.TypeAAAA}
+       qtypes := []dnsmessage.Type{dnsmessage.TypeA, dnsmessage.TypeAAAA}
+       switch ipVersion(network) {
+       case '4':
+               qtypes = []dnsmessage.Type{dnsmessage.TypeA}
+       case '6':
+               qtypes = []dnsmessage.Type{dnsmessage.TypeAAAA}
+       }
        var queryFn func(fqdn string, qtype dnsmessage.Type)
        var responseFn func(fqdn string, qtype dnsmessage.Type) result
        if conf.singleRequest {
@@ -728,7 +736,7 @@ func (r *Resolver) goLookupIPCNAMEOrder(ctx context.Context, name string, order
 // goLookupCNAME is the native Go (non-cgo) implementation of LookupCNAME.
 func (r *Resolver) goLookupCNAME(ctx context.Context, host string) (string, error) {
        order := systemConf().hostLookupOrder(r, host)
-       _, cname, err := r.goLookupIPCNAMEOrder(ctx, host, order)
+       _, cname, err := r.goLookupIPCNAMEOrder(ctx, "ip", host, order)
        return cname.String(), err
 }
 
index 3c9ada365c4a70d2e8358023b6fc94c01ab74acb..ce1a4f358625e7ac771dfecbe441aab2c5674afe 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package net
@@ -600,14 +601,14 @@ func TestGoLookupIPOrderFallbackToFile(t *testing.T) {
                name := fmt.Sprintf("order %v", order)
 
                // First ensure that we get an error when contacting a non-existent host.
-               _, _, err := r.goLookupIPCNAMEOrder(context.Background(), "notarealhost", order)
+               _, _, err := r.goLookupIPCNAMEOrder(context.Background(), "ip", "notarealhost", order)
                if err == nil {
                        t.Errorf("%s: expected error while looking up name not in hosts file", name)
                        continue
                }
 
                // Now check that we get an address when the name appears in the hosts file.
-               addrs, _, err := r.goLookupIPCNAMEOrder(context.Background(), "thor", order) // entry is in "testdata/hosts"
+               addrs, _, err := r.goLookupIPCNAMEOrder(context.Background(), "ip", "thor", order) // entry is in "testdata/hosts"
                if err != nil {
                        t.Errorf("%s: expected to successfully lookup host entry", name)
                        continue
@@ -1845,6 +1846,17 @@ func TestCVE202133195(t *testing.T) {
                                                        Target: dnsmessage.MustNewName("<html>.golang.org."),
                                                },
                                        },
+                                       dnsmessage.Resource{
+                                               Header: dnsmessage.ResourceHeader{
+                                                       Name:   n,
+                                                       Type:   dnsmessage.TypeSRV,
+                                                       Class:  dnsmessage.ClassINET,
+                                                       Length: 4,
+                                               },
+                                               Body: &dnsmessage.SRVResource{
+                                                       Target: dnsmessage.MustNewName("good.golang.org."),
+                                               },
+                                       },
                                )
                        case dnsmessage.TypeMX:
                                r.Answers = append(r.Answers,
@@ -1859,6 +1871,17 @@ func TestCVE202133195(t *testing.T) {
                                                        MX: dnsmessage.MustNewName("<html>.golang.org."),
                                                },
                                        },
+                                       dnsmessage.Resource{
+                                               Header: dnsmessage.ResourceHeader{
+                                                       Name:   dnsmessage.MustNewName("good.golang.org."),
+                                                       Type:   dnsmessage.TypeMX,
+                                                       Class:  dnsmessage.ClassINET,
+                                                       Length: 4,
+                                               },
+                                               Body: &dnsmessage.MXResource{
+                                                       MX: dnsmessage.MustNewName("good.golang.org."),
+                                               },
+                                       },
                                )
                        case dnsmessage.TypeNS:
                                r.Answers = append(r.Answers,
@@ -1873,6 +1896,17 @@ func TestCVE202133195(t *testing.T) {
                                                        NS: dnsmessage.MustNewName("<html>.golang.org."),
                                                },
                                        },
+                                       dnsmessage.Resource{
+                                               Header: dnsmessage.ResourceHeader{
+                                                       Name:   dnsmessage.MustNewName("good.golang.org."),
+                                                       Type:   dnsmessage.TypeNS,
+                                                       Class:  dnsmessage.ClassINET,
+                                                       Length: 4,
+                                               },
+                                               Body: &dnsmessage.NSResource{
+                                                       NS: dnsmessage.MustNewName("good.golang.org."),
+                                               },
+                                       },
                                )
                        case dnsmessage.TypePTR:
                                r.Answers = append(r.Answers,
@@ -1887,6 +1921,17 @@ func TestCVE202133195(t *testing.T) {
                                                        PTR: dnsmessage.MustNewName("<html>.golang.org."),
                                                },
                                        },
+                                       dnsmessage.Resource{
+                                               Header: dnsmessage.ResourceHeader{
+                                                       Name:   dnsmessage.MustNewName("good.golang.org."),
+                                                       Type:   dnsmessage.TypePTR,
+                                                       Class:  dnsmessage.ClassINET,
+                                                       Length: 4,
+                                               },
+                                               Body: &dnsmessage.PTRResource{
+                                                       PTR: dnsmessage.MustNewName("good.golang.org."),
+                                               },
+                                       },
                                )
                        }
                        return r, nil
@@ -1902,57 +1947,177 @@ func TestCVE202133195(t *testing.T) {
        defer func(orig string) { testHookHostsPath = orig }(testHookHostsPath)
        testHookHostsPath = "testdata/hosts"
 
-       _, err := r.LookupCNAME(context.Background(), "golang.org")
-       if expected := "lookup golang.org: CNAME target is invalid"; err == nil || err.Error() != expected {
-               t.Errorf("Resolver.LookupCNAME returned unexpected error, got %q, want %q", err, expected)
-       }
-       _, err = LookupCNAME("golang.org")
-       if expected := "lookup golang.org: CNAME target is invalid"; err == nil || err.Error() != expected {
-               t.Errorf("LookupCNAME returned unexpected error, got %q, want %q", err, expected)
-       }
-
-       _, _, err = r.LookupSRV(context.Background(), "target", "tcp", "golang.org")
-       if expected := "lookup golang.org: SRV target is invalid"; err == nil || err.Error() != expected {
-               t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err, expected)
-       }
-       _, _, err = LookupSRV("target", "tcp", "golang.org")
-       if expected := "lookup golang.org: SRV target is invalid"; err == nil || err.Error() != expected {
-               t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err, expected)
+       tests := []struct {
+               name string
+               f    func(*testing.T)
+       }{
+               {
+                       name: "CNAME",
+                       f: func(t *testing.T) {
+                               expectedErr := &DNSError{Err: errMalformedDNSRecordsDetail, Name: "golang.org"}
+                               _, err := r.LookupCNAME(context.Background(), "golang.org")
+                               if err.Error() != expectedErr.Error() {
+                                       t.Fatalf("unexpected error: %s", err)
+                               }
+                               _, err = LookupCNAME("golang.org")
+                               if err.Error() != expectedErr.Error() {
+                                       t.Fatalf("unexpected error: %s", err)
+                               }
+                       },
+               },
+               {
+                       name: "SRV (bad record)",
+                       f: func(t *testing.T) {
+                               expected := []*SRV{
+                                       {
+                                               Target: "good.golang.org.",
+                                       },
+                               }
+                               expectedErr := &DNSError{Err: errMalformedDNSRecordsDetail, Name: "golang.org"}
+                               _, records, err := r.LookupSRV(context.Background(), "target", "tcp", "golang.org")
+                               if err.Error() != expectedErr.Error() {
+                                       t.Fatalf("unexpected error: %s", err)
+                               }
+                               if !reflect.DeepEqual(records, expected) {
+                                       t.Error("Unexpected record set")
+                               }
+                               _, records, err = LookupSRV("target", "tcp", "golang.org")
+                               if err.Error() != expectedErr.Error() {
+                                       t.Errorf("unexpected error: %s", err)
+                               }
+                               if !reflect.DeepEqual(records, expected) {
+                                       t.Error("Unexpected record set")
+                               }
+                       },
+               },
+               {
+                       name: "SRV (bad header)",
+                       f: func(t *testing.T) {
+                               _, _, err := r.LookupSRV(context.Background(), "hdr", "tcp", "golang.org.")
+                               if expected := "lookup golang.org.: SRV header name is invalid"; err == nil || err.Error() != expected {
+                                       t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err, expected)
+                               }
+                               _, _, err = LookupSRV("hdr", "tcp", "golang.org.")
+                               if expected := "lookup golang.org.: SRV header name is invalid"; err == nil || err.Error() != expected {
+                                       t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err, expected)
+                               }
+                       },
+               },
+               {
+                       name: "MX",
+                       f: func(t *testing.T) {
+                               expected := []*MX{
+                                       {
+                                               Host: "good.golang.org.",
+                                       },
+                               }
+                               expectedErr := &DNSError{Err: errMalformedDNSRecordsDetail, Name: "golang.org"}
+                               records, err := r.LookupMX(context.Background(), "golang.org")
+                               if err.Error() != expectedErr.Error() {
+                                       t.Fatalf("unexpected error: %s", err)
+                               }
+                               if !reflect.DeepEqual(records, expected) {
+                                       t.Error("Unexpected record set")
+                               }
+                               records, err = LookupMX("golang.org")
+                               if err.Error() != expectedErr.Error() {
+                                       t.Fatalf("unexpected error: %s", err)
+                               }
+                               if !reflect.DeepEqual(records, expected) {
+                                       t.Error("Unexpected record set")
+                               }
+                       },
+               },
+               {
+                       name: "NS",
+                       f: func(t *testing.T) {
+                               expected := []*NS{
+                                       {
+                                               Host: "good.golang.org.",
+                                       },
+                               }
+                               expectedErr := &DNSError{Err: errMalformedDNSRecordsDetail, Name: "golang.org"}
+                               records, err := r.LookupNS(context.Background(), "golang.org")
+                               if err.Error() != expectedErr.Error() {
+                                       t.Fatalf("unexpected error: %s", err)
+                               }
+                               if !reflect.DeepEqual(records, expected) {
+                                       t.Error("Unexpected record set")
+                               }
+                               records, err = LookupNS("golang.org")
+                               if err.Error() != expectedErr.Error() {
+                                       t.Fatalf("unexpected error: %s", err)
+                               }
+                               if !reflect.DeepEqual(records, expected) {
+                                       t.Error("Unexpected record set")
+                               }
+                       },
+               },
+               {
+                       name: "Addr",
+                       f: func(t *testing.T) {
+                               expected := []string{"good.golang.org."}
+                               expectedErr := &DNSError{Err: errMalformedDNSRecordsDetail, Name: "192.0.2.42"}
+                               records, err := r.LookupAddr(context.Background(), "192.0.2.42")
+                               if err.Error() != expectedErr.Error() {
+                                       t.Fatalf("unexpected error: %s", err)
+                               }
+                               if !reflect.DeepEqual(records, expected) {
+                                       t.Error("Unexpected record set")
+                               }
+                               records, err = LookupAddr("192.0.2.42")
+                               if err.Error() != expectedErr.Error() {
+                                       t.Fatalf("unexpected error: %s", err)
+                               }
+                               if !reflect.DeepEqual(records, expected) {
+                                       t.Error("Unexpected record set")
+                               }
+                       },
+               },
        }
 
-       _, _, err = r.LookupSRV(context.Background(), "hdr", "tcp", "golang.org")
-       if expected := "lookup golang.org: SRV header name is invalid"; err == nil || err.Error() != expected {
-               t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err, expected)
-       }
-       _, _, err = LookupSRV("hdr", "tcp", "golang.org")
-       if expected := "lookup golang.org: SRV header name is invalid"; err == nil || err.Error() != expected {
-               t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err, expected)
+       for _, tc := range tests {
+               t.Run(tc.name, tc.f)
        }
 
-       _, err = r.LookupMX(context.Background(), "golang.org")
-       if expected := "lookup golang.org: MX target is invalid"; err == nil || err.Error() != expected {
-               t.Errorf("Resolver.LookupMX returned unexpected error, got %q, want %q", err, expected)
-       }
-       _, err = LookupMX("golang.org")
-       if expected := "lookup golang.org: MX target is invalid"; err == nil || err.Error() != expected {
-               t.Errorf("LookupMX returned unexpected error, got %q, want %q", err, expected)
-       }
+}
 
-       _, err = r.LookupNS(context.Background(), "golang.org")
-       if expected := "lookup golang.org: NS target is invalid"; err == nil || err.Error() != expected {
-               t.Errorf("Resolver.LookupNS returned unexpected error, got %q, want %q", err, expected)
-       }
-       _, err = LookupNS("golang.org")
-       if expected := "lookup golang.org: NS target is invalid"; err == nil || err.Error() != expected {
-               t.Errorf("LookupNS returned unexpected error, got %q, want %q", err, expected)
+func TestNullMX(t *testing.T) {
+       fake := fakeDNSServer{
+               rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
+                       r := dnsmessage.Message{
+                               Header: dnsmessage.Header{
+                                       ID:       q.Header.ID,
+                                       Response: true,
+                                       RCode:    dnsmessage.RCodeSuccess,
+                               },
+                               Questions: q.Questions,
+                               Answers: []dnsmessage.Resource{
+                                       {
+                                               Header: dnsmessage.ResourceHeader{
+                                                       Name:  q.Questions[0].Name,
+                                                       Type:  dnsmessage.TypeMX,
+                                                       Class: dnsmessage.ClassINET,
+                                               },
+                                               Body: &dnsmessage.MXResource{
+                                                       MX: dnsmessage.MustNewName("."),
+                                               },
+                                       },
+                               },
+                       }
+                       return r, nil
+               },
        }
-
-       _, err = r.LookupAddr(context.Background(), "192.0.2.42")
-       if expected := "lookup 192.0.2.42: PTR target is invalid"; err == nil || err.Error() != expected {
-               t.Errorf("Resolver.LookupAddr returned unexpected error, got %q, want %q", err, expected)
+       r := Resolver{PreferGo: true, Dial: fake.DialContext}
+       rrset, err := r.LookupMX(context.Background(), "golang.org")
+       if err != nil {
+               t.Fatalf("LookupMX: %v", err)
        }
-       _, err = LookupAddr("192.0.2.42")
-       if expected := "lookup 192.0.2.42: PTR target is invalid"; err == nil || err.Error() != expected {
-               t.Errorf("LookupAddr returned unexpected error, got %q, want %q", err, expected)
+       if want := []*MX{&MX{Host: "."}}; !reflect.DeepEqual(rrset, want) {
+               records := []string{}
+               for _, rr := range rrset {
+                       records = append(records, fmt.Sprintf("%v", rr))
+               }
+               t.Errorf("records = [%v]; want [%v]", strings.Join(records, " "), want[0])
        }
 }
index b76b32fb253ac99f4649f93db4e59a3cb7adf395..4b116029b8742280eafd7ae2f508310fefb34e82 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 // Read system DNS config from /etc/resolv.conf
index f6edffcd7913e3cb948c70a9278898d1c394e807..59e21d67d5800fb162284170a09028b491db5a1e 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package net
index 2964982311ce4b306494f26216168a45c0fe4859..d851bf75667d3a6c6c00f75a8220ab67b8ea08d0 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js
 // +build !js
 
 package net
index c13d5bcd3132231584fbd8230f4dee4db6cacdfd..017f2cb24490ae89bae7146cf2f6275299aef1d5 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows
 
 package net
index b411a378dfc70045e02d001aea4a57e886ce72a9..ea52a45ee89db67def805df8be4b21f3e9d57a97 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !plan9
 // +build !plan9
 
 package net
index 556eb8c8d47c9630c402e2da1f16c74855f30fb0..c304390819a915331276a62c68760ec986d57b8d 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js
 // +build !js
 
 package net
index 415e928bc8e8451c71a09676bcc685822c3f96c1..3de4e76a9f4133ff1a6027e10674824c76937a95 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || js || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd js linux netbsd openbsd solaris
 
 package net
index 9ce9e12c5ecd0970bff09391ebadb64a97eebe5d..533a45e648f11803f10f51095954975e286f1c4b 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !plan9 && !windows
 // +build !plan9,!windows
 
 package net
index f3c69c407f7c1e3f4315d091dd6c602a0c487334..b8753cc092bf1b9d322db63db93addba66022be6 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js
 // +build !js
 
 package net
diff --git a/libgo/go/net/fcntl_libc_test.go b/libgo/go/net/fcntl_libc_test.go
new file mode 100644 (file)
index 0000000..02511c5
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build aix || darwin || solaris
+// +build aix darwin solaris
+
+package net
+
+import "syscall"
+
+// Use a helper function to call fcntl.  This is defined in C in
+// libgo/runtime.
+//extern __go_fcntl_uintptr
+func libc_fcntl(uintptr, uintptr, uintptr) (uintptr, uintptr)
+
+// Implemented in the syscall package.
+//go:linkname fcntl syscall.fcntl
+func fcntl(fd int, cmd int, arg int) (int, error) {
+       syscall.Entersyscall()
+       r, e := libc_fcntl(uintptr(fd), uintptr(cmd), uintptr(arg))
+       syscall.Exitsyscall()
+       if e != 0 {
+               return int(r), syscall.Errno(e)
+       }
+       return int(r), nil
+}
diff --git a/libgo/go/net/fcntl_syscall_test.go b/libgo/go/net/fcntl_syscall_test.go
new file mode 100644 (file)
index 0000000..59ba1a1
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build dragonfly || freebsd || linux || netbsd || openbsd
+// +build dragonfly freebsd linux netbsd openbsd
+
+package net
+
+import (
+       "syscall"
+)
+
+// Use a helper function to call fcntl.  This is defined in C in
+// libgo/runtime.
+//extern __go_fcntl_uintptr
+func libc_fcntl(uintptr, uintptr, uintptr) (uintptr, uintptr)
+
+func fcntl(fd int, cmd int, arg int) (int, error) {
+       syscall.Entersyscall()
+       r, e := libc_fcntl(uintptr(fd), uintptr(cmd), uintptr(arg))
+       syscall.Exitsyscall()
+       if e != 0 {
+               return int(r), syscall.Errno(e)
+       }
+       return int(r), nil
+}
index b2f99bc7da330aa09c800d3a481d14bcff1850f1..a0f1f5a789befc293b0bdd052342c1b87f5a1dc6 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris || windows
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris windows
 
 package net
@@ -63,10 +64,10 @@ func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
        return n, sa, wrapSyscallError(readFromSyscallName, err)
 }
 
-func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
-       n, oobn, flags, sa, err = fd.pfd.ReadMsg(p, oob)
+func (fd *netFD) readMsg(p []byte, oob []byte, flags int) (n, oobn, retflags int, sa syscall.Sockaddr, err error) {
+       n, oobn, retflags, sa, err = fd.pfd.ReadMsg(p, oob, flags)
        runtime.KeepAlive(fd)
-       return n, oobn, flags, sa, wrapSyscallError(readMsgSyscallName, err)
+       return n, oobn, retflags, sa, wrapSyscallError(readMsgSyscallName, err)
 }
 
 func (fd *netFD) Write(p []byte) (nn int, err error) {
index ad79c0677928742a120adc4225e7e9b02fdb24e2..e2db165ade8ac79b9b28b26996d962a9c98787b9 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package net
index bfb8100f53cf068583b23703c4204b40aa89ad51..9f988fe89936179a3f177e266d15f2afd38f4219 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build js && wasm
 // +build js,wasm
 
 package net
index 8c09c0da1bd93ec9818227cdc32bab46c7cf061f..a70ef1b312ff127eb8d4c430c5aa07d3bdb1933a 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js
 // +build !js
 
 package net
index 25caafb9fa82288ca9c57dde1358a4029f3f9ba2..d36a8812998af9aa23275911e0422ce46e31bc5c 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package net
index 780b23caba332ce2db69c24f28465dfde5229ce9..618c6c2f428846cfd4b50ef08259f09b7a20fd12 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris
 
 package net
index f850e2fccfd2baf03e9be8ee8ba02dbdd5555a09..19c43999f9291ca77a13053c92b7efedc1c8e95e 100644 (file)
@@ -36,7 +36,7 @@ var lookupStaticHostTests = []struct {
                },
        },
        {
-               "testdata/ipv4-hosts", // see golang.org/issue/8996
+               "testdata/ipv4-hosts",
                []staticHostEntry{
                        {"localhost", []string{"127.0.0.1", "127.0.0.2", "127.0.0.3"}},
                        {"localhost.localdomain", []string{"127.0.0.3"}},
@@ -102,7 +102,7 @@ var lookupStaticAddrTests = []struct {
                },
        },
        {
-               "testdata/ipv4-hosts", // see golang.org/issue/8996
+               "testdata/ipv4-hosts",
                []staticHostEntry{
                        {"127.0.0.1", []string{"localhost"}},
                        {"127.0.0.2", []string{"localhost"}},
index 76cbca8e6036725ac5091b0dd51ffbd2e2869677..ef2eaf748bdb66df7071530e8cf2a57630fff567 100644 (file)
@@ -95,12 +95,6 @@ func (w *limitWriter) Write(p []byte) (n int, err error) {
 func TestKillChildAfterCopyError(t *testing.T) {
        testenv.MustHaveExec(t)
 
-       defer func() { testHookStartProcess = nil }()
-       proc := make(chan *os.Process, 1)
-       testHookStartProcess = func(p *os.Process) {
-               proc <- p
-       }
-
        h := &Handler{
                Path: os.Args[0],
                Root: "/test.go",
@@ -112,26 +106,9 @@ func TestKillChildAfterCopyError(t *testing.T) {
        const writeLen = 50 << 10
        rw := &customWriterRecorder{&limitWriter{&out, writeLen}, rec}
 
-       donec := make(chan bool, 1)
-       go func() {
-               h.ServeHTTP(rw, req)
-               donec <- true
-       }()
-
-       select {
-       case <-donec:
-               if out.Len() != writeLen || out.Bytes()[0] != 'a' {
-                       t.Errorf("unexpected output: %q", out.Bytes())
-               }
-       case <-time.After(5 * time.Second):
-               t.Errorf("timeout. ServeHTTP hung and didn't kill the child process?")
-               select {
-               case p := <-proc:
-                       p.Kill()
-                       t.Logf("killed process")
-               default:
-                       t.Logf("didn't kill process")
-               }
+       h.ServeHTTP(rw, req)
+       if out.Len() != writeLen || out.Bytes()[0] != 'a' {
+               t.Errorf("unexpected output: %q", out.Bytes())
        }
 }
 
index 9396ce036afdcf06fe1ce772fb0979fbee380908..bc58ea94cc93b782f1c7efc17e073902cf471e4e 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !plan9
 // +build !plan9
 
 package cgi
index 88e2028bc34904e85629ad8cfa3ac92083ca6529..4d380c65db983672ea22974c1be303c2f8065c41 100644 (file)
@@ -17,6 +17,7 @@ import (
        "fmt"
        "io"
        "log"
+       "net/http/internal/ascii"
        "net/url"
        "reflect"
        "sort"
@@ -432,8 +433,7 @@ func basicAuth(username, password string) string {
 // An error is returned if there were too many redirects or if there
 // was an HTTP protocol error. A non-2xx response doesn't cause an
 // error. Any returned error will be of type *url.Error. The url.Error
-// value's Timeout method will report true if request timed out or was
-// canceled.
+// value's Timeout method will report true if the request timed out.
 //
 // When err is nil, resp always contains a non-nil resp.Body.
 // Caller should close resp.Body when done reading from it.
@@ -442,6 +442,9 @@ func basicAuth(username, password string) string {
 //
 // To make a request with custom headers, use NewRequest and
 // DefaultClient.Do.
+//
+// To make a request with a specified context.Context, use NewRequestWithContext
+// and DefaultClient.Do.
 func Get(url string) (resp *Response, err error) {
        return DefaultClient.Get(url)
 }
@@ -466,6 +469,9 @@ func Get(url string) (resp *Response, err error) {
 // Caller should close resp.Body when done reading from it.
 //
 // To make a request with custom headers, use NewRequest and Client.Do.
+//
+// To make a request with a specified context.Context, use NewRequestWithContext
+// and Client.Do.
 func (c *Client) Get(url string) (resp *Response, err error) {
        req, err := NewRequest("GET", url, nil)
        if err != nil {
@@ -541,7 +547,10 @@ func urlErrorOp(method string) string {
        if method == "" {
                return "Get"
        }
-       return method[:1] + strings.ToLower(method[1:])
+       if lowerMethod, ok := ascii.ToLower(method); ok {
+               return method[:1] + lowerMethod[1:]
+       }
+       return method
 }
 
 // Do sends an HTTP request and returns an HTTP response, following
@@ -579,8 +588,7 @@ func urlErrorOp(method string) string {
 // standard library body types.
 //
 // Any returned error will be of type *url.Error. The url.Error
-// value's Timeout method will report true if request timed out or was
-// canceled.
+// value's Timeout method will report true if the request timed out.
 func (c *Client) Do(req *Request) (*Response, error) {
        return c.do(req)
 }
@@ -719,7 +727,6 @@ func (c *Client) do(req *Request) (retres *Response, reterr error) {
                        reqBodyClosed = true
                        if !deadline.IsZero() && didTimeout() {
                                err = &httpError{
-                                       // TODO: early in cycle: s/Client.Timeout exceeded/timeout or context cancellation/
                                        err:     err.Error() + " (Client.Timeout exceeded while awaiting headers)",
                                        timeout: true,
                                }
@@ -821,6 +828,9 @@ func defaultCheckRedirect(req *Request, via []*Request) error {
 //
 // See the Client.Do method documentation for details on how redirects
 // are handled.
+//
+// To make a request with a specified context.Context, use NewRequestWithContext
+// and DefaultClient.Do.
 func Post(url, contentType string, body io.Reader) (resp *Response, err error) {
        return DefaultClient.Post(url, contentType, body)
 }
@@ -834,6 +844,9 @@ func Post(url, contentType string, body io.Reader) (resp *Response, err error) {
 //
 // To set custom headers, use NewRequest and Client.Do.
 //
+// To make a request with a specified context.Context, use NewRequestWithContext
+// and Client.Do.
+//
 // See the Client.Do method documentation for details on how redirects
 // are handled.
 func (c *Client) Post(url, contentType string, body io.Reader) (resp *Response, err error) {
@@ -858,6 +871,9 @@ func (c *Client) Post(url, contentType string, body io.Reader) (resp *Response,
 //
 // See the Client.Do method documentation for details on how redirects
 // are handled.
+//
+// To make a request with a specified context.Context, use NewRequestWithContext
+// and DefaultClient.Do.
 func PostForm(url string, data url.Values) (resp *Response, err error) {
        return DefaultClient.PostForm(url, data)
 }
@@ -873,6 +889,9 @@ func PostForm(url string, data url.Values) (resp *Response, err error) {
 //
 // See the Client.Do method documentation for details on how redirects
 // are handled.
+//
+// To make a request with a specified context.Context, use NewRequestWithContext
+// and Client.Do.
 func (c *Client) PostForm(url string, data url.Values) (resp *Response, err error) {
        return c.Post(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
 }
@@ -888,6 +907,9 @@ func (c *Client) PostForm(url string, data url.Values) (resp *Response, err erro
 //    308 (Permanent Redirect)
 //
 // Head is a wrapper around DefaultClient.Head
+//
+// To make a request with a specified context.Context, use NewRequestWithContext
+// and DefaultClient.Do.
 func Head(url string) (resp *Response, err error) {
        return DefaultClient.Head(url)
 }
@@ -901,6 +923,9 @@ func Head(url string) (resp *Response, err error) {
 //    303 (See Other)
 //    307 (Temporary Redirect)
 //    308 (Permanent Redirect)
+//
+// To make a request with a specified context.Context, use NewRequestWithContext
+// and Client.Do.
 func (c *Client) Head(url string) (resp *Response, err error) {
        req, err := NewRequest("HEAD", url, nil)
        if err != nil {
@@ -926,7 +951,7 @@ func (c *Client) CloseIdleConnections() {
 }
 
 // cancelTimerBody is an io.ReadCloser that wraps rc with two features:
-// 1) on Read error or close, the stop func is called.
+// 1) On Read error or close, the stop func is called.
 // 2) On Read failure, if reqDidTimeout is true, the error is wrapped and
 //    marked as net.Error that hit its timeout.
 type cancelTimerBody struct {
index d90b4841c66cb661065bc67589c8b986e9d64bf0..01d605c35194f88e954c2b348458f5e7aae9c478 100644 (file)
@@ -257,12 +257,12 @@ func TestClientRedirects(t *testing.T) {
                t.Fatalf("Get error: %v", err)
        }
        res.Body.Close()
-       finalUrl := res.Request.URL.String()
+       finalURL := res.Request.URL.String()
        if e, g := "<nil>", fmt.Sprintf("%v", err); e != g {
                t.Errorf("with custom client, expected error %q, got %q", e, g)
        }
-       if !strings.HasSuffix(finalUrl, "/?n=15") {
-               t.Errorf("expected final url to end in /?n=15; got url %q", finalUrl)
+       if !strings.HasSuffix(finalURL, "/?n=15") {
+               t.Errorf("expected final url to end in /?n=15; got url %q", finalURL)
        }
        if e, g := 15, len(lastVia); e != g {
                t.Errorf("expected lastVia to have contained %d elements; got %d", e, g)
@@ -1945,7 +1945,7 @@ func TestClientDoCanceledVsTimeout_h2(t *testing.T) {
 }
 
 // Issue 33545: lock-in the behavior promised by Client.Do's
-// docs about request cancelation vs timing out.
+// docs about request cancellation vs timing out.
 func testClientDoCanceledVsTimeout(t *testing.T, h2 bool) {
        defer afterTest(t)
        cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
index 141bc947f6e960f327045895896d1321027b6075..ca2c1c2506694cc7c636c09af3b7cf9921352287 100644 (file)
@@ -7,6 +7,7 @@ package http
 import (
        "log"
        "net"
+       "net/http/internal/ascii"
        "net/textproto"
        "strconv"
        "strings"
@@ -93,15 +94,23 @@ func readSetCookies(h Header) []*Cookie {
                        if j := strings.Index(attr, "="); j >= 0 {
                                attr, val = attr[:j], attr[j+1:]
                        }
-                       lowerAttr := strings.ToLower(attr)
+                       lowerAttr, isASCII := ascii.ToLower(attr)
+                       if !isASCII {
+                               continue
+                       }
                        val, ok = parseCookieValue(val, false)
                        if !ok {
                                c.Unparsed = append(c.Unparsed, parts[i])
                                continue
                        }
+
                        switch lowerAttr {
                        case "samesite":
-                               lowerVal := strings.ToLower(val)
+                               lowerVal, ascii := ascii.ToLower(val)
+                               if !ascii {
+                                       c.SameSite = SameSiteDefaultMode
+                                       continue
+                               }
                                switch lowerVal {
                                case "lax":
                                        c.SameSite = SameSiteLaxMode
index 9f1991708472b9a0a2438c2a0334c23be352b20b..e6583da7fe67df21caf82a4f0030c07ed8869b76 100644 (file)
@@ -10,6 +10,7 @@ import (
        "fmt"
        "net"
        "net/http"
+       "net/http/internal/ascii"
        "net/url"
        "sort"
        "strings"
@@ -296,7 +297,6 @@ func (j *Jar) setCookies(u *url.URL, cookies []*http.Cookie, now time.Time) {
 // host name.
 func canonicalHost(host string) (string, error) {
        var err error
-       host = strings.ToLower(host)
        if hasPort(host) {
                host, _, err = net.SplitHostPort(host)
                if err != nil {
@@ -307,7 +307,13 @@ func canonicalHost(host string) (string, error) {
                // Strip trailing dot from fully qualified domain names.
                host = host[:len(host)-1]
        }
-       return toASCII(host)
+       encoded, err := toASCII(host)
+       if err != nil {
+               return "", err
+       }
+       // We know this is ascii, no need to check.
+       lower, _ := ascii.ToLower(encoded)
+       return lower, nil
 }
 
 // hasPort reports whether host contains a port number. host may be a host
@@ -469,7 +475,12 @@ func (j *Jar) domainAndType(host, domain string) (string, bool, error) {
                // both are illegal.
                return "", false, errMalformedDomain
        }
-       domain = strings.ToLower(domain)
+
+       domain, isASCII := ascii.ToLower(domain)
+       if !isASCII {
+               // Received non-ASCII domain, e.g. "perché.com" instead of "xn--perch-fsa.com"
+               return "", false, errMalformedDomain
+       }
 
        if domain[len(domain)-1] == '.' {
                // We received stuff like "Domain=www.example.com.".
index a9cc666e8c9637e9806b22581ece20aef131735f..c7f438dd00707a87014d801592be92c2e498a811 100644 (file)
@@ -8,6 +8,7 @@ package cookiejar
 
 import (
        "fmt"
+       "net/http/internal/ascii"
        "strings"
        "unicode/utf8"
 )
@@ -133,12 +134,12 @@ const acePrefix = "xn--"
 // toASCII("bücher.example.com") is "xn--bcher-kva.example.com", and
 // toASCII("golang") is "golang".
 func toASCII(s string) (string, error) {
-       if ascii(s) {
+       if ascii.Is(s) {
                return s, nil
        }
        labels := strings.Split(s, ".")
        for i, label := range labels {
-               if !ascii(label) {
+               if !ascii.Is(label) {
                        a, err := encode(acePrefix, label)
                        if err != nil {
                                return "", err
@@ -148,12 +149,3 @@ func toASCII(s string) (string, error) {
        }
        return strings.Join(labels, "."), nil
 }
-
-func ascii(s string) bool {
-       for i := 0; i < len(s); i++ {
-               if s[i] >= utf8.RuneSelf {
-                       return false
-               }
-       }
-       return true
-}
index c677d5223850260a70236d51e79c1241e55ac9ba..2f411d1d2ec23b3131567bc27bb9a614f08c92d0 100644 (file)
@@ -45,12 +45,15 @@ func ExampleGet() {
        if err != nil {
                log.Fatal(err)
        }
-       robots, err := io.ReadAll(res.Body)
+       body, err := io.ReadAll(res.Body)
        res.Body.Close()
+       if res.StatusCode > 299 {
+               log.Fatalf("Response failed with status code: %d and\nbody: %s\n", res.StatusCode, body)
+       }
        if err != nil {
                log.Fatal(err)
        }
-       fmt.Printf("%s", robots)
+       fmt.Printf("%s", body)
 }
 
 func ExampleFileServer() {
index 756722ba1412a2dcc4e55a2f6e1e6ea4772d3ef6..dc82bf7c3ab7a9c263659e736b35aa6c2cffb7d1 100644 (file)
@@ -16,7 +16,6 @@ import (
        "net/http/cgi"
        "os"
        "strings"
-       "sync"
        "time"
 )
 
@@ -154,7 +153,6 @@ type child struct {
        conn    *conn
        handler http.Handler
 
-       mu       sync.Mutex          // protects requests:
        requests map[uint16]*request // keyed by request ID
 }
 
@@ -193,9 +191,7 @@ var ErrRequestAborted = errors.New("fcgi: request aborted by web server")
 var ErrConnClosed = errors.New("fcgi: connection to web server closed")
 
 func (c *child) handleRecord(rec *record) error {
-       c.mu.Lock()
        req, ok := c.requests[rec.h.Id]
-       c.mu.Unlock()
        if !ok && rec.h.Type != typeBeginRequest && rec.h.Type != typeGetValues {
                // The spec says to ignore unknown request IDs.
                return nil
@@ -218,9 +214,7 @@ func (c *child) handleRecord(rec *record) error {
                        return nil
                }
                req = newRequest(rec.h.Id, br.flags)
-               c.mu.Lock()
                c.requests[rec.h.Id] = req
-               c.mu.Unlock()
                return nil
        case typeParams:
                // NOTE(eds): Technically a key-value pair can straddle the boundary
@@ -248,8 +242,11 @@ func (c *child) handleRecord(rec *record) error {
                        // TODO(eds): This blocks until the handler reads from the pipe.
                        // If the handler takes a long time, it might be a problem.
                        req.pw.Write(content)
-               } else if req.pw != nil {
-                       req.pw.Close()
+               } else {
+                       delete(c.requests, req.reqId)
+                       if req.pw != nil {
+                               req.pw.Close()
+                       }
                }
                return nil
        case typeGetValues:
@@ -260,9 +257,7 @@ func (c *child) handleRecord(rec *record) error {
                // If the filter role is implemented, read the data stream here.
                return nil
        case typeAbortRequest:
-               c.mu.Lock()
                delete(c.requests, rec.h.Id)
-               c.mu.Unlock()
                c.conn.writeEndRequest(rec.h.Id, 0, statusRequestComplete)
                if req.pw != nil {
                        req.pw.CloseWithError(ErrRequestAborted)
@@ -309,9 +304,6 @@ func (c *child) serveRequest(req *request, body io.ReadCloser) {
        // Make sure we serve something even if nothing was written to r
        r.Write(nil)
        r.Close()
-       c.mu.Lock()
-       delete(c.requests, req.reqId)
-       c.mu.Unlock()
        c.conn.writeEndRequest(req.reqId, 0, statusRequestComplete)
 
        // Consume the entire body, so the host isn't still writing to
@@ -330,8 +322,6 @@ func (c *child) serveRequest(req *request, body io.ReadCloser) {
 }
 
 func (c *child) cleanUp() {
-       c.mu.Lock()
-       defer c.mu.Unlock()
        for _, req := range c.requests {
                if req.pw != nil {
                        // race with call to Close in c.serveRequest doesn't matter because
index b58111de208dee2e05f8f46096bddba1f1a7ec74..5888783620874c7598a2faa208bc780dabad3192 100644 (file)
@@ -11,6 +11,7 @@ import (
        "net/http"
        "strings"
        "testing"
+       "time"
 )
 
 var sizeTests = []struct {
@@ -399,3 +400,55 @@ func TestResponseWriterSniffsContentType(t *testing.T) {
                })
        }
 }
+
+type signallingNopCloser struct {
+       io.Reader
+       closed chan bool
+}
+
+func (*signallingNopCloser) Write(buf []byte) (int, error) {
+       return len(buf), nil
+}
+
+func (rc *signallingNopCloser) Close() error {
+       close(rc.closed)
+       return nil
+}
+
+// Test whether server properly closes connection when processing slow
+// requests
+func TestSlowRequest(t *testing.T) {
+       pr, pw := io.Pipe()
+       go func(w io.Writer) {
+               for _, buf := range [][]byte{
+                       streamBeginTypeStdin,
+                       makeRecord(typeStdin, 1, nil),
+               } {
+                       pw.Write(buf)
+                       time.Sleep(100 * time.Millisecond)
+               }
+       }(pw)
+
+       rc := &signallingNopCloser{pr, make(chan bool)}
+       handlerDone := make(chan bool)
+
+       c := newChild(rc, http.HandlerFunc(func(
+               w http.ResponseWriter,
+               r *http.Request,
+       ) {
+               w.WriteHeader(200)
+               close(handlerDone)
+       }))
+       go c.serve()
+       defer c.cleanUp()
+
+       timeout := time.After(2 * time.Second)
+
+       <-handlerDone
+       select {
+       case <-rc.closed:
+               t.Log("FastCGI child closed connection")
+       case <-timeout:
+               t.Error("FastCGI child did not close socket after handling request")
+       }
+}
index b58888dcb146f074418930efd4bed5b38c5ee7b3..77fc8eeccf67601f7f4621ef0507d60a5a47cd44 100644 (file)
@@ -23,12 +23,10 @@ func checker(t *testing.T) func(string, error) {
 func TestFileTransport(t *testing.T) {
        check := checker(t)
 
-       dname, err := os.MkdirTemp("", "")
-       check("TempDir", err)
+       dname := t.TempDir()
        fname := filepath.Join(dname, "foo.txt")
-       err = os.WriteFile(fname, []byte("Bar"), 0644)
+       err := os.WriteFile(fname, []byte("Bar"), 0644)
        check("WriteFile", err)
-       defer os.Remove(dname)
        defer os.Remove(fname)
 
        tr := &Transport{}
index a28ae85958fe6bff917ddfbf93fe56575601d20f..57e731e481ad49830b67a907dee59f554130579b 100644 (file)
@@ -46,7 +46,7 @@ type Dir string
 // to a possibly better non-nil error. In particular, it turns OS-specific errors
 // about opening files in non-directories into fs.ErrNotExist. See Issue 18984.
 func mapDirOpenError(originalErr error, name string) error {
-       if os.IsNotExist(originalErr) || os.IsPermission(originalErr) {
+       if errors.Is(originalErr, fs.ErrNotExist) || errors.Is(originalErr, fs.ErrPermission) {
                return originalErr
        }
 
@@ -670,10 +670,10 @@ func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirec
 // and historically Go's ServeContent always returned just "404 Not Found" for
 // all errors. We don't want to start leaking information in error messages.
 func toHTTPError(err error) (msg string, httpStatus int) {
-       if os.IsNotExist(err) {
+       if errors.Is(err, fs.ErrNotExist) {
                return "404 page not found", StatusNotFound
        }
-       if os.IsPermission(err) {
+       if errors.Is(err, fs.ErrPermission) {
                return "403 Forbidden", StatusForbidden
        }
        // Default:
index 2499051625081bec746ab270c08396305dc63354..b42ade1e8ac4f4482b37fbee242205f6384e857e 100644 (file)
@@ -11,7 +11,6 @@ import (
        "fmt"
        "io"
        "io/fs"
-       "io/ioutil"
        "mime"
        "mime/multipart"
        "net"
@@ -379,11 +378,7 @@ func mustRemoveAll(dir string) {
 
 func TestFileServerImplicitLeadingSlash(t *testing.T) {
        defer afterTest(t)
-       tempDir, err := os.MkdirTemp("", "")
-       if err != nil {
-               t.Fatalf("TempDir: %v", err)
-       }
-       defer mustRemoveAll(tempDir)
+       tempDir := t.TempDir()
        if err := os.WriteFile(filepath.Join(tempDir, "foo.txt"), []byte("Hello world"), 0644); err != nil {
                t.Fatalf("WriteFile: %v", err)
        }
@@ -593,7 +588,7 @@ func TestServeIndexHtml(t *testing.T) {
                                if err != nil {
                                        t.Fatal(err)
                                }
-                               b, err := ioutil.ReadAll(res.Body)
+                               b, err := io.ReadAll(res.Body)
                                if err != nil {
                                        t.Fatal("reading Body:", err)
                                }
@@ -1270,16 +1265,18 @@ func TestFileServerNotDirError(t *testing.T) {
                        if err == nil {
                                t.Fatal("err == nil; want != nil")
                        }
-                       if !os.IsNotExist(err) {
-                               t.Errorf("err = %v; os.IsNotExist(err) = %v; want true", err, os.IsNotExist(err))
+                       if !errors.Is(err, fs.ErrNotExist) {
+                               t.Errorf("err = %v; errors.Is(err, fs.ErrNotExist) = %v; want true", err,
+                                       errors.Is(err, fs.ErrNotExist))
                        }
 
                        _, err = dir.Open("/index.html/not-a-dir/not-a-file")
                        if err == nil {
                                t.Fatal("err == nil; want != nil")
                        }
-                       if !os.IsNotExist(err) {
-                               t.Errorf("err = %v; os.IsNotExist(err) = %v; want true", err, os.IsNotExist(err))
+                       if !errors.Is(err, fs.ErrNotExist) {
+                               t.Errorf("err = %v; errors.Is(err, fs.ErrNotExist) = %v; want true", err,
+                                       errors.Is(err, fs.ErrNotExist))
                        }
                })
        }
index e13c6619db718fb7a592139c4000601e344aed4f..0e5fbf8f26b426637949e9e1828f72730769c1ec 100644 (file)
@@ -1,3 +1,4 @@
+//go:build !nethttpomithttp2
 // +build !nethttpomithttp2
 
 // Code generated by golang.org/x/tools/cmd/bundle. DO NOT EDIT.
@@ -52,6 +53,48 @@ import (
        "golang.org/x/net/idna"
 )
 
+// asciiEqualFold is strings.EqualFold, ASCII only. It reports whether s and t
+// are equal, ASCII-case-insensitively.
+func http2asciiEqualFold(s, t string) bool {
+       if len(s) != len(t) {
+               return false
+       }
+       for i := 0; i < len(s); i++ {
+               if http2lower(s[i]) != http2lower(t[i]) {
+                       return false
+               }
+       }
+       return true
+}
+
+// lower returns the ASCII lowercase version of b.
+func http2lower(b byte) byte {
+       if 'A' <= b && b <= 'Z' {
+               return b + ('a' - 'A')
+       }
+       return b
+}
+
+// isASCIIPrint returns whether s is ASCII and printable according to
+// https://tools.ietf.org/html/rfc20#section-4.2.
+func http2isASCIIPrint(s string) bool {
+       for i := 0; i < len(s); i++ {
+               if s[i] < ' ' || s[i] > '~' {
+                       return false
+               }
+       }
+       return true
+}
+
+// asciiToLower returns the lowercase version of s if s is ASCII and printable,
+// and whether or not it was.
+func http2asciiToLower(s string) (lower string, ok bool) {
+       if !http2isASCIIPrint(s) {
+               return "", false
+       }
+       return strings.ToLower(s), true
+}
+
 // A list of the possible cipher suite ids. Taken from
 // https://www.iana.org/assignments/tls-parameters/tls-parameters.txt
 
@@ -754,61 +797,69 @@ func (p *http2clientConnPool) getClientConn(req *Request, addr string, dialOnMis
                // It gets its own connection.
                http2traceGetConn(req, addr)
                const singleUse = true
-               cc, err := p.t.dialClientConn(addr, singleUse)
+               cc, err := p.t.dialClientConn(req.Context(), addr, singleUse)
                if err != nil {
                        return nil, err
                }
                return cc, nil
        }
-       p.mu.Lock()
-       for _, cc := range p.conns[addr] {
-               if st := cc.idleState(); st.canTakeNewRequest {
-                       if p.shouldTraceGetConn(st) {
-                               http2traceGetConn(req, addr)
+       for {
+               p.mu.Lock()
+               for _, cc := range p.conns[addr] {
+                       if st := cc.idleState(); st.canTakeNewRequest {
+                               if p.shouldTraceGetConn(st) {
+                                       http2traceGetConn(req, addr)
+                               }
+                               p.mu.Unlock()
+                               return cc, nil
                        }
+               }
+               if !dialOnMiss {
                        p.mu.Unlock()
-                       return cc, nil
+                       return nil, http2ErrNoCachedConn
                }
-       }
-       if !dialOnMiss {
+               http2traceGetConn(req, addr)
+               call := p.getStartDialLocked(req.Context(), addr)
                p.mu.Unlock()
-               return nil, http2ErrNoCachedConn
+               <-call.done
+               if http2shouldRetryDial(call, req) {
+                       continue
+               }
+               return call.res, call.err
        }
-       http2traceGetConn(req, addr)
-       call := p.getStartDialLocked(addr)
-       p.mu.Unlock()
-       <-call.done
-       return call.res, call.err
 }
 
 // dialCall is an in-flight Transport dial call to a host.
 type http2dialCall struct {
-       _    http2incomparable
-       p    *http2clientConnPool
+       _ http2incomparable
+       p *http2clientConnPool
+       // the context associated with the request
+       // that created this dialCall
+       ctx  context.Context
        done chan struct{}    // closed when done
        res  *http2ClientConn // valid after done is closed
        err  error            // valid after done is closed
 }
 
 // requires p.mu is held.
-func (p *http2clientConnPool) getStartDialLocked(addr string) *http2dialCall {
+func (p *http2clientConnPool) getStartDialLocked(ctx context.Context, addr string) *http2dialCall {
        if call, ok := p.dialing[addr]; ok {
                // A dial is already in-flight. Don't start another.
                return call
        }
-       call := &http2dialCall{p: p, done: make(chan struct{})}
+       call := &http2dialCall{p: p, done: make(chan struct{}), ctx: ctx}
        if p.dialing == nil {
                p.dialing = make(map[string]*http2dialCall)
        }
        p.dialing[addr] = call
-       go call.dial(addr)
+       go call.dial(call.ctx, addr)
        return call
 }
 
 // run in its own goroutine.
-func (c *http2dialCall) dial(addr string) {
+func (c *http2dialCall) dial(ctx context.Context, addr string) {
        const singleUse = false // shared conn
-       c.res, c.err = c.p.t.dialClientConn(addr, singleUse)
+       c.res, c.err = c.p.t.dialClientConn(ctx, addr, singleUse)
        close(c.done)
 
        c.p.mu.Lock()
@@ -953,6 +1004,31 @@ func (p http2noDialClientConnPool) GetClientConn(req *Request, addr string) (*ht
        return p.getClientConn(req, addr, http2noDialOnMiss)
 }
 
+// shouldRetryDial reports whether the current request should
+// retry dialing after the call finished unsuccessfully, for example
+// if the dial was canceled because of a context cancellation or
+// deadline expiry.
+func http2shouldRetryDial(call *http2dialCall, req *Request) bool {
+       if call.err == nil {
+               // No error, no need to retry
+               return false
+       }
+       if call.ctx == req.Context() {
+               // If the call has the same context as the request, the dial
+               // should not be retried, since any cancellation will have come
+               // from this request.
+               return false
+       }
+       if !errors.Is(call.err, context.Canceled) && !errors.Is(call.err, context.DeadlineExceeded) {
+               // If the call error is not because of a context cancellation or a deadline expiry,
+               // the dial should not be retried.
+               return false
+       }
+       // Only retry if the error is a context cancellation error or deadline expiry
+       // and the context associated with the call was canceled or expired.
+       return call.ctx.Err() != nil
+}
+
 // Buffer chunks are allocated from a pool to reduce pressure on GC.
 // The maximum wasted space per dataBuffer is 2x the largest size class,
 // which happens when the dataBuffer has multiple chunks and there is
@@ -2873,6 +2949,20 @@ func http2traceGot1xxResponseFunc(trace *httptrace.ClientTrace) func(int, textpr
        return nil
 }
 
+// dialTLSWithContext uses tls.Dialer, added in Go 1.15, to open a TLS
+// connection.
+func (t *http2Transport) dialTLSWithContext(ctx context.Context, network, addr string, cfg *tls.Config) (*tls.Conn, error) {
+       dialer := &tls.Dialer{
+               Config: cfg,
+       }
+       cn, err := dialer.DialContext(ctx, network, addr)
+       if err != nil {
+               return nil, err
+       }
+       tlsCn := cn.(*tls.Conn) // DialContext comment promises this will always succeed
+       return tlsCn, nil
+}
+
 var http2DebugGoroutines = os.Getenv("DEBUG_HTTP2_GOROUTINES") == "1"
 
 type http2goroutineLock uint64
@@ -3094,12 +3184,12 @@ func http2buildCommonHeaderMaps() {
        }
 }
 
-func http2lowerHeader(v string) string {
+func http2lowerHeader(v string) (lower string, ascii bool) {
        http2buildCommonHeaderMapsOnce()
        if s, ok := http2commonLowerHeader[v]; ok {
-               return s
+               return s, true
        }
-       return strings.ToLower(v)
+       return http2asciiToLower(v)
 }
 
 var (
@@ -3797,13 +3887,12 @@ func http2ConfigureServer(s *Server, conf *http2Server) error {
 
        if s.TLSConfig == nil {
                s.TLSConfig = new(tls.Config)
-       } else if s.TLSConfig.CipherSuites != nil {
-               // If they already provided a CipherSuite list, return
-               // an error if it has a bad order or is missing
-               // ECDHE_RSA_WITH_AES_128_GCM_SHA256 or ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
+       } else if s.TLSConfig.CipherSuites != nil && s.TLSConfig.MinVersion < tls.VersionTLS13 {
+               // If they already provided a TLS 1.0–1.2 CipherSuite list, return an
+               // error if it is missing ECDHE_RSA_WITH_AES_128_GCM_SHA256 or
+               // ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
                haveRequired := false
-               sawBad := false
-               for i, cs := range s.TLSConfig.CipherSuites {
+               for _, cs := range s.TLSConfig.CipherSuites {
                        switch cs {
                        case tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
                                // Alternative MTI cipher to not discourage ECDSA-only servers.
@@ -3811,14 +3900,9 @@ func http2ConfigureServer(s *Server, conf *http2Server) error {
                                tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
                                haveRequired = true
                        }
-                       if http2isBadCipher(cs) {
-                               sawBad = true
-                       } else if sawBad {
-                               return fmt.Errorf("http2: TLSConfig.CipherSuites index %d contains an HTTP/2-approved cipher suite (%#04x), but it comes after unapproved cipher suites. With this configuration, clients that don't support previous, approved cipher suites may be given an unapproved one and reject the connection.", i, cs)
-                       }
                }
                if !haveRequired {
-                       return fmt.Errorf("http2: TLSConfig.CipherSuites is missing an HTTP/2-required AES_128_GCM_SHA256 cipher (need at least one of TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 or TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256).")
+                       return fmt.Errorf("http2: TLSConfig.CipherSuites is missing an HTTP/2-required AES_128_GCM_SHA256 cipher (need at least one of TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 or TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)")
                }
        }
 
@@ -4864,7 +4948,9 @@ func (sc *http2serverConn) startGracefulShutdown() {
        sc.shutdownOnce.Do(func() { sc.sendServeMsg(http2gracefulShutdownMsg) })
 }
 
-// After sending GOAWAY, the connection will close after goAwayTimeout.
+// After sending GOAWAY with an error code (non-graceful shutdown), the
+// connection will close after goAwayTimeout.
+//
 // If we close the connection immediately after sending GOAWAY, there may
 // be unsent data in our kernel receive buffer, which will cause the kernel
 // to send a TCP RST on close() instead of a FIN. This RST will abort the
@@ -5200,23 +5286,37 @@ func (sc *http2serverConn) processSettingInitialWindowSize(val uint32) error {
 
 func (sc *http2serverConn) processData(f *http2DataFrame) error {
        sc.serveG.check()
-       if sc.inGoAway && sc.goAwayCode != http2ErrCodeNo {
+       id := f.Header().StreamID
+       if sc.inGoAway && (sc.goAwayCode != http2ErrCodeNo || id > sc.maxClientStreamID) {
+               // Discard all DATA frames if the GOAWAY is due to an
+               // error, or:
+               //
+               // Section 6.8: After sending a GOAWAY frame, the sender
+               // can discard frames for streams initiated by the
+               // receiver with identifiers higher than the identified
+               // last stream.
                return nil
        }
-       data := f.Data()
 
-       // "If a DATA frame is received whose stream is not in "open"
-       // or "half closed (local)" state, the recipient MUST respond
-       // with a stream error (Section 5.4.2) of type STREAM_CLOSED."
-       id := f.Header().StreamID
+       data := f.Data()
        state, st := sc.state(id)
        if id == 0 || state == http2stateIdle {
+               // Section 6.1: "DATA frames MUST be associated with a
+               // stream. If a DATA frame is received whose stream
+               // identifier field is 0x0, the recipient MUST respond
+               // with a connection error (Section 5.4.1) of type
+               // PROTOCOL_ERROR."
+               //
                // Section 5.1: "Receiving any frame other than HEADERS
                // or PRIORITY on a stream in this state MUST be
                // treated as a connection error (Section 5.4.1) of
                // type PROTOCOL_ERROR."
                return http2ConnectionError(http2ErrCodeProtocol)
        }
+
+       // "If a DATA frame is received whose stream is not in "open"
+       // or "half closed (local)" state, the recipient MUST respond
+       // with a stream error (Section 5.4.2) of type STREAM_CLOSED."
        if st == nil || state != http2stateOpen || st.gotTrailerHeader || st.resetQueued {
                // This includes sending a RST_STREAM if the stream is
                // in stateHalfClosedLocal (which currently means that
@@ -6344,8 +6444,12 @@ func (w *http2responseWriter) Push(target string, opts *PushOptions) error {
                // but PUSH_PROMISE requests cannot have a body.
                // http://tools.ietf.org/html/rfc7540#section-8.2
                // Also disallow Host, since the promised URL must be absolute.
-               switch strings.ToLower(k) {
-               case "content-length", "content-encoding", "trailer", "te", "expect", "host":
+               if http2asciiEqualFold(k, "content-length") ||
+                       http2asciiEqualFold(k, "content-encoding") ||
+                       http2asciiEqualFold(k, "trailer") ||
+                       http2asciiEqualFold(k, "te") ||
+                       http2asciiEqualFold(k, "expect") ||
+                       http2asciiEqualFold(k, "host") {
                        return fmt.Errorf("promised request headers cannot include %q", k)
                }
        }
@@ -7067,12 +7171,12 @@ func http2canRetryError(err error) bool {
        return false
 }
 
-func (t *http2Transport) dialClientConn(addr string, singleUse bool) (*http2ClientConn, error) {
+func (t *http2Transport) dialClientConn(ctx context.Context, addr string, singleUse bool) (*http2ClientConn, error) {
        host, _, err := net.SplitHostPort(addr)
        if err != nil {
                return nil, err
        }
-       tconn, err := t.dialTLS()("tcp", addr, t.newTLSConfig(host))
+       tconn, err := t.dialTLS(ctx)("tcp", addr, t.newTLSConfig(host))
        if err != nil {
                return nil, err
        }
@@ -7093,34 +7197,24 @@ func (t *http2Transport) newTLSConfig(host string) *tls.Config {
        return cfg
 }
 
-func (t *http2Transport) dialTLS() func(string, string, *tls.Config) (net.Conn, error) {
+func (t *http2Transport) dialTLS(ctx context.Context) func(string, string, *tls.Config) (net.Conn, error) {
        if t.DialTLS != nil {
                return t.DialTLS
        }
-       return t.dialTLSDefault
-}
-
-func (t *http2Transport) dialTLSDefault(network, addr string, cfg *tls.Config) (net.Conn, error) {
-       cn, err := tls.Dial(network, addr, cfg)
-       if err != nil {
-               return nil, err
-       }
-       if err := cn.Handshake(); err != nil {
-               return nil, err
-       }
-       if !cfg.InsecureSkipVerify {
-               if err := cn.VerifyHostname(cfg.ServerName); err != nil {
+       return func(network, addr string, cfg *tls.Config) (net.Conn, error) {
+               tlsCn, err := t.dialTLSWithContext(ctx, network, addr, cfg)
+               if err != nil {
                        return nil, err
                }
+               state := tlsCn.ConnectionState()
+               if p := state.NegotiatedProtocol; p != http2NextProtoTLS {
+                       return nil, fmt.Errorf("http2: unexpected ALPN protocol %q; want %q", p, http2NextProtoTLS)
+               }
+               if !state.NegotiatedProtocolIsMutual {
+                       return nil, errors.New("http2: could not negotiate protocol mutually")
+               }
+               return tlsCn, nil
        }
-       state := cn.ConnectionState()
-       if p := state.NegotiatedProtocol; p != http2NextProtoTLS {
-               return nil, fmt.Errorf("http2: unexpected ALPN protocol %q; want %q", p, http2NextProtoTLS)
-       }
-       if !state.NegotiatedProtocolIsMutual {
-               return nil, errors.New("http2: could not negotiate protocol mutually")
-       }
-       return cn, nil
 }
 
 // disableKeepAlives reports whether connections should be closed as
@@ -7508,7 +7602,7 @@ func http2checkConnHeaders(req *Request) error {
        if vv := req.Header["Transfer-Encoding"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && vv[0] != "chunked") {
                return fmt.Errorf("http2: invalid Transfer-Encoding request header: %q", vv)
        }
-       if vv := req.Header["Connection"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && !strings.EqualFold(vv[0], "close") && !strings.EqualFold(vv[0], "keep-alive")) {
+       if vv := req.Header["Connection"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && !http2asciiEqualFold(vv[0], "close") && !http2asciiEqualFold(vv[0], "keep-alive")) {
                return fmt.Errorf("http2: invalid Connection request header: %q", vv)
        }
        return nil
@@ -8049,19 +8143,21 @@ func (cc *http2ClientConn) encodeHeaders(req *Request, addGzipHeader bool, trail
 
                var didUA bool
                for k, vv := range req.Header {
-                       if strings.EqualFold(k, "host") || strings.EqualFold(k, "content-length") {
+                       if http2asciiEqualFold(k, "host") || http2asciiEqualFold(k, "content-length") {
                                // Host is :authority, already sent.
                                // Content-Length is automatic, set below.
                                continue
-                       } else if strings.EqualFold(k, "connection") || strings.EqualFold(k, "proxy-connection") ||
-                               strings.EqualFold(k, "transfer-encoding") || strings.EqualFold(k, "upgrade") ||
-                               strings.EqualFold(k, "keep-alive") {
+                       } else if http2asciiEqualFold(k, "connection") ||
+                               http2asciiEqualFold(k, "proxy-connection") ||
+                               http2asciiEqualFold(k, "transfer-encoding") ||
+                               http2asciiEqualFold(k, "upgrade") ||
+                               http2asciiEqualFold(k, "keep-alive") {
                                // Per 8.1.2.2 Connection-Specific Header
                                // Fields, don't send connection-specific
                                // fields. We have already checked if any
                                // are error-worthy so just ignore the rest.
                                continue
-                       } else if strings.EqualFold(k, "user-agent") {
+                       } else if http2asciiEqualFold(k, "user-agent") {
                                // Match Go's http1 behavior: at most one
                                // User-Agent. If set to nil or empty string,
                                // then omit it. Otherwise if not mentioned,
@@ -8074,7 +8170,7 @@ func (cc *http2ClientConn) encodeHeaders(req *Request, addGzipHeader bool, trail
                                if vv[0] == "" {
                                        continue
                                }
-                       } else if strings.EqualFold(k, "cookie") {
+                       } else if http2asciiEqualFold(k, "cookie") {
                                // Per 8.1.2.5 To allow for better compression efficiency, the
                                // Cookie header field MAY be split into separate header fields,
                                // each with one or more cookie-pairs.
@@ -8133,7 +8229,12 @@ func (cc *http2ClientConn) encodeHeaders(req *Request, addGzipHeader bool, trail
 
        // Header list size is ok. Write the headers.
        enumerateHeaders(func(name, value string) {
-               name = strings.ToLower(name)
+               name, ascii := http2asciiToLower(name)
+               if !ascii {
+                       // Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header
+                       // field names have to be ASCII characters (just as in HTTP/1.x).
+                       return
+               }
                cc.writeHeader(name, value)
                if traceHeaders {
                        http2traceWroteHeaderField(trace, name, value)
@@ -8181,9 +8282,14 @@ func (cc *http2ClientConn) encodeTrailers(req *Request) ([]byte, error) {
        }
 
        for k, vv := range req.Trailer {
+               lowKey, ascii := http2asciiToLower(k)
+               if !ascii {
+                       // Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header
+                       // field names have to be ASCII characters (just as in HTTP/1.x).
+                       continue
+               }
                // Transfer-Encoding, etc.. have already been filtered at the
                // start of RoundTrip
-               lowKey := strings.ToLower(k)
                for _, v := range vv {
                        cc.writeHeader(lowKey, v)
                }
@@ -9606,7 +9712,12 @@ func http2encodeHeaders(enc *hpack.Encoder, h Header, keys []string) {
        }
        for _, k := range keys {
                vv := h[k]
-               k = http2lowerHeader(k)
+               k, ascii := http2lowerHeader(k)
+               if !ascii {
+                       // Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header
+                       // field names have to be ASCII characters (just as in HTTP/1.x).
+                       continue
+               }
                if !http2validWireHeaderFieldName(k) {
                        // Skip it as backup paranoia. Per
                        // golang.org/issue/14048, these should
index b9b53911f384410425323e30efe391f9bfa02c78..4c72dcb2c88d254f3e8b81a483bb6b40079f4b37 100644 (file)
@@ -7,6 +7,7 @@ package http
 import (
        "io"
        "net/http/httptrace"
+       "net/http/internal/ascii"
        "net/textproto"
        "sort"
        "strings"
@@ -251,7 +252,7 @@ func hasToken(v, token string) bool {
                if endPos := sp + len(token); endPos != len(v) && !isTokenBoundary(v[endPos]) {
                        continue
                }
-               if strings.EqualFold(v[sp:sp+len(token)], token) {
+               if ascii.EqualFold(v[sp:sp+len(token)], token) {
                        return true
                }
        }
index 4c5054b399410dd22b02bb1661203e0bb3160d38..101799f574f4655610c2ec49d013b66c76b7a434 100644 (file)
@@ -62,15 +62,6 @@ func isNotToken(r rune) bool {
        return !httpguts.IsTokenRune(r)
 }
 
-func isASCII(s string) bool {
-       for i := 0; i < len(s); i++ {
-               if s[i] >= utf8.RuneSelf {
-                       return false
-               }
-       }
-       return true
-}
-
 // stringContainsCTLByte reports whether s contains any ASCII control character.
 func stringContainsCTLByte(s string) bool {
        for i := 0; i < len(s); i++ {
index 3f1d7cee710ed2601ee616fb2d2a2f7e53826cbe..0d92fe5f964fb704dc4fa3ef1c1c2aae6d1ecd12 100644 (file)
@@ -9,9 +9,13 @@ package http
 import (
        "bytes"
        "internal/testenv"
+       "io/fs"
        "net/url"
+       "os"
        "os/exec"
        "reflect"
+       "regexp"
+       "strings"
        "testing"
 )
 
@@ -156,3 +160,61 @@ func BenchmarkCopyValues(b *testing.B) {
                b.Fatal("Benchmark wasn't run")
        }
 }
+
+var forbiddenStringsFunctions = map[string]bool{
+       // Functions that use Unicode-aware case folding.
+       "EqualFold":      true,
+       "Title":          true,
+       "ToLower":        true,
+       "ToLowerSpecial": true,
+       "ToTitle":        true,
+       "ToTitleSpecial": true,
+       "ToUpper":        true,
+       "ToUpperSpecial": true,
+
+       // Functions that use Unicode-aware spaces.
+       "Fields":    true,
+       "TrimSpace": true,
+}
+
+// TestNoUnicodeStrings checks that nothing in net/http uses the Unicode-aware
+// strings and bytes package functions. HTTP is mostly ASCII based, and doing
+// Unicode-aware case folding or space stripping can introduce vulnerabilities.
+func TestNoUnicodeStrings(t *testing.T) {
+       if !testenv.HasSrc() {
+               t.Skip("source code not available")
+       }
+
+       re := regexp.MustCompile(`(strings|bytes).([A-Za-z]+)`)
+       if err := fs.WalkDir(os.DirFS("."), ".", func(path string, d fs.DirEntry, err error) error {
+               if err != nil {
+                       t.Fatal(err)
+               }
+
+               if path == "internal/ascii" {
+                       return fs.SkipDir
+               }
+               if !strings.HasSuffix(path, ".go") ||
+                       strings.HasSuffix(path, "_test.go") ||
+                       path == "h2_bundle.go" || d.IsDir() {
+                       return nil
+               }
+
+               contents, err := os.ReadFile(path)
+               if err != nil {
+                       t.Fatal(err)
+               }
+               for lineNum, line := range strings.Split(string(contents), "\n") {
+                       for _, match := range re.FindAllStringSubmatch(line, -1) {
+                               if !forbiddenStringsFunctions[match[2]] {
+                                       continue
+                               }
+                               t.Errorf("disallowed call to %s at %s:%d", match[0], path, lineNum+1)
+                       }
+               }
+
+               return nil
+       }); err != nil {
+               t.Fatal(err)
+       }
+}
index 24284826122eb7a422a117e9c5c19be9cd65003f..1b712ef2b0a8e8a471ca69f3af76b8d56b18fe5a 100644 (file)
@@ -122,11 +122,30 @@ func (rw *ResponseRecorder) WriteString(str string) (int, error) {
        return len(str), nil
 }
 
+func checkWriteHeaderCode(code int) {
+       // Issue 22880: require valid WriteHeader status codes.
+       // For now we only enforce that it's three digits.
+       // In the future we might block things over 599 (600 and above aren't defined
+       // at https://httpwg.org/specs/rfc7231.html#status.codes)
+       // and we might block under 200 (once we have more mature 1xx support).
+       // But for now any three digits.
+       //
+       // We used to send "HTTP/1.1 000 0" on the wire in responses but there's
+       // no equivalent bogus thing we can realistically send in HTTP/2,
+       // so we'll consistently panic instead and help people find their bugs
+       // early. (We can't return an error from WriteHeader even if we wanted to.)
+       if code < 100 || code > 999 {
+               panic(fmt.Sprintf("invalid WriteHeader code %v", code))
+       }
+}
+
 // WriteHeader implements http.ResponseWriter.
 func (rw *ResponseRecorder) WriteHeader(code int) {
        if rw.wroteHeader {
                return
        }
+
+       checkWriteHeaderCode(code)
        rw.Code = code
        rw.wroteHeader = true
        if rw.HeaderMap == nil {
index a865e878b9b3bf327f804945dccb415241dbba97..8cb32dd7403683375f292ab9285d8bb1d7f33696 100644 (file)
@@ -345,3 +345,28 @@ func TestParseContentLength(t *testing.T) {
                }
        }
 }
+
+// Ensure that httptest.Recorder panics when given a non-3 digit (XXX)
+// status HTTP code. See https://golang.org/issues/45353
+func TestRecorderPanicsOnNonXXXStatusCode(t *testing.T) {
+       badCodes := []int{
+               -100, 0, 99, 1000, 20000,
+       }
+       for _, badCode := range badCodes {
+               badCode := badCode
+               t.Run(fmt.Sprintf("Code=%d", badCode), func(t *testing.T) {
+                       defer func() {
+                               if r := recover(); r == nil {
+                                       t.Fatal("Expected a panic")
+                               }
+                       }()
+
+                       handler := func(rw http.ResponseWriter, _ *http.Request) {
+                               rw.WriteHeader(badCode)
+                       }
+                       r, _ := http.NewRequest("GET", "http://example.org/", nil)
+                       rw := NewRecorder()
+                       handler(rw, r)
+               })
+       }
+}
index 8ebf681f4b89b46d1f9bf02f95e4f86476ae4d4f..a9faa9aa140e6356ece32e08aa9090b45f09f75d 100644 (file)
@@ -14,7 +14,7 @@ import (
        "log"
        "net"
        "net/http"
-       "net/http/internal"
+       "net/http/internal/testcert"
        "os"
        "strings"
        "sync"
@@ -144,7 +144,7 @@ func (s *Server) StartTLS() {
        if s.client == nil {
                s.client = &http.Client{Transport: &http.Transport{}}
        }
-       cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey)
+       cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey)
        if err != nil {
                panic(fmt.Sprintf("httptest: NewTLSServer: %v", err))
        }
@@ -316,6 +316,13 @@ func (s *Server) wrap() {
        s.Config.ConnState = func(c net.Conn, cs http.ConnState) {
                s.mu.Lock()
                defer s.mu.Unlock()
+
+               // Keep Close from returning until the user's ConnState hook
+               // (if any) finishes. Without this, the call to forgetConn
+               // below might send the count to 0 before we run the hook.
+               s.wg.Add(1)
+               defer s.wg.Done()
+
                switch cs {
                case http.StateNew:
                        s.wg.Add(1)
index 6a5cbac9d89ce5cb64b25fa6ce9d78ef8a421099..5777c91747c200c9e232c50a3c9796e114952c6c 100644 (file)
@@ -127,7 +127,7 @@ type ClientTrace struct {
 
        // ConnectDone is called when a new connection's Dial
        // completes. The provided err indicates whether the
-       // connection completedly successfully.
+       // connection completed successfully.
        // If net.Dialer.DualStack ("Happy Eyeballs") support is
        // enabled, this may be called multiple times.
        ConnectDone func(network, addr string, err error)
index 8168b2ebc05d0d633a43226f37e5e7d03b51fb4e..366cc8239ac7550b8137044d8a534d8d556258ff 100644 (file)
@@ -478,7 +478,7 @@ func TestDumpResponse(t *testing.T) {
        }
 }
 
-// Issue 38352: Check for deadlock on cancelled requests.
+// Issue 38352: Check for deadlock on canceled requests.
 func TestDumpRequestOutIssue38352(t *testing.T) {
        if testing.Short() {
                return
index ccb84562e0a70d2720f6d426dff31dc87a5b4e50..8b63368386f43ba81a574e571ada7bcfffd195e0 100644 (file)
@@ -13,6 +13,7 @@ import (
        "log"
        "net"
        "net/http"
+       "net/http/internal/ascii"
        "net/textproto"
        "net/url"
        "strings"
@@ -234,6 +235,15 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
        if req.ContentLength == 0 {
                outreq.Body = nil // Issue 16036: nil Body for http.Transport retries
        }
+       if outreq.Body != nil {
+               // Reading from the request body after returning from a handler is not
+               // allowed, and the RoundTrip goroutine that reads the Body can outlive
+               // this handler. This can lead to a crash if the handler panics (see
+               // Issue 46866). Although calling Close doesn't guarantee there isn't
+               // any Read in flight after the handle returns, in practice it's safe to
+               // read after closing it.
+               defer outreq.Body.Close()
+       }
        if outreq.Header == nil {
                outreq.Header = make(http.Header) // Issue 33142: historical behavior was to always allocate
        }
@@ -242,6 +252,10 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
        outreq.Close = false
 
        reqUpType := upgradeType(outreq.Header)
+       if !ascii.IsPrint(reqUpType) {
+               p.getErrorHandler()(rw, req, fmt.Errorf("client tried to switch to invalid protocol %q", reqUpType))
+               return
+       }
        removeConnectionHeaders(outreq.Header)
 
        // Remove hop-by-hop headers to the backend. Especially
@@ -534,13 +548,16 @@ func upgradeType(h http.Header) string {
        if !httpguts.HeaderValuesContainsToken(h["Connection"], "Upgrade") {
                return ""
        }
-       return strings.ToLower(h.Get("Upgrade"))
+       return h.Get("Upgrade")
 }
 
 func (p *ReverseProxy) handleUpgradeResponse(rw http.ResponseWriter, req *http.Request, res *http.Response) {
        reqUpType := upgradeType(req.Header)
        resUpType := upgradeType(res.Header)
-       if reqUpType != resUpType {
+       if !ascii.IsPrint(resUpType) { // We know reqUpType is ASCII, it's checked by the caller.
+               p.getErrorHandler()(rw, req, fmt.Errorf("backend tried to switch to invalid protocol %q", resUpType))
+       }
+       if !ascii.EqualFold(reqUpType, resUpType) {
                p.getErrorHandler()(rw, req, fmt.Errorf("backend tried to switch protocol %q when %q was requested", resUpType, reqUpType))
                return
        }
@@ -558,7 +575,7 @@ func (p *ReverseProxy) handleUpgradeResponse(rw http.ResponseWriter, req *http.R
 
        backConnCloseCh := make(chan bool)
        go func() {
-               // Ensure that the cancelation of a request closes the backend.
+               // Ensure that the cancellation of a request closes the backend.
                // See issue https://golang.org/issue/35559.
                select {
                case <-req.Context().Done():
index 3211463bcbcd2860eb1fa9178f9a2a4f5cfa6273..4b6ad77a29466fe0fbb9f1e79fa1bd804b2264ea 100644 (file)
@@ -16,6 +16,7 @@ import (
        "log"
        "net/http"
        "net/http/httptest"
+       "net/http/internal/ascii"
        "net/url"
        "os"
        "reflect"
@@ -1121,6 +1122,45 @@ func TestReverseProxy_PanicBodyError(t *testing.T) {
        rproxy.ServeHTTP(httptest.NewRecorder(), req)
 }
 
+// Issue #46866: panic without closing incoming request body causes a panic
+func TestReverseProxy_PanicClosesIncomingBody(t *testing.T) {
+       backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+               out := "this call was relayed by the reverse proxy"
+               // Coerce a wrong content length to induce io.ErrUnexpectedEOF
+               w.Header().Set("Content-Length", fmt.Sprintf("%d", len(out)*2))
+               fmt.Fprintln(w, out)
+       }))
+       defer backend.Close()
+       backendURL, err := url.Parse(backend.URL)
+       if err != nil {
+               t.Fatal(err)
+       }
+       proxyHandler := NewSingleHostReverseProxy(backendURL)
+       proxyHandler.ErrorLog = log.New(io.Discard, "", 0) // quiet for tests
+       frontend := httptest.NewServer(proxyHandler)
+       defer frontend.Close()
+       frontendClient := frontend.Client()
+
+       var wg sync.WaitGroup
+       for i := 0; i < 2; i++ {
+               wg.Add(1)
+               go func() {
+                       defer wg.Done()
+                       for j := 0; j < 10; j++ {
+                               const reqLen = 6 * 1024 * 1024
+                               req, _ := http.NewRequest("POST", frontend.URL, &io.LimitedReader{R: neverEnding('x'), N: reqLen})
+                               req.ContentLength = reqLen
+                               resp, _ := frontendClient.Transport.RoundTrip(req)
+                               if resp != nil {
+                                       io.Copy(io.Discard, resp.Body)
+                                       resp.Body.Close()
+                               }
+                       }
+               }()
+       }
+       wg.Wait()
+}
+
 func TestSelectFlushInterval(t *testing.T) {
        tests := []struct {
                name string
@@ -1242,7 +1282,7 @@ func TestReverseProxyWebSocket(t *testing.T) {
                t.Errorf("Header(XHeader) = %q; want %q", got, want)
        }
 
-       if upgradeType(res.Header) != "websocket" {
+       if !ascii.EqualFold(upgradeType(res.Header), "websocket") {
                t.Fatalf("not websocket upgrade; got %#v", res.Header)
        }
        rwc, ok := res.Body.(io.ReadWriteCloser)
@@ -1267,7 +1307,7 @@ func TestReverseProxyWebSocket(t *testing.T) {
        }
 }
 
-func TestReverseProxyWebSocketCancelation(t *testing.T) {
+func TestReverseProxyWebSocketCancellation(t *testing.T) {
        n := 5
        triggerCancelCh := make(chan bool, n)
        nthResponse := func(i int) string {
@@ -1359,7 +1399,7 @@ func TestReverseProxyWebSocketCancelation(t *testing.T) {
                t.Errorf("X-Header mismatch\n\tgot:  %q\n\twant: %q", g, w)
        }
 
-       if g, w := upgradeType(res.Header), "websocket"; g != w {
+       if g, w := upgradeType(res.Header), "websocket"; !ascii.EqualFold(g, w) {
                t.Fatalf("Upgrade header mismatch\n\tgot:  %q\n\twant: %q", g, w)
        }
 
diff --git a/libgo/go/net/http/internal/ascii/print.go b/libgo/go/net/http/internal/ascii/print.go
new file mode 100644 (file)
index 0000000..585e5ba
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ascii
+
+import (
+       "strings"
+       "unicode"
+)
+
+// EqualFold is strings.EqualFold, ASCII only. It reports whether s and t
+// are equal, ASCII-case-insensitively.
+func EqualFold(s, t string) bool {
+       if len(s) != len(t) {
+               return false
+       }
+       for i := 0; i < len(s); i++ {
+               if lower(s[i]) != lower(t[i]) {
+                       return false
+               }
+       }
+       return true
+}
+
+// lower returns the ASCII lowercase version of b.
+func lower(b byte) byte {
+       if 'A' <= b && b <= 'Z' {
+               return b + ('a' - 'A')
+       }
+       return b
+}
+
+// IsPrint returns whether s is ASCII and printable according to
+// https://tools.ietf.org/html/rfc20#section-4.2.
+func IsPrint(s string) bool {
+       for i := 0; i < len(s); i++ {
+               if s[i] < ' ' || s[i] > '~' {
+                       return false
+               }
+       }
+       return true
+}
+
+// Is returns whether s is ASCII.
+func Is(s string) bool {
+       for i := 0; i < len(s); i++ {
+               if s[i] > unicode.MaxASCII {
+                       return false
+               }
+       }
+       return true
+}
+
+// ToLower returns the lowercase version of s if s is ASCII and printable.
+func ToLower(s string) (lower string, ok bool) {
+       if !IsPrint(s) {
+               return "", false
+       }
+       return strings.ToLower(s), true
+}
diff --git a/libgo/go/net/http/internal/ascii/print_test.go b/libgo/go/net/http/internal/ascii/print_test.go
new file mode 100644 (file)
index 0000000..0b7767c
--- /dev/null
@@ -0,0 +1,95 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ascii
+
+import "testing"
+
+func TestEqualFold(t *testing.T) {
+       var tests = []struct {
+               name string
+               a, b string
+               want bool
+       }{
+               {
+                       name: "empty",
+                       want: true,
+               },
+               {
+                       name: "simple match",
+                       a:    "CHUNKED",
+                       b:    "chunked",
+                       want: true,
+               },
+               {
+                       name: "same string",
+                       a:    "chunked",
+                       b:    "chunked",
+                       want: true,
+               },
+               {
+                       name: "Unicode Kelvin symbol",
+                       a:    "chunKed", // This "K" is 'KELVIN SIGN' (\u212A)
+                       b:    "chunked",
+                       want: false,
+               },
+       }
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       if got := EqualFold(tt.a, tt.b); got != tt.want {
+                               t.Errorf("AsciiEqualFold(%q,%q): got %v want %v", tt.a, tt.b, got, tt.want)
+                       }
+               })
+       }
+}
+
+func TestIsPrint(t *testing.T) {
+       var tests = []struct {
+               name string
+               in   string
+               want bool
+       }{
+               {
+                       name: "empty",
+                       want: true,
+               },
+               {
+                       name: "ASCII low",
+                       in:   "This is a space: ' '",
+                       want: true,
+               },
+               {
+                       name: "ASCII high",
+                       in:   "This is a tilde: '~'",
+                       want: true,
+               },
+               {
+                       name: "ASCII low non-print",
+                       in:   "This is a unit separator: \x1F",
+                       want: false,
+               },
+               {
+                       name: "Ascii high non-print",
+                       in:   "This is a Delete: \x7F",
+                       want: false,
+               },
+               {
+                       name: "Unicode letter",
+                       in:   "Today it's 280K outside: it's freezing!", // This "K" is 'KELVIN SIGN' (\u212A)
+                       want: false,
+               },
+               {
+                       name: "Unicode emoji",
+                       in:   "Gophers like 🧀",
+                       want: false,
+               },
+       }
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       if got := IsPrint(tt.in); got != tt.want {
+                               t.Errorf("IsASCIIPrint(%q): got %v want %v", tt.in, got, tt.want)
+                       }
+               })
+       }
+}
similarity index 94%
rename from libgo/go/net/http/internal/testcert.go
rename to libgo/go/net/http/internal/testcert/testcert.go
index 2284a836fb7015d2a41f43cc555c2259e82a93ba..5f94704ef590d6ca5ef9433e67d5d66990a2042a 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package internal
+// Package testcert contains a test-only localhost certificate.
+package testcert
 
 import "strings"
 
@@ -25,7 +26,7 @@ h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM
 fblo6RBxUQ==
 -----END CERTIFICATE-----`)
 
-// LocalhostKey is the private key for localhostCert.
+// LocalhostKey is the private key for LocalhostCert.
 var LocalhostKey = []byte(testingKey(`-----BEGIN RSA TESTING KEY-----
 MIICXgIBAAKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9
 SjY1bIw4iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZB
index 30c6e48cfcb12bb09016ce4a789ea07efa71b0ff..79599d006aaf94dc1537c6024d200de2b6d0c961 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build nethttpomithttp2
 // +build nethttpomithttp2
 
 package http
index 5389a388c17de3dd2c7dc9b4263c6c49942ec87b..888ea35c9a6c5229c50c946926f17a256c8da59c 100644 (file)
@@ -287,7 +287,7 @@ func (name handler) serveDeltaProfile(w http.ResponseWriter, r *http.Request, p
                err := r.Context().Err()
                if err == context.DeadlineExceeded {
                        serveError(w, http.StatusRequestTimeout, err.Error())
-               } else { // TODO: what's a good status code for cancelled requests? 400?
+               } else { // TODO: what's a good status code for canceled requests? 400?
                        serveError(w, http.StatusInternalServerError, err.Error())
                }
                return
@@ -431,7 +431,7 @@ Types of profiles available:
 
        b.WriteString(`</table>
 <a href="goroutine?debug=2">full goroutine stack dump</a>
-<br/>
+<br>
 <p>
 Profile Descriptions:
 <ul>
index adba5406e900683ab447cf9b8120ac11313f8313..09cb0c7f564f745f1b50c9f861f441603055e764 100644 (file)
@@ -19,6 +19,7 @@ import (
        "mime/multipart"
        "net"
        "net/http/httptrace"
+       "net/http/internal/ascii"
        "net/textproto"
        "net/url"
        urlpkg "net/url"
@@ -723,7 +724,7 @@ func idnaASCII(v string) (string, error) {
        // version does not.
        // Note that for correct ASCII IDNs ToASCII will only do considerably more
        // work, but it will not cause an allocation.
-       if isASCII(v) {
+       if ascii.Is(v) {
                return v, nil
        }
        return idna.Lookup.ToASCII(v)
@@ -779,7 +780,8 @@ func removeZone(host string) string {
 }
 
 // ParseHTTPVersion parses an HTTP version string.
-// "HTTP/1.0" returns (1, 0, true).
+// "HTTP/1.0" returns (1, 0, true). Note that strings without
+// a minor version, such as "HTTP/2", are not valid.
 func ParseHTTPVersion(vers string) (major, minor int, ok bool) {
        const Big = 1000000 // arbitrary upper bound
        switch vers {
@@ -823,7 +825,7 @@ func validMethod(method string) bool {
        return len(method) > 0 && strings.IndexFunc(method, isNotToken) == -1
 }
 
-// NewRequest wraps NewRequestWithContext using the background context.
+// NewRequest wraps NewRequestWithContext using context.Background.
 func NewRequest(method, url string, body io.Reader) (*Request, error) {
        return NewRequestWithContext(context.Background(), method, url, body)
 }
@@ -947,7 +949,7 @@ func (r *Request) BasicAuth() (username, password string, ok bool) {
 func parseBasicAuth(auth string) (username, password string, ok bool) {
        const prefix = "Basic "
        // Case insensitive prefix match. See Issue 22736.
-       if len(auth) < len(prefix) || !strings.EqualFold(auth[:len(prefix)], prefix) {
+       if len(auth) < len(prefix) || !ascii.EqualFold(auth[:len(prefix)], prefix) {
                return
        }
        c, err := base64.StdEncoding.DecodeString(auth[len(prefix):])
@@ -1009,16 +1011,16 @@ func putTextprotoReader(r *textproto.Reader) {
 // requests and handle them via the Handler interface. ReadRequest
 // only supports HTTP/1.x requests. For HTTP/2, use golang.org/x/net/http2.
 func ReadRequest(b *bufio.Reader) (*Request, error) {
-       return readRequest(b, deleteHostHeader)
-}
+       req, err := readRequest(b)
+       if err != nil {
+               return nil, err
+       }
 
-// Constants for readRequest's deleteHostHeader parameter.
-const (
-       deleteHostHeader = true
-       keepHostHeader   = false
-)
+       delete(req.Header, "Host")
+       return req, err
+}
 
-func readRequest(b *bufio.Reader, deleteHostHeader bool) (req *Request, err error) {
+func readRequest(b *bufio.Reader) (req *Request, err error) {
        tp := newTextprotoReader(b)
        req = new(Request)
 
@@ -1076,6 +1078,9 @@ func readRequest(b *bufio.Reader, deleteHostHeader bool) (req *Request, err erro
                return nil, err
        }
        req.Header = Header(mimeHeader)
+       if len(req.Header["Host"]) > 1 {
+               return nil, fmt.Errorf("too many Host headers")
+       }
 
        // RFC 7230, section 5.3: Must treat
        //      GET /index.html HTTP/1.1
@@ -1088,9 +1093,6 @@ func readRequest(b *bufio.Reader, deleteHostHeader bool) (req *Request, err erro
        if req.Host == "" {
                req.Host = req.Header.get("Host")
        }
-       if deleteHostHeader {
-               delete(req.Header, "Host")
-       }
 
        fixPragmaCacheControl(req.Header)
 
@@ -1123,6 +1125,9 @@ func readRequest(b *bufio.Reader, deleteHostHeader bool) (req *Request, err erro
 // MaxBytesReader prevents clients from accidentally or maliciously
 // sending a large request and wasting server resources.
 func MaxBytesReader(w ResponseWriter, r io.ReadCloser, n int64) io.ReadCloser {
+       if n < 0 { // Treat negative limits as equivalent to 0.
+               n = 0
+       }
        return &maxBytesReader{w: w, r: r, n: n}
 }
 
@@ -1288,16 +1293,18 @@ func (r *Request) ParseForm() error {
 // its file parts are stored in memory, with the remainder stored on
 // disk in temporary files.
 // ParseMultipartForm calls ParseForm if necessary.
+// If ParseForm returns an error, ParseMultipartForm returns it but also
+// continues parsing the request body.
 // After one call to ParseMultipartForm, subsequent calls have no effect.
 func (r *Request) ParseMultipartForm(maxMemory int64) error {
        if r.MultipartForm == multipartByReader {
                return errors.New("http: multipart handled by MultipartReader")
        }
+       var parseFormErr error
        if r.Form == nil {
-               err := r.ParseForm()
-               if err != nil {
-                       return err
-               }
+               // Let errors in ParseForm fall through, and just
+               // return it at the end.
+               parseFormErr = r.ParseForm()
        }
        if r.MultipartForm != nil {
                return nil
@@ -1324,7 +1331,7 @@ func (r *Request) ParseMultipartForm(maxMemory int64) error {
 
        r.MultipartForm = f
 
-       return nil
+       return parseFormErr
 }
 
 // FormValue returns the first value for the named component of the query.
@@ -1452,5 +1459,5 @@ func requestMethodUsuallyLacksBody(method string) bool {
 // an HTTP/1 connection.
 func (r *Request) requiresHTTP1() bool {
        return hasToken(r.Header.Get("Connection"), "upgrade") &&
-               strings.EqualFold(r.Header.Get("Upgrade"), "websocket")
+               ascii.EqualFold(r.Header.Get("Upgrade"), "websocket")
 }
index 29297b0e7bd8c785d85f34401844c1b3a43d75c0..4e0c4ba207f8be66a7f529de7aa7ac7fb052021a 100644 (file)
@@ -32,9 +32,26 @@ func TestQuery(t *testing.T) {
        }
 }
 
+// Issue #25192: Test that ParseForm fails but still parses the form when an URL
+// containing a semicolon is provided.
+func TestParseFormSemicolonSeparator(t *testing.T) {
+       for _, method := range []string{"POST", "PATCH", "PUT", "GET"} {
+               req, _ := NewRequest(method, "http://www.google.com/search?q=foo;q=bar&a=1",
+                       strings.NewReader("q"))
+               err := req.ParseForm()
+               if err == nil {
+                       t.Fatalf(`for method %s, ParseForm expected an error, got success`, method)
+               }
+               wantForm := url.Values{"a": []string{"1"}}
+               if !reflect.DeepEqual(req.Form, wantForm) {
+                       t.Fatalf("for method %s, ParseForm expected req.Form = %v, want %v", method, req.Form, wantForm)
+               }
+       }
+}
+
 func TestParseFormQuery(t *testing.T) {
        req, _ := NewRequest("POST", "http://www.google.com/search?q=foo&q=bar&both=x&prio=1&orphan=nope&empty=not",
-               strings.NewReader("z=post&both=y&prio=2&=nokey&orphan;empty=&"))
+               strings.NewReader("z=post&both=y&prio=2&=nokey&orphan&empty=&"))
        req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
 
        if q := req.FormValue("q"); q != "foo" {
@@ -245,6 +262,29 @@ func TestParseMultipartForm(t *testing.T) {
        }
 }
 
+// Issue 45789: multipart form should not include directory path in filename
+func TestParseMultipartFormFilename(t *testing.T) {
+       postData :=
+               `--xxx
+Content-Disposition: form-data; name="file"; filename="../usr/foobar.txt/"
+Content-Type: text/plain
+
+--xxx--
+`
+       req := &Request{
+               Method: "POST",
+               Header: Header{"Content-Type": {`multipart/form-data; boundary=xxx`}},
+               Body:   io.NopCloser(strings.NewReader(postData)),
+       }
+       _, hdr, err := req.FormFile("file")
+       if err != nil {
+               t.Fatal(err)
+       }
+       if hdr.Filename != "foobar.txt" {
+               t.Errorf("expected only the last element of the path, got %q", hdr.Filename)
+       }
+}
+
 // Issue #40430: Test that if maxMemory for ParseMultipartForm when combined with
 // the payload size and the internal leeway buffer size of 10MiB overflows, that we
 // correctly return an error.
@@ -342,6 +382,18 @@ func TestMultipartRequest(t *testing.T) {
        validateTestMultipartContents(t, req, false)
 }
 
+// Issue #25192: Test that ParseMultipartForm fails but still parses the
+// multi-part form when an URL containing a semicolon is provided.
+func TestParseMultipartFormSemicolonSeparator(t *testing.T) {
+       req := newTestMultipartRequest(t)
+       req.URL = &url.URL{RawQuery: "q=foo;q=bar"}
+       if err := req.ParseMultipartForm(25); err == nil {
+               t.Fatal("ParseMultipartForm expected error due to invalid semicolon, got nil")
+       }
+       defer req.MultipartForm.RemoveAll()
+       validateTestMultipartContents(t, req, false)
+}
+
 func TestMultipartRequestAuto(t *testing.T) {
        // Test that FormValue and FormFile automatically invoke
        // ParseMultipartForm and return the right values.
@@ -469,6 +521,10 @@ var readRequestErrorTests = []struct {
                in:     "HEAD / HTTP/1.1\r\nContent-Length:0\r\nContent-Length: 0\r\n\r\n",
                header: Header{"Content-Length": {"0"}},
        },
+       11: {
+               in:  "HEAD / HTTP/1.1\r\nHost: foo\r\nHost: bar\r\n\r\n\r\n\r\n",
+               err: "too many Host headers",
+       },
 }
 
 func TestReadRequestErrors(t *testing.T) {
@@ -850,6 +906,92 @@ func TestMaxBytesReaderStickyError(t *testing.T) {
        }
 }
 
+// Issue 45101: maxBytesReader's Read panicked when n < -1. This test
+// also ensures that Read treats negative limits as equivalent to 0.
+func TestMaxBytesReaderDifferentLimits(t *testing.T) {
+       const testStr = "1234"
+       tests := [...]struct {
+               limit   int64
+               lenP    int
+               wantN   int
+               wantErr bool
+       }{
+               0: {
+                       limit:   -123,
+                       lenP:    0,
+                       wantN:   0,
+                       wantErr: false, // Ensure we won't return an error when the limit is negative, but we don't need to read.
+               },
+               1: {
+                       limit:   -100,
+                       lenP:    32 * 1024,
+                       wantN:   0,
+                       wantErr: true,
+               },
+               2: {
+                       limit:   -2,
+                       lenP:    1,
+                       wantN:   0,
+                       wantErr: true,
+               },
+               3: {
+                       limit:   -1,
+                       lenP:    2,
+                       wantN:   0,
+                       wantErr: true,
+               },
+               4: {
+                       limit:   0,
+                       lenP:    3,
+                       wantN:   0,
+                       wantErr: true,
+               },
+               5: {
+                       limit:   1,
+                       lenP:    4,
+                       wantN:   1,
+                       wantErr: true,
+               },
+               6: {
+                       limit:   2,
+                       lenP:    5,
+                       wantN:   2,
+                       wantErr: true,
+               },
+               7: {
+                       limit:   3,
+                       lenP:    2,
+                       wantN:   2,
+                       wantErr: false,
+               },
+               8: {
+                       limit:   int64(len(testStr)),
+                       lenP:    len(testStr),
+                       wantN:   len(testStr),
+                       wantErr: false,
+               },
+               9: {
+                       limit:   100,
+                       lenP:    6,
+                       wantN:   len(testStr),
+                       wantErr: false,
+               },
+       }
+       for i, tt := range tests {
+               rc := MaxBytesReader(nil, io.NopCloser(strings.NewReader(testStr)), tt.limit)
+
+               n, err := rc.Read(make([]byte, tt.lenP))
+
+               if n != tt.wantN {
+                       t.Errorf("%d. n: %d, want n: %d", i, n, tt.wantN)
+               }
+
+               if (err != nil) != tt.wantErr {
+                       t.Errorf("%d. error: %v", i, err)
+               }
+       }
+}
+
 func TestWithContextDeepCopiesURL(t *testing.T) {
        req, err := NewRequest("POST", "https://golang.org/", nil)
        if err != nil {
index 2ec736bfb1975377d38e88c0a0c9ae4041f2ec10..eef7c79293e643e08677e24ba9d5c1e2fb769ffc 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js || !wasm
 // +build !js !wasm
 
 package http
index c6a221ac628be63665fc6d9d5a9303ba60082759..74c83a9172cab2524156d097394fb1fe5f1ef202 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build js && wasm
 // +build js,wasm
 
 package http
index f8687416fe96c019a80e7e2ae58740f2dd7508db..6394da3bb7cf60d0263e723bb611967f64d43820 100644 (file)
@@ -25,6 +25,7 @@ import (
        "net/http/httptest"
        "net/http/httputil"
        "net/http/internal"
+       "net/http/internal/testcert"
        "net/url"
        "os"
        "os/exec"
@@ -1475,7 +1476,7 @@ func TestServeTLS(t *testing.T) {
        defer afterTest(t)
        defer SetTestHookServerServe(nil)
 
-       cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey)
+       cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey)
        if err != nil {
                t.Fatal(err)
        }
@@ -1599,7 +1600,7 @@ func TestAutomaticHTTP2_Serve_WithTLSConfig(t *testing.T) {
 }
 
 func TestAutomaticHTTP2_ListenAndServe(t *testing.T) {
-       cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey)
+       cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey)
        if err != nil {
                t.Fatal(err)
        }
@@ -1609,7 +1610,7 @@ func TestAutomaticHTTP2_ListenAndServe(t *testing.T) {
 }
 
 func TestAutomaticHTTP2_ListenAndServe_GetCertificate(t *testing.T) {
-       cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey)
+       cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey)
        if err != nil {
                t.Fatal(err)
        }
@@ -6507,3 +6508,104 @@ func TestDisableKeepAliveUpgrade(t *testing.T) {
                t.Fatalf("unexpected value read from body:\ngot: %q\nwant: %q", b, "hello")
        }
 }
+
+func TestMuxRedirectRelative(t *testing.T) {
+       setParallel(t)
+       req, err := ReadRequest(bufio.NewReader(strings.NewReader("GET http://example.com HTTP/1.1\r\nHost: test\r\n\r\n")))
+       if err != nil {
+               t.Errorf("%s", err)
+       }
+       mux := NewServeMux()
+       resp := httptest.NewRecorder()
+       mux.ServeHTTP(resp, req)
+       if got, want := resp.Header().Get("Location"), "/"; got != want {
+               t.Errorf("Location header expected %q; got %q", want, got)
+       }
+       if got, want := resp.Code, StatusMovedPermanently; got != want {
+               t.Errorf("Expected response code %d; got %d", want, got)
+       }
+}
+
+// TestQuerySemicolon tests the behavior of semicolons in queries. See Issue 25192.
+func TestQuerySemicolon(t *testing.T) {
+       t.Cleanup(func() { afterTest(t) })
+
+       tests := []struct {
+               query           string
+               xNoSemicolons   string
+               xWithSemicolons string
+               warning         bool
+       }{
+               {"?a=1;x=bad&x=good", "good", "bad", true},
+               {"?a=1;b=bad&x=good", "good", "good", true},
+               {"?a=1%3Bx=bad&x=good%3B", "good;", "good;", false},
+               {"?a=1;x=good;x=bad", "", "good", true},
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.query+"/allow=false", func(t *testing.T) {
+                       allowSemicolons := false
+                       testQuerySemicolon(t, tt.query, tt.xNoSemicolons, allowSemicolons, tt.warning)
+               })
+               t.Run(tt.query+"/allow=true", func(t *testing.T) {
+                       allowSemicolons, expectWarning := true, false
+                       testQuerySemicolon(t, tt.query, tt.xWithSemicolons, allowSemicolons, expectWarning)
+               })
+       }
+}
+
+func testQuerySemicolon(t *testing.T, query string, wantX string, allowSemicolons, expectWarning bool) {
+       setParallel(t)
+
+       writeBackX := func(w ResponseWriter, r *Request) {
+               x := r.URL.Query().Get("x")
+               if expectWarning {
+                       if err := r.ParseForm(); err == nil || !strings.Contains(err.Error(), "semicolon") {
+                               t.Errorf("expected error mentioning semicolons from ParseForm, got %v", err)
+                       }
+               } else {
+                       if err := r.ParseForm(); err != nil {
+                               t.Errorf("expected no error from ParseForm, got %v", err)
+                       }
+               }
+               if got := r.FormValue("x"); x != got {
+                       t.Errorf("got %q from FormValue, want %q", got, x)
+               }
+               fmt.Fprintf(w, "%s", x)
+       }
+
+       h := Handler(HandlerFunc(writeBackX))
+       if allowSemicolons {
+               h = AllowQuerySemicolons(h)
+       }
+
+       ts := httptest.NewUnstartedServer(h)
+       logBuf := &bytes.Buffer{}
+       ts.Config.ErrorLog = log.New(logBuf, "", 0)
+       ts.Start()
+       defer ts.Close()
+
+       req, _ := NewRequest("GET", ts.URL+query, nil)
+       res, err := ts.Client().Do(req)
+       if err != nil {
+               t.Fatal(err)
+       }
+       slurp, _ := io.ReadAll(res.Body)
+       res.Body.Close()
+       if got, want := res.StatusCode, 200; got != want {
+               t.Errorf("Status = %d; want = %d", got, want)
+       }
+       if got, want := string(slurp), wantX; got != want {
+               t.Errorf("Body = %q; want = %q", got, want)
+       }
+
+       if expectWarning {
+               if !strings.Contains(logBuf.String(), "semicolon") {
+                       t.Errorf("got %q from ErrorLog, expected a mention of semicolons", logBuf.String())
+               }
+       } else {
+               if strings.Contains(logBuf.String(), "semicolon") {
+                       t.Errorf("got %q from ErrorLog, expected no mention of semicolons", logBuf.String())
+               }
+       }
+}
index 33aadd6c2a9ce0a47136e32b6193d2b4e557c3de..ce3993341d33d53830ba160af986364423f2b421 100644 (file)
@@ -333,7 +333,7 @@ func (c *conn) hijackLocked() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
 const bufferBeforeChunkingSize = 2048
 
 // chunkWriter writes to a response's conn buffer, and is the writer
-// wrapped by the response.bufw buffered writer.
+// wrapped by the response.w buffered writer.
 //
 // chunkWriter also is responsible for finalizing the Header, including
 // conditionally setting the Content-Type and setting a Content-Length
@@ -577,37 +577,17 @@ func (w *response) ReadFrom(src io.Reader) (n int64, err error) {
                return io.CopyBuffer(writerOnly{w}, src, buf)
        }
 
-       // sendfile path:
-
-       // Do not start actually writing response until src is readable.
-       // If body length is <= sniffLen, sendfile/splice path will do
-       // little anyway. This small read also satisfies sniffing the
-       // body in case Content-Type is missing.
-       nr, er := src.Read(buf[:sniffLen])
-       atEOF := errors.Is(er, io.EOF)
-       n += int64(nr)
-
-       if nr > 0 {
-               // Write the small amount read normally.
-               nw, ew := w.Write(buf[:nr])
-               if ew != nil {
-                       err = ew
-               } else if nr != nw {
-                       err = io.ErrShortWrite
+       // Copy the first sniffLen bytes before switching to ReadFrom.
+       // This ensures we don't start writing the response before the
+       // source is available (see golang.org/issue/5660) and provides
+       // enough bytes to perform Content-Type sniffing when required.
+       if !w.cw.wroteHeader {
+               n0, err := io.CopyBuffer(writerOnly{w}, io.LimitReader(src, sniffLen), buf)
+               n += n0
+               if err != nil || n0 < sniffLen {
+                       return n, err
                }
        }
-       if err == nil && er != nil && !atEOF {
-               err = er
-       }
-
-       // Do not send StatusOK in the error case where nothing has been written.
-       if err == nil && !w.wroteHeader {
-               w.WriteHeader(StatusOK) // nr == 0, no error (or EOF)
-       }
-
-       if err != nil || atEOF {
-               return n, err
-       }
 
        w.w.Flush()  // get rid of any previous writes
        w.cw.flush() // make sure Header is written; flush data to rwc
@@ -620,7 +600,7 @@ func (w *response) ReadFrom(src io.Reader) (n int64, err error) {
                return n, err
        }
 
-       n0, err := io.Copy(writerOnly{w}, src)
+       n0, err := io.CopyBuffer(writerOnly{w}, src, buf)
        n += n0
        return n, err
 }
@@ -964,14 +944,14 @@ func (c *conn) readRequest(ctx context.Context) (w *response, err error) {
                hdrDeadline      time.Time // or zero if none
        )
        t0 := time.Now()
-       if d := c.server.readHeaderTimeout(); d != 0 {
+       if d := c.server.readHeaderTimeout(); d > 0 {
                hdrDeadline = t0.Add(d)
        }
-       if d := c.server.ReadTimeout; d != 0 {
+       if d := c.server.ReadTimeout; d > 0 {
                wholeReqDeadline = t0.Add(d)
        }
        c.rwc.SetReadDeadline(hdrDeadline)
-       if d := c.server.WriteTimeout; d != 0 {
+       if d := c.server.WriteTimeout; d > 0 {
                defer func() {
                        c.rwc.SetWriteDeadline(time.Now().Add(d))
                }()
@@ -983,7 +963,7 @@ func (c *conn) readRequest(ctx context.Context) (w *response, err error) {
                peek, _ := c.bufr.Peek(4) // ReadRequest will get err below
                c.bufr.Discard(numLeadingCRorLF(peek))
        }
-       req, err := readRequest(c.bufr, keepHostHeader)
+       req, err := readRequest(c.bufr)
        if err != nil {
                if c.r.hitReadLimit() {
                        return nil, errTooLarge
@@ -1003,9 +983,6 @@ func (c *conn) readRequest(ctx context.Context) (w *response, err error) {
        if req.ProtoAtLeast(1, 1) && (!haveHost || len(hosts) == 0) && !isH2Upgrade && req.Method != "CONNECT" {
                return nil, badRequestError("missing required Host header")
        }
-       if len(hosts) > 1 {
-               return nil, badRequestError("too many Host headers")
-       }
        if len(hosts) == 1 && !httpguts.ValidHostHeader(hosts[0]) {
                return nil, badRequestError("malformed Host header")
        }
@@ -1557,12 +1534,12 @@ func (w *response) bodyAllowed() bool {
 // The Writers are wired together like:
 //
 // 1. *response (the ResponseWriter) ->
-// 2. (*response).w, a *bufio.Writer of bufferBeforeChunkingSize bytes
+// 2. (*response).w, a *bufio.Writer of bufferBeforeChunkingSize bytes ->
 // 3. chunkWriter.Writer (whose writeHeader finalizes Content-Length/Type)
-//    and which writes the chunk headers, if needed.
-// 4. conn.buf, a bufio.Writer of default (4kB) bytes, writing to ->
+//    and which writes the chunk headers, if needed ->
+// 4. conn.bufw, a *bufio.Writer of default (4kB) bytes, writing to ->
 // 5. checkConnErrorWriter{c}, which notes any non-nil error on Write
-//    and populates c.werr with it if so. but otherwise writes to:
+//    and populates c.werr with it if so, but otherwise writes to ->
 // 6. the rwc, the net.Conn.
 //
 // TODO(bradfitz): short-circuit some of the buffering when the
@@ -1836,13 +1813,13 @@ func (c *conn) serve(ctx context.Context) {
        }()
 
        if tlsConn, ok := c.rwc.(*tls.Conn); ok {
-               if d := c.server.ReadTimeout; d != 0 {
+               if d := c.server.ReadTimeout; d > 0 {
                        c.rwc.SetReadDeadline(time.Now().Add(d))
                }
-               if d := c.server.WriteTimeout; d != 0 {
+               if d := c.server.WriteTimeout; d > 0 {
                        c.rwc.SetWriteDeadline(time.Now().Add(d))
                }
-               if err := tlsConn.Handshake(); err != nil {
+               if err := tlsConn.HandshakeContext(ctx); err != nil {
                        // If the handshake failed due to the client not speaking
                        // TLS, assume they're speaking plaintext HTTP and write a
                        // 400 response on the TLS conn's underlying net.Conn.
@@ -2412,9 +2389,8 @@ func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
 
        if path != r.URL.Path {
                _, pattern = mux.handler(host, path)
-               url := *r.URL
-               url.Path = path
-               return RedirectHandler(url.String(), StatusMovedPermanently), pattern
+               u := &url.URL{Path: path, RawQuery: r.URL.RawQuery}
+               return RedirectHandler(u.String(), StatusMovedPermanently), pattern
        }
 
        return mux.handler(host, r.URL.Path)
@@ -2572,7 +2548,8 @@ type Server struct {
        TLSConfig *tls.Config
 
        // ReadTimeout is the maximum duration for reading the entire
-       // request, including the body.
+       // request, including the body. A zero or negative value means
+       // there will be no timeout.
        //
        // Because ReadTimeout does not let Handlers make per-request
        // decisions on each request body's acceptable deadline or
@@ -2592,6 +2569,7 @@ type Server struct {
        // writes of the response. It is reset whenever a new
        // request's header is read. Like ReadTimeout, it does not
        // let Handlers make decisions on a per-request basis.
+       // A zero or negative value means there will be no timeout.
        WriteTimeout time.Duration
 
        // IdleTimeout is the maximum amount of time to wait for the
@@ -2643,7 +2621,7 @@ type Server struct {
        // value.
        ConnContext func(ctx context.Context, c net.Conn) context.Context
 
-       inShutdown atomicBool // true when when server is in shutdown
+       inShutdown atomicBool // true when server is in shutdown
 
        disableKeepAlives int32     // accessed atomically.
        nextProtoOnce     sync.Once // guards setupHTTP2_* init
@@ -2889,9 +2867,51 @@ func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
        if req.RequestURI == "*" && req.Method == "OPTIONS" {
                handler = globalOptionsHandler{}
        }
+
+       if req.URL != nil && strings.Contains(req.URL.RawQuery, ";") {
+               var allowQuerySemicolonsInUse int32
+               req = req.WithContext(context.WithValue(req.Context(), silenceSemWarnContextKey, func() {
+                       atomic.StoreInt32(&allowQuerySemicolonsInUse, 1)
+               }))
+               defer func() {
+                       if atomic.LoadInt32(&allowQuerySemicolonsInUse) == 0 {
+                               sh.srv.logf("http: URL query contains semicolon, which is no longer a supported separator; parts of the query may be stripped when parsed; see golang.org/issue/25192")
+                       }
+               }()
+       }
+
        handler.ServeHTTP(rw, req)
 }
 
+var silenceSemWarnContextKey = &contextKey{"silence-semicolons"}
+
+// AllowQuerySemicolons returns a handler that serves requests by converting any
+// unescaped semicolons in the URL query to ampersands, and invoking the handler h.
+//
+// This restores the pre-Go 1.17 behavior of splitting query parameters on both
+// semicolons and ampersands. (See golang.org/issue/25192). Note that this
+// behavior doesn't match that of many proxies, and the mismatch can lead to
+// security issues.
+//
+// AllowQuerySemicolons should be invoked before Request.ParseForm is called.
+func AllowQuerySemicolons(h Handler) Handler {
+       return HandlerFunc(func(w ResponseWriter, r *Request) {
+               if silenceSemicolonsWarning, ok := r.Context().Value(silenceSemWarnContextKey).(func()); ok {
+                       silenceSemicolonsWarning()
+               }
+               if strings.Contains(r.URL.RawQuery, ";") {
+                       r2 := new(Request)
+                       *r2 = *r
+                       r2.URL = new(url.URL)
+                       *r2.URL = *r.URL
+                       r2.URL.RawQuery = strings.ReplaceAll(r.URL.RawQuery, ";", "&")
+                       h.ServeHTTP(w, r2)
+               } else {
+                       h.ServeHTTP(w, r)
+               }
+       })
+}
+
 // ListenAndServe listens on the TCP network address srv.Addr and then
 // calls Serve to handle requests on incoming connections.
 // Accepted connections are configured to enable TCP keep-alives.
index 8d5350374ddb61040af7c0d6b2a00e88436dd64c..e91335729af16171cfe4df274eb3298bfcc91903 100644 (file)
@@ -157,9 +157,25 @@ func testServerIssue5953(t *testing.T, h2 bool) {
        resp.Body.Close()
 }
 
-func TestContentTypeWithCopy_h1(t *testing.T) { testContentTypeWithCopy(t, h1Mode) }
-func TestContentTypeWithCopy_h2(t *testing.T) { testContentTypeWithCopy(t, h2Mode) }
-func testContentTypeWithCopy(t *testing.T, h2 bool) {
+type byteAtATimeReader struct {
+       buf []byte
+}
+
+func (b *byteAtATimeReader) Read(p []byte) (n int, err error) {
+       if len(p) < 1 {
+               return 0, nil
+       }
+       if len(b.buf) == 0 {
+               return 0, io.EOF
+       }
+       p[0] = b.buf[0]
+       b.buf = b.buf[1:]
+       return 1, nil
+}
+
+func TestContentTypeWithVariousSources_h1(t *testing.T) { testContentTypeWithVariousSources(t, h1Mode) }
+func TestContentTypeWithVariousSources_h2(t *testing.T) { testContentTypeWithVariousSources(t, h2Mode) }
+func testContentTypeWithVariousSources(t *testing.T, h2 bool) {
        defer afterTest(t)
 
        const (
@@ -167,30 +183,86 @@ func testContentTypeWithCopy(t *testing.T, h2 bool) {
                expected = "text/html; charset=utf-8"
        )
 
-       cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
-               // Use io.Copy from a bytes.Buffer to trigger ReadFrom.
-               buf := bytes.NewBuffer([]byte(input))
-               n, err := io.Copy(w, buf)
-               if int(n) != len(input) || err != nil {
-                       t.Errorf("io.Copy(w, %q) = %v, %v want %d, nil", input, n, err, len(input))
-               }
-       }))
-       defer cst.close()
+       for _, test := range []struct {
+               name    string
+               handler func(ResponseWriter, *Request)
+       }{{
+               name: "write",
+               handler: func(w ResponseWriter, r *Request) {
+                       // Write the whole input at once.
+                       n, err := w.Write([]byte(input))
+                       if int(n) != len(input) || err != nil {
+                               t.Errorf("w.Write(%q) = %v, %v want %d, nil", input, n, err, len(input))
+                       }
+               },
+       }, {
+               name: "write one byte at a time",
+               handler: func(w ResponseWriter, r *Request) {
+                       // Write the input one byte at a time.
+                       buf := []byte(input)
+                       for i := range buf {
+                               n, err := w.Write(buf[i : i+1])
+                               if n != 1 || err != nil {
+                                       t.Errorf("w.Write(%q) = %v, %v want 1, nil", input, n, err)
+                               }
+                       }
+               },
+       }, {
+               name: "copy from Reader",
+               handler: func(w ResponseWriter, r *Request) {
+                       // Use io.Copy from a plain Reader.
+                       type readerOnly struct{ io.Reader }
+                       buf := bytes.NewBuffer([]byte(input))
+                       n, err := io.Copy(w, readerOnly{buf})
+                       if int(n) != len(input) || err != nil {
+                               t.Errorf("io.Copy(w, %q) = %v, %v want %d, nil", input, n, err, len(input))
+                       }
+               },
+       }, {
+               name: "copy from bytes.Buffer",
+               handler: func(w ResponseWriter, r *Request) {
+                       // Use io.Copy from a bytes.Buffer to trigger ReadFrom.
+                       buf := bytes.NewBuffer([]byte(input))
+                       n, err := io.Copy(w, buf)
+                       if int(n) != len(input) || err != nil {
+                               t.Errorf("io.Copy(w, %q) = %v, %v want %d, nil", input, n, err, len(input))
+                       }
+               },
+       }, {
+               name: "copy one byte at a time",
+               handler: func(w ResponseWriter, r *Request) {
+                       // Use io.Copy from a Reader that returns one byte at a time.
+                       n, err := io.Copy(w, &byteAtATimeReader{[]byte(input)})
+                       if int(n) != len(input) || err != nil {
+                               t.Errorf("io.Copy(w, %q) = %v, %v want %d, nil", input, n, err, len(input))
+                       }
+               },
+       }} {
+               t.Run(test.name, func(t *testing.T) {
+                       cst := newClientServerTest(t, h2, HandlerFunc(test.handler))
+                       defer cst.close()
+
+                       resp, err := cst.c.Get(cst.ts.URL)
+                       if err != nil {
+                               t.Fatalf("Get: %v", err)
+                       }
+                       if ct := resp.Header.Get("Content-Type"); ct != expected {
+                               t.Errorf("Content-Type = %q, want %q", ct, expected)
+                       }
+                       if want, got := resp.Header.Get("Content-Length"), fmt.Sprint(len(input)); want != got {
+                               t.Errorf("Content-Length = %q, want %q", want, got)
+                       }
+                       data, err := io.ReadAll(resp.Body)
+                       if err != nil {
+                               t.Errorf("reading body: %v", err)
+                       } else if !bytes.Equal(data, []byte(input)) {
+                               t.Errorf("data is %q, want %q", data, input)
+                       }
+                       resp.Body.Close()
+
+               })
 
-       resp, err := cst.c.Get(cst.ts.URL)
-       if err != nil {
-               t.Fatalf("Get: %v", err)
-       }
-       if ct := resp.Header.Get("Content-Type"); ct != expected {
-               t.Errorf("Content-Type = %q, want %q", ct, expected)
-       }
-       data, err := io.ReadAll(resp.Body)
-       if err != nil {
-               t.Errorf("reading body: %v", err)
-       } else if !bytes.Equal(data, []byte(input)) {
-               t.Errorf("data is %q, want %q", data, input)
        }
-       resp.Body.Close()
 }
 
 func TestSniffWriteSize_h1(t *testing.T) { testSniffWriteSize(t, h1Mode) }
index fbb0c39829d729ca246c5011210b5af245abf355..85c2e5a360d68676f2f6c4574b0e5833fc68ca24 100644 (file)
@@ -12,6 +12,7 @@ import (
        "io"
        "net/http/httptrace"
        "net/http/internal"
+       "net/http/internal/ascii"
        "net/textproto"
        "reflect"
        "sort"
@@ -638,7 +639,7 @@ func (t *transferReader) parseTransferEncoding() error {
        if len(raw) != 1 {
                return &unsupportedTEError{fmt.Sprintf("too many transfer encodings: %q", raw)}
        }
-       if strings.ToLower(textproto.TrimString(raw[0])) != "chunked" {
+       if !ascii.EqualFold(textproto.TrimString(raw[0]), "chunked") {
                return &unsupportedTEError{fmt.Sprintf("unsupported transfer encoding: %q", raw[0])}
        }
 
index 0aa48273dd385848bc04166027a5d4548494f47b..309194e8e52c86f8ef17109464f8b28a1f244bfa 100644 (file)
@@ -21,6 +21,7 @@ import (
        "log"
        "net"
        "net/http/httptrace"
+       "net/http/internal/ascii"
        "net/textproto"
        "net/url"
        "os"
@@ -426,6 +427,7 @@ func (t *Transport) onceSetNextProtoDefaults() {
 //
 // The environment values may be either a complete URL or a
 // "host[:port]", in which case the "http" scheme is assumed.
+// The schemes "http", "https", and "socks5" are supported.
 // An error is returned if the value is a different form.
 //
 // A nil URL and nil error are returned if no proxy is defined in the
@@ -786,10 +788,12 @@ func (t *Transport) CancelRequest(req *Request) {
 // Cancel an in-flight request, recording the error value.
 // Returns whether the request was canceled.
 func (t *Transport) cancelRequest(key cancelKey, err error) bool {
+       // This function must not return until the cancel func has completed.
+       // See: https://golang.org/issue/34658
        t.reqMu.Lock()
+       defer t.reqMu.Unlock()
        cancel := t.reqCanceler[key]
        delete(t.reqCanceler, key)
-       t.reqMu.Unlock()
        if cancel != nil {
                cancel(err)
        }
@@ -1185,7 +1189,7 @@ type wantConn struct {
 
        // hooks for testing to know when dials are done
        // beforeDial is called in the getConn goroutine when the dial is queued.
-       // afterDial is called when the dial is completed or cancelled.
+       // afterDial is called when the dial is completed or canceled.
        beforeDial func()
        afterDial  func()
 
@@ -1373,7 +1377,7 @@ func (t *Transport) getConn(treq *transportRequest, cm connectMethod) (pc *persi
                        trace.GotConn(httptrace.GotConnInfo{Conn: w.pc.conn, Reused: w.pc.isReused()})
                }
                if w.err != nil {
-                       // If the request has been cancelled, that's probably
+                       // If the request has been canceled, that's probably
                        // what caused w.err; if so, prefer to return the
                        // cancellation error (see golang.org/issue/16049).
                        select {
@@ -1435,7 +1439,7 @@ func (t *Transport) queueForDial(w *wantConn) {
 
 // dialConnFor dials on behalf of w and delivers the result to w.
 // dialConnFor has received permission to dial w.cm and is counted in t.connCount[w.cm.key()].
-// If the dial is cancelled or unsuccessful, dialConnFor decrements t.connCount[w.cm.key()].
+// If the dial is canceled or unsuccessful, dialConnFor decrements t.connCount[w.cm.key()].
 func (t *Transport) dialConnFor(w *wantConn) {
        defer w.afterDial()
 
@@ -1505,7 +1509,7 @@ func (t *Transport) decConnsPerHost(key connectMethodKey) {
 // Add TLS to a persistent connection, i.e. negotiate a TLS session. If pconn is already a TLS
 // tunnel, this function establishes a nested TLS session inside the encrypted channel.
 // The remote endpoint's name may be overridden by TLSClientConfig.ServerName.
-func (pconn *persistConn) addTLS(name string, trace *httptrace.ClientTrace) error {
+func (pconn *persistConn) addTLS(ctx context.Context, name string, trace *httptrace.ClientTrace) error {
        // Initiate TLS and check remote host name against certificate.
        cfg := cloneTLSConfig(pconn.t.TLSClientConfig)
        if cfg.ServerName == "" {
@@ -1527,7 +1531,7 @@ func (pconn *persistConn) addTLS(name string, trace *httptrace.ClientTrace) erro
                if trace != nil && trace.TLSHandshakeStart != nil {
                        trace.TLSHandshakeStart()
                }
-               err := tlsConn.Handshake()
+               err := tlsConn.HandshakeContext(ctx)
                if timer != nil {
                        timer.Stop()
                }
@@ -1583,7 +1587,7 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (pconn *pers
                        if trace != nil && trace.TLSHandshakeStart != nil {
                                trace.TLSHandshakeStart()
                        }
-                       if err := tc.Handshake(); err != nil {
+                       if err := tc.HandshakeContext(ctx); err != nil {
                                go pconn.conn.Close()
                                if trace != nil && trace.TLSHandshakeDone != nil {
                                        trace.TLSHandshakeDone(tls.ConnectionState{}, err)
@@ -1607,7 +1611,7 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (pconn *pers
                        if firstTLSHost, _, err = net.SplitHostPort(cm.addr()); err != nil {
                                return nil, wrapErr(err)
                        }
-                       if err = pconn.addTLS(firstTLSHost, trace); err != nil {
+                       if err = pconn.addTLS(ctx, firstTLSHost, trace); err != nil {
                                return nil, wrapErr(err)
                        }
                }
@@ -1721,7 +1725,7 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (pconn *pers
        }
 
        if cm.proxyURL != nil && cm.targetScheme == "https" {
-               if err := pconn.addTLS(cm.tlsHost(), trace); err != nil {
+               if err := pconn.addTLS(ctx, cm.tlsHost(), trace); err != nil {
                        return nil, err
                }
        }
@@ -2183,7 +2187,7 @@ func (pc *persistConn) readLoop() {
                }
 
                resp.Body = body
-               if rc.addedGzip && strings.EqualFold(resp.Header.Get("Content-Encoding"), "gzip") {
+               if rc.addedGzip && ascii.EqualFold(resp.Header.Get("Content-Encoding"), "gzip") {
                        resp.Body = &gzipReader{body: body}
                        resp.Header.Del("Content-Encoding")
                        resp.Header.Del("Content-Length")
index 1097ffd1739cc375143533c2ac7be3d7fdb272f3..1cce27235dfdc3ce73c7188c609187d61ebb6bb2 100644 (file)
@@ -12,7 +12,7 @@ import (
        "errors"
        "io"
        "net"
-       "net/http/internal"
+       "net/http/internal/testcert"
        "strings"
        "testing"
 )
@@ -191,7 +191,7 @@ func (f roundTripFunc) RoundTrip(r *Request) (*Response, error) {
 
 // Issue 25009
 func TestTransportBodyAltRewind(t *testing.T) {
-       cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey)
+       cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey)
        if err != nil {
                t.Fatal(err)
        }
index d0202c0e0074ef392771ef016400872e66acef10..cae54643ddd0ddc77de32ee8235c313bca048acf 100644 (file)
@@ -30,7 +30,7 @@ import (
        "net/http/httptest"
        "net/http/httptrace"
        "net/http/httputil"
-       "net/http/internal"
+       "net/http/internal/testcert"
        "net/textproto"
        "net/url"
        "os"
@@ -626,12 +626,15 @@ func TestTransportMaxConnsPerHost(t *testing.T) {
                        t.Fatalf("ExportHttp2ConfigureTransport: %v", err)
                }
 
-               connCh := make(chan net.Conn, 1)
+               mu := sync.Mutex{}
+               var conns []net.Conn
                var dialCnt, gotConnCnt, tlsHandshakeCnt int32
                tr.Dial = func(network, addr string) (net.Conn, error) {
                        atomic.AddInt32(&dialCnt, 1)
                        c, err := net.Dial(network, addr)
-                       connCh <- c
+                       mu.Lock()
+                       defer mu.Unlock()
+                       conns = append(conns, c)
                        return c, err
                }
 
@@ -685,7 +688,12 @@ func TestTransportMaxConnsPerHost(t *testing.T) {
                        t.FailNow()
                }
 
-               (<-connCh).Close()
+               mu.Lock()
+               for _, c := range conns {
+                       c.Close()
+               }
+               conns = nil
+               mu.Unlock()
                tr.CloseIdleConnections()
 
                doReq()
@@ -3738,7 +3746,7 @@ func TestTransportDialTLSContext(t *testing.T) {
                if err != nil {
                        return nil, err
                }
-               return c, c.Handshake()
+               return c, c.HandshakeContext(ctx)
        }
 
        req, err := NewRequest("GET", ts.URL, nil)
@@ -4295,7 +4303,7 @@ func TestTransportReuseConnEmptyResponseBody(t *testing.T) {
 
 // Issue 13839
 func TestNoCrashReturningTransportAltConn(t *testing.T) {
-       cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey)
+       cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey)
        if err != nil {
                t.Fatal(err)
        }
index 23e65d56e86f5ae83633620a879250d52a57f6bd..4dc62407c6d5ecef2049db623b31c5db4d21df8f 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 package main
index 914aaa010f3b98bb270f3455d4b39b454b8d71ca..0e5d3202c911ec1efe8d3b26b25300b9f5cfb1e0 100644 (file)
@@ -6,6 +6,7 @@ package net
 
 import (
        "errors"
+       "internal/itoa"
        "sync"
        "time"
 )
@@ -230,7 +231,7 @@ func (zc *ipv6ZoneCache) name(index int) string {
                zoneCache.RUnlock()
        }
        if !ok { // last resort
-               name = uitoa(uint(index))
+               name = itoa.Uitoa(uint(index))
        }
        return name
 }
index d791cb30167943cc9355cb08635ad9a99efd58fe..7578b1a16a91a90baabeef015e2f84d18fe14fb3 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || netbsd || openbsd
 // +build darwin dragonfly freebsd netbsd openbsd
 
 package net
index 947dde71e61b2935c062a0366bb5d1a73672a6a5..8d0d9c367198d0abd5ba602c4209c6b0988c55ee 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || netbsd || openbsd
 // +build darwin dragonfly freebsd netbsd openbsd
 
 package net
index a809b5f5ce49e6cf31e07cea02ab3fe34e6b7736..6230e0bfeec1d56a117c107beb69e9db7861d61b 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build dragonfly || netbsd || openbsd
 // +build dragonfly netbsd openbsd
 
 package net
index 45badd64954a17d087eab9a9540b94acd2d938e4..2b51fcb632a3f7add6cb1a0ece5b920899263e4d 100644 (file)
@@ -16,9 +16,9 @@ func interfaceMessages(ifindex int) ([]route.Message, error) {
        if err != nil {
                typ = route.RIBType(syscall.NET_RT_IFLIST)
                rib, err = route.FetchRIB(syscall.AF_UNSPEC, typ, ifindex)
-       }
-       if err != nil {
-               return nil, err
+               if err != nil {
+                       return nil, err
+               }
        }
        return route.ParseRIB(typ, rib)
 }
index 31bbaca4675c2955acd9f4064b070c9c6827224a..957975c265549211e3a6c11bbd7b19bc730f79c5 100644 (file)
@@ -6,6 +6,7 @@ package net
 
 import (
        "errors"
+       "internal/itoa"
        "os"
 )
 
@@ -38,8 +39,8 @@ func interfaceTable(ifindex int) ([]Interface, error) {
 
 func readInterface(i int) (*Interface, error) {
        ifc := &Interface{
-               Index: i + 1,                        // Offset the index by one to suit the contract
-               Name:  netdir + "/ipifc/" + itoa(i), // Name is the full path to the interface path in plan9
+               Index: i + 1,                             // Offset the index by one to suit the contract
+               Name:  netdir + "/ipifc/" + itoa.Itoa(i), // Name is the full path to the interface path in plan9
        }
 
        ifcstat := ifc.Name + "/status"
index 437b9ebb18941e97de2ef6e057c5d9e6b1971cca..1075e36205a16798685939ce0da8a97dcc2e3923 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build hurd || (js && wasm)
 // +build hurd js,wasm
 
 package net
index b2ef21e8ac24482f3d59608539f52e544b8eaaa8..754db36e3c44306edfa986165478611b574b3905 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js
 // +build !js
 
 package net
index bf41a0fb82de3a8b98ba6610f8550b1d0c5382f5..0d69fa5da4127d2f9c863ec597db31ee8bdfcfa4 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd
 // +build darwin dragonfly freebsd linux netbsd openbsd
 
 package net
index 3b0a48aef4d986f9ea6ce0ac76c83f0ff70c970c..8af85d382eb0935cbb606e9c6869a5b7354b69c8 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js && !plan9
 // +build !js,!plan9
 
 package socktest_test
index 4d9d4143564864ce1b90ad42503f112f23cc5cda..6aa8875b66cf6c1cee258401128c733ee49d4c66 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js && !plan9 && !windows
 // +build !js,!plan9,!windows
 
 package socktest_test
index 863edef0d35595e53407afbdfc0d55e37319342c..cda74e8639986909c9a3bf740a825e547f12ba35 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !plan9
 // +build !plan9
 
 package socktest
index 28ce72cb855a6e1769326cee1b56d585439dd23c..5aa2ecec08fd31ad596e475345c0befa72fc8721 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build plan9
 // +build plan9
 
 package socktest
index 4c037baec0c7c7c1a8303799ab7e0c05ba8a5285..be9ef6dd1c3adedd29a994c0cec2a5bd8a06e6fd 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris
 
 package socktest
index b13ba57fcba18ca77a9fd3029af952f152a71034..5e95896f36215abf2447eac4d0902c8d58dac532 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build dragonfly || freebsd || hurd || illumos || linux || netbsd || openbsd
 // +build dragonfly freebsd hurd illumos linux netbsd openbsd
 
 package socktest
index fbbffc6eaba823d409c1535c0cb408c40706de86..39f3dbc7e78662840c143949b32fee4c24c90d86 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris
 
 package socktest
index c00fe8ed3cc64f704572996e946ee37f332b5674..38e1aa2247f5c329d9c247de420b2a58ecc8a25b 100644 (file)
 
 package net
 
-import "internal/bytealg"
+import (
+       "internal/bytealg"
+       "internal/itoa"
+)
 
 // IP address lengths (bytes).
 const (
@@ -125,6 +128,25 @@ func (ip IP) IsLoopback() bool {
        return ip.Equal(IPv6loopback)
 }
 
+// IsPrivate reports whether ip is a private address, according to
+// RFC 1918 (IPv4 addresses) and RFC 4193 (IPv6 addresses).
+func (ip IP) IsPrivate() bool {
+       if ip4 := ip.To4(); ip4 != nil {
+               // Following RFC 1918, Section 3. Private Address Space which says:
+               //   The Internet Assigned Numbers Authority (IANA) has reserved the
+               //   following three blocks of the IP address space for private internets:
+               //     10.0.0.0        -   10.255.255.255  (10/8 prefix)
+               //     172.16.0.0      -   172.31.255.255  (172.16/12 prefix)
+               //     192.168.0.0     -   192.168.255.255 (192.168/16 prefix)
+               return ip4[0] == 10 ||
+                       (ip4[0] == 172 && ip4[1]&0xf0 == 16) ||
+                       (ip4[0] == 192 && ip4[1] == 168)
+       }
+       // Following RFC 4193, Section 8. IANA Considerations which says:
+       //   The IANA has assigned the FC00::/7 prefix to "Unique Local Unicast".
+       return len(ip) == IPv6len && ip[0]&0xfe == 0xfc
+}
+
 // IsMulticast reports whether ip is a multicast address.
 func (ip IP) IsMulticast() bool {
        if ip4 := ip.To4(); ip4 != nil {
@@ -531,7 +553,7 @@ func (n *IPNet) String() string {
        if l == -1 {
                return nn.String() + "/" + m.String()
        }
-       return nn.String() + "/" + uitoa(uint(l))
+       return nn.String() + "/" + itoa.Uitoa(uint(l))
 }
 
 // Parse IPv4 address (d.d.d.d).
@@ -552,6 +574,10 @@ func parseIPv4(s string) IP {
                if !ok || n > 0xFF {
                        return nil
                }
+               if c > 1 && s[0] == '0' {
+                       // Reject non-zero components with leading zeroes.
+                       return nil
+               }
                s = s[c:]
                p[i] = byte(n)
        }
index a5fc5e644a2b2717ab16b1005c586be8bb65d2d6..5bbda6024dc3d9dd54189eb202afcb5cda572ad7 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js
 // +build !js
 
 package net
@@ -20,9 +21,7 @@ var parseIPTests = []struct {
 }{
        {"127.0.1.2", IPv4(127, 0, 1, 2)},
        {"127.0.0.1", IPv4(127, 0, 0, 1)},
-       {"127.001.002.003", IPv4(127, 1, 2, 3)},
        {"::ffff:127.1.2.3", IPv4(127, 1, 2, 3)},
-       {"::ffff:127.001.002.003", IPv4(127, 1, 2, 3)},
        {"::ffff:7f01:0203", IPv4(127, 1, 2, 3)},
        {"0:0:0:0:0000:ffff:127.1.2.3", IPv4(127, 1, 2, 3)},
        {"0:0:0:0:000000:ffff:127.1.2.3", IPv4(127, 1, 2, 3)},
@@ -42,6 +41,11 @@ var parseIPTests = []struct {
        {"fe80::1%911", nil},
        {"", nil},
        {"a1:a2:a3:a4::b1:b2:b3:b4", nil}, // Issue 6628
+       {"127.001.002.003", nil},
+       {"::ffff:127.001.002.003", nil},
+       {"123.000.000.000", nil},
+       {"1.2..4", nil},
+       {"0123.0.0.1", nil},
 }
 
 func TestParseIP(t *testing.T) {
@@ -357,6 +361,7 @@ var parseCIDRTests = []struct {
        {"0.0.-2.0/32", nil, nil, &ParseError{Type: "CIDR address", Text: "0.0.-2.0/32"}},
        {"0.0.0.-3/32", nil, nil, &ParseError{Type: "CIDR address", Text: "0.0.0.-3/32"}},
        {"0.0.0.0/-0", nil, nil, &ParseError{Type: "CIDR address", Text: "0.0.0.0/-0"}},
+       {"127.000.000.001/32", nil, nil, &ParseError{Type: "CIDR address", Text: "127.000.000.001/32"}},
        {"", nil, nil, &ParseError{Type: "CIDR address", Text: ""}},
 }
 
@@ -690,6 +695,28 @@ var ipAddrScopeTests = []struct {
        {IP.IsGlobalUnicast, IP{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
        {IP.IsGlobalUnicast, IP{0xff, 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
        {IP.IsGlobalUnicast, nil, false},
+       {IP.IsPrivate, nil, false},
+       {IP.IsPrivate, IPv4(1, 1, 1, 1), false},
+       {IP.IsPrivate, IPv4(9, 255, 255, 255), false},
+       {IP.IsPrivate, IPv4(10, 0, 0, 0), true},
+       {IP.IsPrivate, IPv4(10, 255, 255, 255), true},
+       {IP.IsPrivate, IPv4(11, 0, 0, 0), false},
+       {IP.IsPrivate, IPv4(172, 15, 255, 255), false},
+       {IP.IsPrivate, IPv4(172, 16, 0, 0), true},
+       {IP.IsPrivate, IPv4(172, 16, 255, 255), true},
+       {IP.IsPrivate, IPv4(172, 23, 18, 255), true},
+       {IP.IsPrivate, IPv4(172, 31, 255, 255), true},
+       {IP.IsPrivate, IPv4(172, 31, 0, 0), true},
+       {IP.IsPrivate, IPv4(172, 32, 0, 0), false},
+       {IP.IsPrivate, IPv4(192, 167, 255, 255), false},
+       {IP.IsPrivate, IPv4(192, 168, 0, 0), true},
+       {IP.IsPrivate, IPv4(192, 168, 255, 255), true},
+       {IP.IsPrivate, IPv4(192, 169, 0, 0), false},
+       {IP.IsPrivate, IP{0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, false},
+       {IP.IsPrivate, IP{0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, true},
+       {IP.IsPrivate, IP{0xfc, 0xff, 0x12, 0, 0, 0, 0, 0x44, 0, 0, 0, 0, 0, 0, 0, 0}, true},
+       {IP.IsPrivate, IP{0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, true},
+       {IP.IsPrivate, IP{0xfe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
 }
 
 func name(f interface{}) string {
index fdb39135be9c9e699a86c0b05332a02d970c6120..ffc437c4560564c68743e1d1d8568ecafec31af3 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows
 
 package net
@@ -74,7 +75,7 @@ func stripIPv4Header(n int, b []byte) int {
 
 func (c *IPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
        var sa syscall.Sockaddr
-       n, oobn, flags, sa, err = c.fd.readMsg(b, oob)
+       n, oobn, flags, sa, err = c.fd.readMsg(b, oob, 0)
        switch sa := sa.(type) {
        case *syscall.SockaddrInet4:
                addr = &IPAddr{IP: sa.Addr[0:]}
index 8e3543dfc7fd71c733e1d674d1d0e53d1d9ed835..a96448ee6c656817f1a16e5ff6fd27ca774048fa 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js
 // +build !js
 
 package net
index 7d0684d176400d0a1c2bd23a0a8b460a75bc8ff5..0f5da2577c6a62e12faad7b2ec0b75cb23841431 100644 (file)
@@ -7,6 +7,7 @@ package net
 import (
        "context"
        "internal/bytealg"
+       "runtime"
        "sync"
 )
 
@@ -44,6 +45,13 @@ func supportsIPv6() bool {
 // IPv4 address inside an IPv6 address at transport layer
 // protocols. See RFC 4291, RFC 4038 and RFC 3493.
 func supportsIPv4map() bool {
+       // Some operating systems provide no support for mapping IPv4
+       // addresses to IPv6, and a runtime check is unnecessary.
+       switch runtime.GOOS {
+       case "dragonfly", "openbsd":
+               return false
+       }
+
        ipStackCaps.Once.Do(ipStackCaps.probe)
        return ipStackCaps.ipv4MappedIPv6Enabled
 }
index 7a4b7a6041cbf5948209c72087810e8dce4d8d0c..43287431c88c89ad581cff755b19ac5b96b97b59 100644 (file)
@@ -7,12 +7,13 @@ package net
 import (
        "context"
        "internal/bytealg"
+       "internal/itoa"
        "io/fs"
        "os"
        "syscall"
 )
 
-// Probe probes IPv4, IPv6 and IPv4-mapped IPv6 communication
+// probe probes IPv4, IPv6 and IPv4-mapped IPv6 communication
 // capabilities.
 //
 // Plan 9 uses IPv6 natively, see ip(3).
@@ -336,9 +337,9 @@ func plan9LocalAddr(addr Addr) string {
                if port == 0 {
                        return ""
                }
-               return itoa(port)
+               return itoa.Itoa(port)
        }
-       return ip.String() + "!" + itoa(port)
+       return ip.String() + "!" + itoa.Itoa(port)
 }
 
 func hangupCtlWrite(ctx context.Context, proto string, ctl *os.File, msg string) error {
index 84e72d52549429b1907f3fc159a72e2b6fea9c26..cdd191aaeb8d22f688eecc368ce52f659dd2ce1b 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows
 
 package net
@@ -13,13 +14,13 @@ import (
        "syscall"
 )
 
-// Probe probes IPv4, IPv6 and IPv4-mapped IPv6 communication
+// probe probes IPv4, IPv6 and IPv4-mapped IPv6 communication
 // capabilities which are controlled by the IPV6_V6ONLY socket option
 // and kernel configuration.
 //
 // Should we try to use the IPv4 socket interface if we're only
 // dealing with IPv4 sockets? As long as the host system understands
-// IPv4-mapped IPv6, it's okay to pass IPv4-mapeed IPv6 addresses to
+// IPv4-mapped IPv6, it's okay to pass IPv4-mapped IPv6 addresses to
 // the IPv6 interface. That simplifies our code and is most
 // general. Unfortunately, we need to run on kernels built without
 // IPv6 support too. So probe the kernel to figure it out.
index d8c72096ed16514fc415f9ba15905fc2439a25de..b1dce29ac209a91e45436583ef3ffa2788e39378 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js && !plan9
 // +build !js,!plan9
 
 package net
index 0660268249bc765186a4443273bd111266e8a280..d350ef7fc03b0b6259a562e5f28b04a40157fdf0 100644 (file)
@@ -166,6 +166,9 @@ func (r *Resolver) getLookupGroup() *singleflight.Group {
 
 // LookupHost looks up the given host using the local resolver.
 // It returns a slice of that host's addresses.
+//
+// LookupHost uses context.Background internally; to specify the context, use
+// Resolver.LookupHost.
 func LookupHost(host string) (addrs []string, err error) {
        return DefaultResolver.LookupHost(context.Background(), host)
 }
@@ -353,6 +356,9 @@ func ipAddrsEface(addrs []IPAddr) []interface{} {
 }
 
 // LookupPort looks up the port for the given network and service.
+//
+// LookupPort uses context.Background internally; to specify the context, use
+// Resolver.LookupPort.
 func LookupPort(network, service string) (port int, err error) {
        return DefaultResolver.LookupPort(context.Background(), network, service)
 }
@@ -392,6 +398,9 @@ func (r *Resolver) LookupPort(ctx context.Context, network, service string) (por
 //
 // The returned canonical name is validated to be a properly
 // formatted presentation-format domain name.
+//
+// LookupCNAME uses context.Background internally; to specify the context, use
+// Resolver.LookupCNAME.
 func LookupCNAME(host string) (cname string, err error) {
        return DefaultResolver.LookupCNAME(context.Background(), host)
 }
@@ -415,7 +424,7 @@ func (r *Resolver) LookupCNAME(ctx context.Context, host string) (string, error)
                return "", err
        }
        if !isDomainName(cname) {
-               return "", &DNSError{Err: "CNAME target is invalid", Name: host}
+               return "", &DNSError{Err: errMalformedDNSRecordsDetail, Name: host}
        }
        return cname, nil
 }
@@ -431,7 +440,9 @@ func (r *Resolver) LookupCNAME(ctx context.Context, host string) (string, error)
 // and proto are empty strings, LookupSRV looks up name directly.
 //
 // The returned service names are validated to be properly
-// formatted presentation-format domain names.
+// formatted presentation-format domain names. If the response contains
+// invalid names, those records are filtered out and an error
+// will be returned alongside the the remaining results, if any.
 func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
        return DefaultResolver.LookupSRV(context.Background(), service, proto, name)
 }
@@ -447,7 +458,9 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err err
 // and proto are empty strings, LookupSRV looks up name directly.
 //
 // The returned service names are validated to be properly
-// formatted presentation-format domain names.
+// formatted presentation-format domain names. If the response contains
+// invalid names, those records are filtered out and an error
+// will be returned alongside the the remaining results, if any.
 func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) {
        cname, addrs, err := r.lookupSRV(ctx, service, proto, name)
        if err != nil {
@@ -456,21 +469,31 @@ func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) (
        if cname != "" && !isDomainName(cname) {
                return "", nil, &DNSError{Err: "SRV header name is invalid", Name: name}
        }
+       filteredAddrs := make([]*SRV, 0, len(addrs))
        for _, addr := range addrs {
                if addr == nil {
                        continue
                }
                if !isDomainName(addr.Target) {
-                       return "", nil, &DNSError{Err: "SRV target is invalid", Name: name}
+                       continue
                }
+               filteredAddrs = append(filteredAddrs, addr)
        }
-       return cname, addrs, nil
+       if len(addrs) != len(filteredAddrs) {
+               return cname, filteredAddrs, &DNSError{Err: errMalformedDNSRecordsDetail, Name: name}
+       }
+       return cname, filteredAddrs, nil
 }
 
 // LookupMX returns the DNS MX records for the given domain name sorted by preference.
 //
 // The returned mail server names are validated to be properly
-// formatted presentation-format domain names.
+// formatted presentation-format domain names. If the response contains
+// invalid names, those records are filtered out and an error
+// will be returned alongside the the remaining results, if any.
+//
+// LookupMX uses context.Background internally; to specify the context, use
+// Resolver.LookupMX.
 func LookupMX(name string) ([]*MX, error) {
        return DefaultResolver.LookupMX(context.Background(), name)
 }
@@ -478,27 +501,41 @@ func LookupMX(name string) ([]*MX, error) {
 // LookupMX returns the DNS MX records for the given domain name sorted by preference.
 //
 // The returned mail server names are validated to be properly
-// formatted presentation-format domain names.
+// formatted presentation-format domain names. If the response contains
+// invalid names, those records are filtered out and an error
+// will be returned alongside the the remaining results, if any.
 func (r *Resolver) LookupMX(ctx context.Context, name string) ([]*MX, error) {
        records, err := r.lookupMX(ctx, name)
        if err != nil {
                return nil, err
        }
+       filteredMX := make([]*MX, 0, len(records))
        for _, mx := range records {
                if mx == nil {
                        continue
                }
-               if !isDomainName(mx.Host) {
-                       return nil, &DNSError{Err: "MX target is invalid", Name: name}
+               // Bypass the hostname validity check for targets which contain only a dot,
+               // as this is used to represent a 'Null' MX record.
+               if mx.Host != "." && !isDomainName(mx.Host) {
+                       continue
                }
+               filteredMX = append(filteredMX, mx)
+       }
+       if len(records) != len(filteredMX) {
+               return filteredMX, &DNSError{Err: errMalformedDNSRecordsDetail, Name: name}
        }
-       return records, nil
+       return filteredMX, nil
 }
 
 // LookupNS returns the DNS NS records for the given domain name.
 //
 // The returned name server names are validated to be properly
-// formatted presentation-format domain names.
+// formatted presentation-format domain names. If the response contains
+// invalid names, those records are filtered out and an error
+// will be returned alongside the the remaining results, if any.
+//
+// LookupNS uses context.Background internally; to specify the context, use
+// Resolver.LookupNS.
 func LookupNS(name string) ([]*NS, error) {
        return DefaultResolver.LookupNS(context.Background(), name)
 }
@@ -506,24 +543,34 @@ func LookupNS(name string) ([]*NS, error) {
 // LookupNS returns the DNS NS records for the given domain name.
 //
 // The returned name server names are validated to be properly
-// formatted presentation-format domain names.
+// formatted presentation-format domain names. If the response contains
+// invalid names, those records are filtered out and an error
+// will be returned alongside the the remaining results, if any.
 func (r *Resolver) LookupNS(ctx context.Context, name string) ([]*NS, error) {
        records, err := r.lookupNS(ctx, name)
        if err != nil {
                return nil, err
        }
+       filteredNS := make([]*NS, 0, len(records))
        for _, ns := range records {
                if ns == nil {
                        continue
                }
                if !isDomainName(ns.Host) {
-                       return nil, &DNSError{Err: "NS target is invalid", Name: name}
+                       continue
                }
+               filteredNS = append(filteredNS, ns)
        }
-       return records, nil
+       if len(records) != len(filteredNS) {
+               return filteredNS, &DNSError{Err: errMalformedDNSRecordsDetail, Name: name}
+       }
+       return filteredNS, nil
 }
 
 // LookupTXT returns the DNS TXT records for the given domain name.
+//
+// LookupTXT uses context.Background internally; to specify the context, use
+// Resolver.LookupTXT.
 func LookupTXT(name string) ([]string, error) {
        return DefaultResolver.lookupTXT(context.Background(), name)
 }
@@ -537,10 +584,14 @@ func (r *Resolver) LookupTXT(ctx context.Context, name string) ([]string, error)
 // of names mapping to that address.
 //
 // The returned names are validated to be properly formatted presentation-format
-// domain names.
+// domain names. If the response contains invalid names, those records are filtered
+// out and an error will be returned alongside the the remaining results, if any.
 //
 // When using the host C library resolver, at most one result will be
 // returned. To bypass the host resolver, use a custom Resolver.
+//
+// LookupAddr uses context.Background internally; to specify the context, use
+// Resolver.LookupAddr.
 func LookupAddr(addr string) (names []string, err error) {
        return DefaultResolver.LookupAddr(context.Background(), addr)
 }
@@ -549,16 +600,26 @@ func LookupAddr(addr string) (names []string, err error) {
 // of names mapping to that address.
 //
 // The returned names are validated to be properly formatted presentation-format
-// domain names.
+// domain names. If the response contains invalid names, those records are filtered
+// out and an error will be returned alongside the the remaining results, if any.
 func (r *Resolver) LookupAddr(ctx context.Context, addr string) ([]string, error) {
        names, err := r.lookupAddr(ctx, addr)
        if err != nil {
                return nil, err
        }
+       filteredNames := make([]string, 0, len(names))
        for _, name := range names {
-               if !isDomainName(name) {
-                       return nil, &DNSError{Err: "PTR target is invalid", Name: addr}
+               if isDomainName(name) {
+                       filteredNames = append(filteredNames, name)
                }
        }
-       return names, nil
+       if len(names) != len(filteredNames) {
+               return filteredNames, &DNSError{Err: errMalformedDNSRecordsDetail, Name: addr}
+       }
+       return filteredNames, nil
 }
+
+// errMalformedDNSRecordsDetail is the DNSError detail which is returned when a Resolver.Lookup...
+// method recieves DNS records which contain invalid DNS names. This may be returned alongside
+// results which have had the malformed records filtered out.
+var errMalformedDNSRecordsDetail = "DNS response contained records which contain invalid names"
index 3b3c39bc7dacf799ed32c42e5ca6a8d547bec6d6..f4fcaed5cfa1c78d9ca3b80d81926b20074de7dd 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build js && wasm
 // +build js,wasm
 
 package net
index 6a2d48eedace46d23e2a40c4f10ab38466a39900..75c18b33ac06f0eca362200a8909b45bf3ab23c3 100644 (file)
@@ -8,6 +8,7 @@ import (
        "context"
        "errors"
        "internal/bytealg"
+       "internal/itoa"
        "io"
        "os"
 )
@@ -84,7 +85,7 @@ func queryCS1(ctx context.Context, net string, ip IP, port int) (clone, dest str
        if len(ip) != 0 && !ip.IsUnspecified() {
                ips = ip.String()
        }
-       lines, err := queryCS(ctx, net, ips, itoa(port))
+       lines, err := queryCS(ctx, net, ips, itoa.Itoa(port))
        if err != nil {
                return
        }
@@ -308,7 +309,7 @@ func (*Resolver) lookupTXT(ctx context.Context, name string) (txt []string, err
        }
        for _, line := range lines {
                if i := bytealg.IndexByteString(line, '\t'); i >= 0 {
-                       txt = append(txt, absDomainName([]byte(line[i+1:])))
+                       txt = append(txt, line[i+1:])
                }
        }
        return
index 32a0d377da3ed4b13b9a93c276eec625d9ee3436..3faaf007106b7c7327f1eb194dfc8d944f8b53d4 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js
 // +build !js
 
 package net
index c27b1a0a195149cff6ff0ea3a65f0bb631735b6e..05f49b0b0e69834b67660009d12f8e44e314ee50 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package net
@@ -89,7 +90,7 @@ func (r *Resolver) lookupHost(ctx context.Context, host string) (addrs []string,
 
 func (r *Resolver) lookupIP(ctx context.Context, network, host string) (addrs []IPAddr, err error) {
        if r.preferGo() {
-               return r.goLookupIP(ctx, host)
+               return r.goLookupIP(ctx, network, host)
        }
        order := systemConf().hostLookupOrder(r, host)
        if order == hostLookupCgo {
@@ -99,7 +100,7 @@ func (r *Resolver) lookupIP(ctx context.Context, network, host string) (addrs []
                // cgo not available (or netgo); fall back to Go's DNS resolver
                order = hostLookupFilesDNS
        }
-       ips, _, err := r.goLookupIPCNAMEOrder(ctx, host, order)
+       ips, _, err := r.goLookupIPCNAMEOrder(ctx, network, host, order)
        return ips, err
 }
 
index 62b61ed6c2f3ce9ed43a0bff92358be6a731db34..aa95501d023930d114970e828296e9d10b531d9e 100644 (file)
@@ -299,7 +299,7 @@ func lookupPTR(name string) (ptr []string, err error) {
        ptr = make([]string, 0, 10)
        rx := regexp.MustCompile(`(?m)^Pinging\s+([a-zA-Z0-9.\-]+)\s+\[.*$`)
        for _, ans := range rx.FindAllStringSubmatch(r, -1) {
-               ptr = append(ptr, ans[1]+".")
+               ptr = append(ptr, absDomainName([]byte(ans[1])))
        }
        return
 }
index d436df17235d9c627e0f339f269b9de337f001da..03f7d63b243a706a858934665819c729befb98a8 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build dragonfly || freebsd || hurd || illumos || linux || netbsd || openbsd
 // +build dragonfly freebsd hurd illumos linux netbsd openbsd
 
 package net
index a92dff56c2aae15360b3c337e0e1a3442eeb58cf..645b267b78090835050a56c68e768759239b0f5f 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js && !plan9 && !windows
 // +build !js,!plan9,!windows
 
 package net
index bac84aa3002ab184272bd80a60efe746ad46b6b8..bcea630cd3c4ccb037b4d19582c927892d13a825 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build (js && wasm) || plan9 || windows
 // +build js,wasm plan9 windows
 
 package net
index f2484f306db91dce5a64855f0c14494b2bf08b88..c9ab25a4ad572ebb8e663fbf6bfe1d2c18999802 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js && !plan9
 // +build !js,!plan9
 
 package net
index 2d5be2ee5f81c1b634b84b0ce002306252e3d5e5..dc17d3fbb84d1547879afa575352561299aa510e 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js
 // +build !js
 
 package net
index ef7e915aa60a5174cc6710b29f6f230f31d7a6a7..367cefce2e32e5f84c8ca3ea8abe2d10dc15966d 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package net
index 867e31e9ae6a55823a237f89fc5335594d085ca4..b50a1e59a1a9239b7da034fe38f6b1619e88ea95 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js
 // +build !js
 
 package net
index 4b4ed129ccc3f8e798e601f6110230f0579ad49e..a7c65fff79526d1ce70fef7a96eaafd9ff06dd18 100644 (file)
@@ -539,6 +539,9 @@ type ParseError struct {
 
 func (e *ParseError) Error() string { return "invalid " + e.Type + ": " + e.Text }
 
+func (e *ParseError) Timeout() bool   { return false }
+func (e *ParseError) Temporary() bool { return false }
+
 type AddrError struct {
        Err  string
        Addr string
@@ -642,7 +645,7 @@ var errClosed = poll.ErrNetClosing
 // another goroutine before the I/O is completed. This may be wrapped
 // in another error, and should normally be tested using
 // errors.Is(err, net.ErrClosed).
-var ErrClosed = errClosed
+var ErrClosed error = errClosed
 
 type writerOnly struct {
        io.Writer
@@ -733,6 +736,7 @@ func (v *Buffers) consume(n int64) {
                        return
                }
                n -= ln0
+               (*v)[0] = nil
                *v = (*v)[1:]
        }
 }
index 0c48dd5c03bb47ead18b5571a1c635865ca83dd4..74fc1da6fd80af665696880153bfc49a508900d6 100644 (file)
@@ -4,6 +4,7 @@
 
 // Fake networking for js/wasm. It is intended to allow tests of other package to pass.
 
+//go:build js && wasm
 // +build js,wasm
 
 package net
@@ -267,7 +268,7 @@ func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
        return 0, nil, syscall.ENOSYS
 }
 
-func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
+func (fd *netFD) readMsg(p []byte, oob []byte, flags int) (n, oobn, retflags int, sa syscall.Sockaddr, err error) {
        return 0, 0, 0, nil, syscall.ENOSYS
 }
 
index 409e1400af96c8f10727dcb6e88ff2f62ff2ed7d..6e7be4db23c1e2a26733bf251ff47546efcddd0d 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js
 // +build !js
 
 package net
@@ -587,3 +588,23 @@ func TestNotTemporaryRead(t *testing.T) {
        }
        withTCPConnPair(t, client, server)
 }
+
+// The various errors should implement the Error interface.
+func TestErrors(t *testing.T) {
+       var (
+               _ Error = &OpError{}
+               _ Error = &ParseError{}
+               _ Error = &AddrError{}
+               _ Error = UnknownNetworkError("")
+               _ Error = InvalidAddrError("")
+               _ Error = &timeoutError{}
+               _ Error = &DNSConfigError{}
+               _ Error = &DNSError{}
+       )
+
+       // ErrClosed was introduced as type error, so we can't check
+       // it using a declaration.
+       if _, ok := ErrClosed.(Error); !ok {
+               t.Fatal("ErrClosed does not implement Error")
+       }
+}
index 98d740ff978889344e681eb57104d5727192a74e..c12ee75ae5f2422d22240a0f5ffc274ba67e14ce 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package net
index 53cbc4d0d5992e850a0fad1d715eb33b9f9eda8d..948b8d3d50e1bfd3dd776d1d910058b4f1712cf6 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package net
index a377d333d6afe312e66d32c9c6d506baecbc9927..aeb9845fa77b8fc12828c797908910b673bfe9dc 100644 (file)
@@ -5,6 +5,7 @@
 // This file implements API tests across platforms and will never have a build
 // tag.
 
+//go:build !js
 // +build !js
 
 package net
index cdb35bb826e0edf8f4c446816002fafec05f1b77..6c230ab63fa0c7906a5c80b95f0e2443be5d139f 100644 (file)
@@ -172,32 +172,6 @@ func xtoi2(s string, e byte) (byte, bool) {
        return byte(n), ok && ei == 2
 }
 
-// Convert integer to decimal string.
-func itoa(val int) string {
-       if val < 0 {
-               return "-" + uitoa(uint(-val))
-       }
-       return uitoa(uint(val))
-}
-
-// Convert unsigned integer to decimal string.
-func uitoa(val uint) string {
-       if val == 0 { // avoid string allocation
-               return "0"
-       }
-       var buf [20]byte // big enough for 64bit value base 10
-       i := len(buf) - 1
-       for val >= 10 {
-               q := val / 10
-               buf[i] = byte('0' + val - q*10)
-               i--
-               val = q
-       }
-       // val < 10
-       buf[i] = byte('0' + val)
-       return string(buf[i:])
-}
-
 // Convert i to a hexadecimal string. Leading zeros are not printed.
 func appendHex(dst []byte, i uint32) []byte {
        if i == 0 {
index a3b402fdcd535ae84c75f77c7127845f79e839d9..07b4cbb772bc50e114ca4009bb3ad4534c430630 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris
 
 // Read system port mappings from /etc/services
index 6f83f526812f80f080d009cc55547d0d27a5150b..fc9b3862563e9a2c0cef4a76eee225eb281848dc 100644 (file)
@@ -5,6 +5,7 @@
 // This file implements API tests across platforms and will never have a build
 // tag.
 
+//go:build !js
 // +build !js
 
 package net
index cec977f75d9e2764124e7a2e5126eb91e2f0cb9a..975aa8d9569162ff52f750d58f648e0f6f77502a 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build (js && wasm) || plan9
 // +build js,wasm plan9
 
 package net
index a08ff89d1af8d9690c376e34ba3bd4bcac498670..3ef7af33b7330e307d31d61f1bf2fc330ef72369 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js
 // +build !js
 
 package net
index 21527c4c03cc893e3238d0e2b295ec5b447377d6..77df4f8d44bc1503124c07c2f33148655ab4e3cd 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package net
index 9cb928240f1c4de331eee28f3b82953ccaf68b47..074c5b9b0d7a5ecaf84aaef241cb29225a3a2ed4 100644 (file)
@@ -283,7 +283,7 @@ func suitableMethods(typ reflect.Type, reportErr bool) map[string]*methodType {
                mtype := method.Type
                mname := method.Name
                // Method must be exported.
-               if method.PkgPath != "" {
+               if !method.IsExported() {
                        continue
                }
                // Method needs three ins: receiver, *args, *reply.
index 53bc53af43b09caeb8f198acaf6294e7a1ab15f4..5753bc02898742181c55fd7979f17ef6ed2422d5 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || (js && wasm) || netbsd || openbsd
 // +build aix darwin js,wasm netbsd openbsd
 
 package net
index d6057fd83912872791a2284f8f5d026b1a17fb81..54e51fa0abc66e38a1646bd04cd443f82ef04833 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js
 // +build !js
 
 package net
@@ -13,7 +14,6 @@ import (
        "errors"
        "fmt"
        "io"
-       "io/ioutil"
        "os"
        "runtime"
        "sync"
@@ -366,7 +366,7 @@ func TestSendfileOnWriteTimeoutExceeded(t *testing.T) {
        }
        defer conn.Close()
 
-       n, err := io.Copy(ioutil.Discard, conn)
+       n, err := io.Copy(io.Discard, conn)
        if err != nil {
                t.Fatalf("expected nil error, but got %v", err)
        }
index 8cededce58d7fea97274bac397277f52c4f93b20..54667d672f87b405e2c599999664ce193fe575ff 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build dragonfly || freebsd || solaris
 // +build dragonfly freebsd solaris
 
 package net
index 4ac5443e6a130c5cb251bc799c382cbc825eaa7b..7cbf15229887155f05ac91092e3e4d079fa961bd 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js
 // +build !js
 
 package net
@@ -104,13 +105,6 @@ func TestTCPServer(t *testing.T) {
                                        if perr := parseDialError(err); perr != nil {
                                                t.Error(perr)
                                        }
-                                       if tt.taddr == "::1" && os.Getenv("GO_BUILDER_NAME") == "darwin-amd64-10_12" && os.IsTimeout(err) {
-                                               // A suspected kernel bug in macOS 10.12 occasionally results in
-                                               // "i/o timeout" errors when dialing address ::1. The errors have not
-                                               // been observed on newer versions of the OS, so we don't plan to work
-                                               // around them. See https://golang.org/issue/32919.
-                                               t.Skipf("skipping due to error on known-flaky macOS 10.12 builder: %v", err)
-                                       }
                                        t.Fatal(err)
                                }
                                defer c.Close()
index 73fb6be814eb8acfcdf20599a516703fae9d2ea7..4c883ada78f91ef2d9dcd16e9641d664ce6125d4 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || netbsd || openbsd
 // +build darwin dragonfly freebsd netbsd openbsd
 
 package net
index 43be6ff9b651e5b6f519d0b021e6398a7f710624..cb57bb4d8be7d0e70529b3351ea9cf3156fa0221 100644 (file)
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This file implements sysSocket and accept for platforms that
-// provide a fast path for setting SetNonblock and CloseOnExec.
+// This file implements sysSocket for platforms that provide a fast path for
+// setting SetNonblock and CloseOnExec.
 
+//go:build dragonfly || freebsd || hurd || illumos || linux || netbsd || openbsd
 // +build dragonfly freebsd hurd illumos linux netbsd openbsd
 
 package net
index 8fe9bc74871ff4ef8add77a31bf7160bb0bb888a..8c09b0bf3ce0e809a946109a5ab00f614dd41fe6 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris || windows
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris windows
 
 package net
index 6d44f43b898973dd94f4a4b2e3fc749c040b3054..1e5032e8c92f3b1eb2cafd9f1d632e0c1c9ad4c5 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || hurd || (js && wasm) || solaris
 // +build aix hurd js,wasm solaris
 
 package net
index 470d04444da037518ff0ab3cf517b0864243de9a..618d85f8530cd1f3b5292c3736412049f5fbed58 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows
 
 package net
index 7b8b8d9654cd7872481ec8abc455c6b4a2f13821..e52fa886394472ff944613ffbc46ad85f6f7000d 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || netbsd || openbsd
 // +build darwin dragonfly freebsd netbsd openbsd
 
 package net
@@ -25,7 +26,7 @@ func setDefaultSockopts(s, family, sotype int, ipv6only bool) error {
                        syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_PORTRANGE, syscall.IPV6_PORTRANGE_HIGH)
                }
        }
-       if supportsIPv4map() && family == syscall.AF_INET6 && sotype != syscall.SOCK_RAW {
+       if family == syscall.AF_INET6 && sotype != syscall.SOCK_RAW && supportsIPv4map() {
                // Allow both IP versions even if the OS default
                // is otherwise. Note that some operating systems
                // never admit this option.
index d2cb30b527aeb6136db5e232a55a5df638b85189..34788723920fcca2a59b01d9c497ec245f53c477 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris || windows
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris windows
 
 package net
index 52624a35d81b891c40547f7eef4c4e731f4a579a..99b5277ed0a874c098ed936633f44d8dc4cad436 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build js && wasm
 // +build js,wasm
 
 package net
index c93f59245e78cbfe5eb13145f1d024e2730aeff3..8b0b5d2c342bde5669dfeccb06230889b9bf2bee 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd netbsd openbsd solaris
 
 package net
index 0ac50e322e33b60c2751dd726cda189f0b49113f..a063e79d1065403d16018b429bb9be1a212ecad5 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris || windows
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris windows
 
 package net
index 57cd2890405c04c552897fed2779f4b2a637fcb7..4175922cec5f6f7d013626c3a28a928d979a2d7f 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build js && wasm
 // +build js,wasm
 
 package net
index 9106cb2c18c6844beb25f4bc4bbffadd0ba78182..ce2e9046a9440f9506c808fdb9934bc42ffd2944 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !linux
 // +build !linux
 
 package net
index cd4e01fc845e87338de3b3f4136723a845bc23b4..d5f6367cf5c3c3e4284082c6e746504e13007fbe 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build linux
 // +build linux
 
 package net
index 967b8bea9dd805f95250de4d84ed0ba4da16c8f9..a32483e2df94e4101948501042aba46ef7790394 100644 (file)
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This file implements sysSocket and accept for platforms that do not
-// provide a fast path for setting SetNonblock and CloseOnExec.
+// This file implements sysSocket for platforms that do not provide a fast path
+// for setting SetNonblock and CloseOnExec.
 
+//go:build aix || darwin || (solaris && !illumos)
 // +build aix darwin solaris,!illumos
 
 package net
index 9a9b03a1e89069920bc6bd174e0331fd48013bb2..19a90143f34861be7efc3ddb6de3a102bef59391 100644 (file)
@@ -6,6 +6,7 @@ package net
 
 import (
        "context"
+       "internal/itoa"
        "io"
        "os"
        "syscall"
@@ -31,9 +32,9 @@ func (a *TCPAddr) String() string {
        }
        ip := ipEmptyString(a.IP)
        if a.Zone != "" {
-               return JoinHostPort(ip+"%"+a.Zone, itoa(a.Port))
+               return JoinHostPort(ip+"%"+a.Zone, itoa.Itoa(a.Port))
        }
-       return JoinHostPort(ip, itoa(a.Port))
+       return JoinHostPort(ip, itoa.Itoa(a.Port))
 }
 
 func (a *TCPAddr) isWildcard() bool {
index 2c359da3980328a904e2aca342bedcb60988f284..9fd7822709c0f171812b030ae0a3246adf576697 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows
 
 package net
index c220c0bd8411500f14718615bd0d7deb664b9c72..884c5cbec8b1710c92876fa46905cfae5624ad32 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js
 // +build !js
 
 package net
index 2bd591b5944f227b841dd609477bb1026d7b7dd5..41bd229132d912883a18aefb1b24b6b56d2e59a2 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js && !plan9 && !windows
 // +build !js,!plan9,!windows
 
 package net
index fb568718573a6255372bc02205df645585a053b3..264359dcf3daf15bd14c8d82eadafeffcf566dbb 100644 (file)
@@ -7,6 +7,7 @@
 package net
 
 import (
+       "internal/itoa"
        "syscall"
        "time"
 )
@@ -17,7 +18,7 @@ func setNoDelay(fd *netFD, noDelay bool) error {
 
 // Set keep alive period.
 func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
-       cmd := "keepalive " + itoa(int(d/time.Millisecond))
+       cmd := "keepalive " + itoa.Itoa(int(d/time.Millisecond))
        _, e := fd.ctl.WriteAt([]byte(cmd), 0)
        return e
 }
index 01bc421975605dde2e114abeecffe0bb3bee2c43..4c99ab8bf26eea2b4f348282dc4e90a665da3b7c 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris || windows
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris windows
 
 package net
index d043da123d6e81a78e6afe7ca51753ff46365c8c..028d5fd29cff8ebda730b1e9eb7bf46c72fd2430 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build js && wasm
 // +build js,wasm
 
 package net
index e05cb73783d5fffe151fa256e30bbe9663e2bf13..cc0662ad7ccf576eb4fb1811c03eb44b2dbba122 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || freebsd || hurd || linux || netbsd
 // +build aix freebsd hurd linux netbsd
 
 package net
index 5208bb44ac863dd418b429a54903d8c802fb05e4..6b99675dfc884cda1dc312663ccfdd9423b8659b 100644 (file)
@@ -1,12 +1,8 @@
 # See https://tools.ietf.org/html/rfc1123.
-#
-# The literal IPv4 address parser in the net package is a relaxed
-# one. It may accept a literal IPv4 address in dotted-decimal notation
-# with leading zeros such as "001.2.003.4".
 
 # internet address and host name
 127.0.0.1      localhost       # inline comment separated by tab
-127.000.000.002        localhost       # inline comment separated by space
+127.0.0.2      localhost   # inline comment separated by space
 
 # internet address, host name and aliases
-127.000.000.003        localhost       localhost.localdomain
+127.0.0.3      localhost       localhost.localdomain
index 205aaa430ba812a885ac531fa1dc19d0adea7448..e1cf1467c36f00aca3bf254d9c0676a91398a173 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js
 // +build !js
 
 package net
index 571e099abd81c0e60fa5e51a1f79afe90a085b86..70f2ce226aa7b149471b23432baf1d7fae3e62ea 100644 (file)
@@ -6,6 +6,7 @@ package net
 
 import (
        "context"
+       "internal/itoa"
        "syscall"
 )
 
@@ -34,9 +35,9 @@ func (a *UDPAddr) String() string {
        }
        ip := ipEmptyString(a.IP)
        if a.Zone != "" {
-               return JoinHostPort(ip+"%"+a.Zone, itoa(a.Port))
+               return JoinHostPort(ip+"%"+a.Zone, itoa.Itoa(a.Port))
        }
-       return JoinHostPort(ip, itoa(a.Port))
+       return JoinHostPort(ip, itoa.Itoa(a.Port))
 }
 
 func (a *UDPAddr) isWildcard() bool {
@@ -99,11 +100,20 @@ func (c *UDPConn) SyscallConn() (syscall.RawConn, error) {
 }
 
 // ReadFromUDP acts like ReadFrom but returns a UDPAddr.
-func (c *UDPConn) ReadFromUDP(b []byte) (int, *UDPAddr, error) {
+func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) {
+       // This function is designed to allow the caller to control the lifetime
+       // of the returned *UDPAddr and thereby prevent an allocation.
+       // See https://blog.filippo.io/efficient-go-apis-with-the-inliner/.
+       // The real work is done by readFromUDP, below.
+       return c.readFromUDP(b, &UDPAddr{})
+}
+
+// readFromUDP implements ReadFromUDP.
+func (c *UDPConn) readFromUDP(b []byte, addr *UDPAddr) (int, *UDPAddr, error) {
        if !c.ok() {
                return 0, nil, syscall.EINVAL
        }
-       n, addr, err := c.readFrom(b)
+       n, addr, err := c.readFrom(b, addr)
        if err != nil {
                err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
        }
@@ -112,14 +122,9 @@ func (c *UDPConn) ReadFromUDP(b []byte) (int, *UDPAddr, error) {
 
 // ReadFrom implements the PacketConn ReadFrom method.
 func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) {
-       if !c.ok() {
-               return 0, nil, syscall.EINVAL
-       }
-       n, addr, err := c.readFrom(b)
-       if err != nil {
-               err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
-       }
+       n, addr, err := c.readFromUDP(b, &UDPAddr{})
        if addr == nil {
+               // Return Addr(nil), not Addr(*UDPConn(nil)).
                return n, nil, err
        }
        return n, addr, err
index 79986ce4da2891beeef3624a1f6e9a24fb15dffa..1df293d1db93525d91938d8e5b291142ce9c3a6f 100644 (file)
@@ -11,7 +11,7 @@ import (
        "syscall"
 )
 
-func (c *UDPConn) readFrom(b []byte) (n int, addr *UDPAddr, err error) {
+func (c *UDPConn) readFrom(b []byte, addr *UDPAddr) (int, *UDPAddr, error) {
        buf := make([]byte, udpHeaderSize+len(b))
        m, err := c.fd.Read(buf)
        if err != nil {
@@ -23,8 +23,9 @@ func (c *UDPConn) readFrom(b []byte) (n int, addr *UDPAddr, err error) {
        buf = buf[:m]
 
        h, buf := unmarshalUDPHeader(buf)
-       n = copy(b, buf)
-       return n, &UDPAddr{IP: h.raddr, Port: int(h.rport)}, nil
+       n := copy(b, buf)
+       *addr = UDPAddr{IP: h.raddr, Port: int(h.rport)}
+       return n, addr, nil
 }
 
 func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) {
index 858a3efe2f955a7e69745f08dce34562847d59e3..a4c6da293b24c0f4390df73845eb361260ac2e78 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows
 
 package net
@@ -42,21 +43,23 @@ func (a *UDPAddr) toLocal(net string) sockaddr {
        return &UDPAddr{loopbackIP(net), a.Port, a.Zone}
 }
 
-func (c *UDPConn) readFrom(b []byte) (int, *UDPAddr, error) {
-       var addr *UDPAddr
+func (c *UDPConn) readFrom(b []byte, addr *UDPAddr) (int, *UDPAddr, error) {
        n, sa, err := c.fd.readFrom(b)
        switch sa := sa.(type) {
        case *syscall.SockaddrInet4:
-               addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
+               *addr = UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
        case *syscall.SockaddrInet6:
-               addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneCache.name(int(sa.ZoneId))}
+               *addr = UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneCache.name(int(sa.ZoneId))}
+       default:
+               // No sockaddr, so don't return UDPAddr.
+               addr = nil
        }
        return n, addr, err
 }
 
 func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) {
        var sa syscall.Sockaddr
-       n, oobn, flags, sa, err = c.fd.readMsg(b, oob)
+       n, oobn, flags, sa, err = c.fd.readMsg(b, oob, 0)
        switch sa := sa.(type) {
        case *syscall.SockaddrInet4:
                addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
index 327eba65412d9b9770da9b40330264bfa8d38eb4..0e8c3511c36e459258d617d7217b81d1b8ed6a3c 100644 (file)
@@ -2,12 +2,15 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js
 // +build !js
 
 package net
 
 import (
+       "errors"
        "internal/testenv"
+       "os"
        "reflect"
        "runtime"
        "testing"
@@ -444,3 +447,51 @@ func TestUDPReadSizeError(t *testing.T) {
                }
        }
 }
+
+// TestUDPReadTimeout verifies that ReadFromUDP with timeout returns an error
+// without data or an address.
+func TestUDPReadTimeout(t *testing.T) {
+       la, err := ResolveUDPAddr("udp4", "127.0.0.1:0")
+       if err != nil {
+               t.Fatal(err)
+       }
+       c, err := ListenUDP("udp4", la)
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer c.Close()
+
+       c.SetDeadline(time.Now())
+       b := make([]byte, 1)
+       n, addr, err := c.ReadFromUDP(b)
+       if !errors.Is(err, os.ErrDeadlineExceeded) {
+               t.Errorf("ReadFromUDP got err %v want os.ErrDeadlineExceeded", err)
+       }
+       if n != 0 {
+               t.Errorf("ReadFromUDP got n %d want 0", n)
+       }
+       if addr != nil {
+               t.Errorf("ReadFromUDP got addr %+#v want nil", addr)
+       }
+}
+
+func BenchmarkWriteToReadFromUDP(b *testing.B) {
+       conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)})
+       if err != nil {
+               b.Fatal(err)
+       }
+       addr := conn.LocalAddr()
+       buf := make([]byte, 8)
+       b.ResetTimer()
+       b.ReportAllocs()
+       for i := 0; i < b.N; i++ {
+               _, err := conn.WriteTo(buf, addr)
+               if err != nil {
+                       b.Fatal(err)
+               }
+               _, _, err = conn.ReadFromUDP(buf)
+               if err != nil {
+                       b.Fatal(err)
+               }
+       }
+}
index 37214854dac8941cefca2c83312eff92a00555cc..af075af2034485bb32d916434f31e687717535cf 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows
 
 package net
@@ -112,7 +113,11 @@ func (c *UnixConn) readFrom(b []byte) (int, *UnixAddr, error) {
 
 func (c *UnixConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) {
        var sa syscall.Sockaddr
-       n, oobn, flags, sa, err = c.fd.readMsg(b, oob)
+       n, oobn, flags, sa, err = c.fd.readMsg(b, oob, readMsgFlags)
+       if readMsgFlags == 0 && err == nil && oobn > 0 {
+               setReadMsgCloseOnExec(oob[:oobn])
+       }
+
        switch sa := sa.(type) {
        case *syscall.SockaddrUnix:
                if sa.Name != "" {
diff --git a/libgo/go/net/unixsock_readmsg_cloexec.go b/libgo/go/net/unixsock_readmsg_cloexec.go
new file mode 100644 (file)
index 0000000..716484c
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build aix || darwin || freebsd || solaris
+// +build aix darwin freebsd solaris
+
+package net
+
+import "syscall"
+
+const readMsgFlags = 0
+
+func setReadMsgCloseOnExec(oob []byte) {
+       scms, err := syscall.ParseSocketControlMessage(oob)
+       if err != nil {
+               return
+       }
+
+       for _, scm := range scms {
+               if scm.Header.Level == syscall.SOL_SOCKET && scm.Header.Type == syscall.SCM_RIGHTS {
+                       fds, err := syscall.ParseUnixRights(&scm)
+                       if err != nil {
+                               continue
+                       }
+                       for _, fd := range fds {
+                               syscall.CloseOnExec(fd)
+                       }
+               }
+       }
+}
diff --git a/libgo/go/net/unixsock_readmsg_cmsg_cloexec.go b/libgo/go/net/unixsock_readmsg_cmsg_cloexec.go
new file mode 100644 (file)
index 0000000..bb851b8
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build dragonfly || linux || netbsd || openbsd
+// +build dragonfly linux netbsd openbsd
+
+package net
+
+import "syscall"
+
+const readMsgFlags = syscall.MSG_CMSG_CLOEXEC
+
+func setReadMsgCloseOnExec(oob []byte) {}
diff --git a/libgo/go/net/unixsock_readmsg_other.go b/libgo/go/net/unixsock_readmsg_other.go
new file mode 100644 (file)
index 0000000..3290761
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build (js && wasm) || windows
+// +build js,wasm windows
+
+package net
+
+const readMsgFlags = 0
+
+func setReadMsgCloseOnExec(oob []byte) {}
diff --git a/libgo/go/net/unixsock_readmsg_test.go b/libgo/go/net/unixsock_readmsg_test.go
new file mode 100644 (file)
index 0000000..a4d2fca
--- /dev/null
@@ -0,0 +1,105 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
+// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package net
+
+import (
+       "os"
+       "syscall"
+       "testing"
+       "time"
+)
+
+func TestUnixConnReadMsgUnixSCMRightsCloseOnExec(t *testing.T) {
+       if !testableNetwork("unix") {
+               t.Skip("not unix system")
+       }
+
+       scmFile, err := os.Open(os.DevNull)
+       if err != nil {
+               t.Fatalf("file open: %v", err)
+       }
+       defer scmFile.Close()
+
+       rights := syscall.UnixRights(int(scmFile.Fd()))
+       fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM, 0)
+       if err != nil {
+               t.Fatalf("Socketpair: %v", err)
+       }
+
+       writeFile := os.NewFile(uintptr(fds[0]), "write-socket")
+       defer writeFile.Close()
+       readFile := os.NewFile(uintptr(fds[1]), "read-socket")
+       defer readFile.Close()
+
+       cw, err := FileConn(writeFile)
+       if err != nil {
+               t.Fatalf("FileConn: %v", err)
+       }
+       defer cw.Close()
+       cr, err := FileConn(readFile)
+       if err != nil {
+               t.Fatalf("FileConn: %v", err)
+       }
+       defer cr.Close()
+
+       ucw, ok := cw.(*UnixConn)
+       if !ok {
+               t.Fatalf("got %T; want UnixConn", cw)
+       }
+       ucr, ok := cr.(*UnixConn)
+       if !ok {
+               t.Fatalf("got %T; want UnixConn", cr)
+       }
+
+       oob := make([]byte, syscall.CmsgSpace(4))
+       err = ucw.SetWriteDeadline(time.Now().Add(5 * time.Second))
+       if err != nil {
+               t.Fatalf("Can't set unix connection timeout: %v", err)
+       }
+       _, _, err = ucw.WriteMsgUnix(nil, rights, nil)
+       if err != nil {
+               t.Fatalf("UnixConn readMsg: %v", err)
+       }
+       err = ucr.SetReadDeadline(time.Now().Add(5 * time.Second))
+       if err != nil {
+               t.Fatalf("Can't set unix connection timeout: %v", err)
+       }
+       _, oobn, _, _, err := ucr.ReadMsgUnix(nil, oob)
+       if err != nil {
+               t.Fatalf("UnixConn readMsg: %v", err)
+       }
+
+       scms, err := syscall.ParseSocketControlMessage(oob[:oobn])
+       if err != nil {
+               t.Fatalf("ParseSocketControlMessage: %v", err)
+       }
+       if len(scms) != 1 {
+               t.Fatalf("got scms = %#v; expected 1 SocketControlMessage", scms)
+       }
+       scm := scms[0]
+       gotFDs, err := syscall.ParseUnixRights(&scm)
+       if err != nil {
+               t.Fatalf("syscall.ParseUnixRights: %v", err)
+       }
+       if len(gotFDs) != 1 {
+               t.Fatalf("got FDs %#v: wanted only 1 fd", gotFDs)
+       }
+       defer func() {
+               if err := syscall.Close(gotFDs[0]); err != nil {
+                       t.Fatalf("fail to close gotFDs: %v", err)
+               }
+       }()
+
+       flags, err := fcntl(gotFDs[0], syscall.F_GETFD, 0)
+       if err != nil {
+               t.Fatalf("Can't get flags of fd:%#v, with err:%v", gotFDs[0], err)
+       }
+       if flags&syscall.FD_CLOEXEC == 0 {
+               t.Fatalf("got flags %#x, want %#x (FD_CLOEXEC) set", flags, syscall.FD_CLOEXEC)
+       }
+}
index 0b13bf655f3de092e58ac1b1059c778a8e894b67..71092e88fb600f98f0b1f642d7e121475d0985f6 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js && !plan9 && !windows
 // +build !js,!plan9,!windows
 
 package net
index 5dccc1465334ce2e4cd2cf092c2b0ceada6aae2f..29244f64710337f97c79068fe0c965da2d388211 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build windows
 // +build windows
 
 package net
index d90f5f06b548b03baccd81256ec614817a728a24..20de0f6f5178a1e9f4cb39ab7352973d44732bdf 100644 (file)
@@ -425,31 +425,31 @@ func (u *Userinfo) String() string {
        return s
 }
 
-// Maybe rawurl is of the form scheme:path.
+// Maybe rawURL is of the form scheme:path.
 // (Scheme must be [a-zA-Z][a-zA-Z0-9+-.]*)
-// If so, return scheme, path; else return "", rawurl.
-func getscheme(rawurl string) (scheme, path string, err error) {
-       for i := 0; i < len(rawurl); i++ {
-               c := rawurl[i]
+// If so, return scheme, path; else return "", rawURL.
+func getScheme(rawURL string) (scheme, path string, err error) {
+       for i := 0; i < len(rawURL); i++ {
+               c := rawURL[i]
                switch {
                case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z':
                // do nothing
                case '0' <= c && c <= '9' || c == '+' || c == '-' || c == '.':
                        if i == 0 {
-                               return "", rawurl, nil
+                               return "", rawURL, nil
                        }
                case c == ':':
                        if i == 0 {
                                return "", "", errors.New("missing protocol scheme")
                        }
-                       return rawurl[:i], rawurl[i+1:], nil
+                       return rawURL[:i], rawURL[i+1:], nil
                default:
                        // we have encountered an invalid character,
                        // so there is no valid scheme
-                       return "", rawurl, nil
+                       return "", rawURL, nil
                }
        }
-       return "", rawurl, nil
+       return "", rawURL, nil
 }
 
 // split slices s into two substrings separated by the first occurrence of
@@ -466,15 +466,15 @@ func split(s string, sep byte, cutc bool) (string, string) {
        return s[:i], s[i:]
 }
 
-// Parse parses rawurl into a URL structure.
+// Parse parses a raw url into a URL structure.
 //
-// The rawurl may be relative (a path, without a host) or absolute
+// The url may be relative (a path, without a host) or absolute
 // (starting with a scheme). Trying to parse a hostname and path
 // without a scheme is invalid but may not necessarily return an
 // error, due to parsing ambiguities.
-func Parse(rawurl string) (*URL, error) {
+func Parse(rawURL string) (*URL, error) {
        // Cut off #frag
-       u, frag := split(rawurl, '#', true)
+       u, frag := split(rawURL, '#', true)
        url, err := parse(u, false)
        if err != nil {
                return nil, &Error{"parse", u, err}
@@ -483,20 +483,20 @@ func Parse(rawurl string) (*URL, error) {
                return url, nil
        }
        if err = url.setFragment(frag); err != nil {
-               return nil, &Error{"parse", rawurl, err}
+               return nil, &Error{"parse", rawURL, err}
        }
        return url, nil
 }
 
-// ParseRequestURI parses rawurl into a URL structure. It assumes that
-// rawurl was received in an HTTP request, so the rawurl is interpreted
+// ParseRequestURI parses a raw url into a URL structure. It assumes that
+// url was received in an HTTP request, so the url is interpreted
 // only as an absolute URI or an absolute path.
-// The string rawurl is assumed not to have a #fragment suffix.
+// The string url is assumed not to have a #fragment suffix.
 // (Web browsers strip #fragment before sending the URL to a web server.)
-func ParseRequestURI(rawurl string) (*URL, error) {
-       url, err := parse(rawurl, true)
+func ParseRequestURI(rawURL string) (*URL, error) {
+       url, err := parse(rawURL, true)
        if err != nil {
-               return nil, &Error{"parse", rawurl, err}
+               return nil, &Error{"parse", rawURL, err}
        }
        return url, nil
 }
@@ -505,27 +505,27 @@ func ParseRequestURI(rawurl string) (*URL, error) {
 // viaRequest is true, the URL is assumed to have arrived via an HTTP request,
 // in which case only absolute URLs or path-absolute relative URLs are allowed.
 // If viaRequest is false, all forms of relative URLs are allowed.
-func parse(rawurl string, viaRequest bool) (*URL, error) {
+func parse(rawURL string, viaRequest bool) (*URL, error) {
        var rest string
        var err error
 
-       if stringContainsCTLByte(rawurl) {
+       if stringContainsCTLByte(rawURL) {
                return nil, errors.New("net/url: invalid control character in URL")
        }
 
-       if rawurl == "" && viaRequest {
+       if rawURL == "" && viaRequest {
                return nil, errors.New("empty url")
        }
        url := new(URL)
 
-       if rawurl == "*" {
+       if rawURL == "*" {
                url.Path = "*"
                return url, nil
        }
 
        // Split off possible leading "http:", "mailto:", etc.
        // Cannot contain escaped characters.
-       if url.Scheme, rest, err = getscheme(rawurl); err != nil {
+       if url.Scheme, rest, err = getScheme(rawURL); err != nil {
                return nil, err
        }
        url.Scheme = strings.ToLower(url.Scheme)
@@ -909,15 +909,22 @@ func (v Values) Del(key string) {
        delete(v, key)
 }
 
+// Has checks whether a given key is set.
+func (v Values) Has(key string) bool {
+       _, ok := v[key]
+       return ok
+}
+
 // ParseQuery parses the URL-encoded query string and returns
 // a map listing the values specified for each key.
 // ParseQuery always returns a non-nil map containing all the
 // valid query parameters found; err describes the first decoding error
 // encountered, if any.
 //
-// Query is expected to be a list of key=value settings separated by
-// ampersands or semicolons. A setting without an equals sign is
-// interpreted as a key set to an empty value.
+// Query is expected to be a list of key=value settings separated by ampersands.
+// A setting without an equals sign is interpreted as a key set to an empty
+// value.
+// Settings containing a non-URL-encoded semicolon are considered invalid.
 func ParseQuery(query string) (Values, error) {
        m := make(Values)
        err := parseQuery(m, query)
@@ -927,11 +934,15 @@ func ParseQuery(query string) (Values, error) {
 func parseQuery(m Values, query string) (err error) {
        for query != "" {
                key := query
-               if i := strings.IndexAny(key, "&;"); i >= 0 {
+               if i := strings.IndexAny(key, "&"); i >= 0 {
                        key, query = key[:i], key[i+1:]
                } else {
                        query = ""
                }
+               if strings.Contains(key, ";") {
+                       err = fmt.Errorf("invalid semicolon separator in query")
+                       continue
+               }
                if key == "" {
                        continue
                }
@@ -1009,6 +1020,8 @@ func resolvePath(base, ref string) string {
        )
        first := true
        remaining := full
+       // We want to return a leading '/', so write it now.
+       dst.WriteByte('/')
        for i >= 0 {
                i = strings.IndexByte(remaining, '/')
                if i < 0 {
@@ -1023,10 +1036,12 @@ func resolvePath(base, ref string) string {
                }
 
                if elem == ".." {
-                       str := dst.String()
+                       // Ignore the leading '/' we already wrote.
+                       str := dst.String()[1:]
                        index := strings.LastIndexByte(str, '/')
 
                        dst.Reset()
+                       dst.WriteByte('/')
                        if index == -1 {
                                first = true
                        } else {
@@ -1045,7 +1060,12 @@ func resolvePath(base, ref string) string {
                dst.WriteByte('/')
        }
 
-       return "/" + strings.TrimPrefix(dst.String(), "/")
+       // We wrote an initial '/', but we don't want two.
+       r := dst.String()
+       if len(r) > 1 && r[1] == '/' {
+               r = r[1:]
+       }
+       return r
 }
 
 // IsAbs reports whether the URL is absolute.
@@ -1058,11 +1078,11 @@ func (u *URL) IsAbs() bool {
 // may be relative or absolute. Parse returns nil, err on parse
 // failure, otherwise its return value is the same as ResolveReference.
 func (u *URL) Parse(ref string) (*URL, error) {
-       refurl, err := Parse(ref)
+       refURL, err := Parse(ref)
        if err != nil {
                return nil, err
        }
-       return u.ResolveReference(refurl), nil
+       return u.ResolveReference(refURL), nil
 }
 
 // ResolveReference resolves a URI reference to an absolute URI from
@@ -1151,8 +1171,8 @@ func (u *URL) Port() string {
 // splitHostPort separates host and port. If the port is not valid, it returns
 // the entire input as host, and it doesn't check the validity of the host.
 // Unlike net.SplitHostPort, but per RFC 3986, it requires ports to be numeric.
-func splitHostPort(hostport string) (host, port string) {
-       host = hostport
+func splitHostPort(hostPort string) (host, port string) {
+       host = hostPort
 
        colon := strings.LastIndexByte(host, ':')
        if colon != -1 && validOptionalPort(host[colon:]) {
index f02e4650d87ecf3c216684646c5066ced1ef8503..63c8e695af765050f5bfa0c1db616d0cf905a7f9 100644 (file)
@@ -1295,10 +1295,10 @@ func TestResolveReference(t *testing.T) {
 }
 
 func TestQueryValues(t *testing.T) {
-       u, _ := Parse("http://x.com?foo=bar&bar=1&bar=2")
+       u, _ := Parse("http://x.com?foo=bar&bar=1&bar=2&baz")
        v := u.Query()
-       if len(v) != 2 {
-               t.Errorf("got %d keys in Query values, want 2", len(v))
+       if len(v) != 3 {
+               t.Errorf("got %d keys in Query values, want 3", len(v))
        }
        if g, e := v.Get("foo"), "bar"; g != e {
                t.Errorf("Get(foo) = %q, want %q", g, e)
@@ -1313,6 +1313,18 @@ func TestQueryValues(t *testing.T) {
        if g, e := v.Get("baz"), ""; g != e {
                t.Errorf("Get(baz) = %q, want %q", g, e)
        }
+       if h, e := v.Has("foo"), true; h != e {
+               t.Errorf("Has(foo) = %t, want %t", h, e)
+       }
+       if h, e := v.Has("bar"), true; h != e {
+               t.Errorf("Has(bar) = %t, want %t", h, e)
+       }
+       if h, e := v.Has("baz"), true; h != e {
+               t.Errorf("Has(baz) = %t, want %t", h, e)
+       }
+       if h, e := v.Has("noexist"), false; h != e {
+               t.Errorf("Has(noexist) = %t, want %t", h, e)
+       }
        v.Del("bar")
        if g, e := v.Get("bar"), ""; g != e {
                t.Errorf("second Get(bar) = %q, want %q", g, e)
@@ -1322,57 +1334,125 @@ func TestQueryValues(t *testing.T) {
 type parseTest struct {
        query string
        out   Values
+       ok    bool
 }
 
 var parseTests = []parseTest{
+       {
+               query: "a=1",
+               out:   Values{"a": []string{"1"}},
+               ok:    true,
+       },
        {
                query: "a=1&b=2",
                out:   Values{"a": []string{"1"}, "b": []string{"2"}},
+               ok:    true,
        },
        {
                query: "a=1&a=2&a=banana",
                out:   Values{"a": []string{"1", "2", "banana"}},
+               ok:    true,
        },
        {
                query: "ascii=%3Ckey%3A+0x90%3E",
                out:   Values{"ascii": []string{"<key: 0x90>"}},
+               ok:    true,
+       }, {
+               query: "a=1;b=2",
+               out:   Values{},
+               ok:    false,
+       }, {
+               query: "a;b=1",
+               out:   Values{},
+               ok:    false,
+       }, {
+               query: "a=%3B", // hex encoding for semicolon
+               out:   Values{"a": []string{";"}},
+               ok:    true,
        },
        {
-               query: "a=1;b=2",
-               out:   Values{"a": []string{"1"}, "b": []string{"2"}},
+               query: "a%3Bb=1",
+               out:   Values{"a;b": []string{"1"}},
+               ok:    true,
        },
        {
                query: "a=1&a=2;a=banana",
-               out:   Values{"a": []string{"1", "2", "banana"}},
+               out:   Values{"a": []string{"1"}},
+               ok:    false,
+       },
+       {
+               query: "a;b&c=1",
+               out:   Values{"c": []string{"1"}},
+               ok:    false,
+       },
+       {
+               query: "a=1&b=2;a=3&c=4",
+               out:   Values{"a": []string{"1"}, "c": []string{"4"}},
+               ok:    false,
+       },
+       {
+               query: "a=1&b=2;c=3",
+               out:   Values{"a": []string{"1"}},
+               ok:    false,
+       },
+       {
+               query: ";",
+               out:   Values{},
+               ok:    false,
+       },
+       {
+               query: "a=1;",
+               out:   Values{},
+               ok:    false,
+       },
+       {
+               query: "a=1&;",
+               out:   Values{"a": []string{"1"}},
+               ok:    false,
+       },
+       {
+               query: ";a=1&b=2",
+               out:   Values{"b": []string{"2"}},
+               ok:    false,
+       },
+       {
+               query: "a=1&b=2;",
+               out:   Values{"a": []string{"1"}},
+               ok:    false,
        },
 }
 
 func TestParseQuery(t *testing.T) {
-       for i, test := range parseTests {
-               form, err := ParseQuery(test.query)
-               if err != nil {
-                       t.Errorf("test %d: Unexpected error: %v", i, err)
-                       continue
-               }
-               if len(form) != len(test.out) {
-                       t.Errorf("test %d: len(form) = %d, want %d", i, len(form), len(test.out))
-               }
-               for k, evs := range test.out {
-                       vs, ok := form[k]
-                       if !ok {
-                               t.Errorf("test %d: Missing key %q", i, k)
-                               continue
+       for _, test := range parseTests {
+               t.Run(test.query, func(t *testing.T) {
+                       form, err := ParseQuery(test.query)
+                       if test.ok != (err == nil) {
+                               want := "<error>"
+                               if test.ok {
+                                       want = "<nil>"
+                               }
+                               t.Errorf("Unexpected error: %v, want %v", err, want)
                        }
-                       if len(vs) != len(evs) {
-                               t.Errorf("test %d: len(form[%q]) = %d, want %d", i, k, len(vs), len(evs))
-                               continue
+                       if len(form) != len(test.out) {
+                               t.Errorf("len(form) = %d, want %d", len(form), len(test.out))
                        }
-                       for j, ev := range evs {
-                               if v := vs[j]; v != ev {
-                                       t.Errorf("test %d: form[%q][%d] = %q, want %q", i, k, j, v, ev)
+                       for k, evs := range test.out {
+                               vs, ok := form[k]
+                               if !ok {
+                                       t.Errorf("Missing key %q", k)
+                                       continue
+                               }
+                               if len(vs) != len(evs) {
+                                       t.Errorf("len(form[%q]) = %d, want %d", k, len(vs), len(evs))
+                                       continue
+                               }
+                               for j, ev := range evs {
+                                       if v := vs[j]; v != ev {
+                                               t.Errorf("form[%q][%d] = %q, want %q", k, j, v, ev)
+                                       }
                                }
                        }
-               }
+               })
        }
 }
 
index 6d8cb6a6f81666443e4fba43484573401f519e68..f79f2d0865d559ebb358430d32956ea65e95d858 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
 // +build darwin dragonfly freebsd linux netbsd openbsd solaris
 
 package net
index d603b7f70a660917441c440306d0da227edae3b4..bf40ca2023ac9e52902bf8514194a8c2852db0d1 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js
 // +build !js
 
 package net
index 8b20f42b34de630c36c1f88c53ee1845cbd84bbb..a0fedc2f99061df9424f712d55be2d65ec4c4bf9 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || illumos || linux || netbsd || openbsd
 // +build darwin dragonfly freebsd illumos linux netbsd openbsd
 
 package net
index fd21ddd3848d49767f09b0dafa6bfd973758ceee..0336323e8b6e730878405be56c232ac7d318d012 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package os_test
index 704a6fb29e3e68b1863efecf6bcf755b054756f0..fe8f2a84466697c981465e22ca62ad4e1ac41534 100644 (file)
@@ -78,7 +78,7 @@ func NewSyscallError(syscall string, err error) error {
 // well as some syscall errors.
 //
 // This function predates errors.Is. It only supports errors returned by
-// the os package. New code should use errors.Is(err, os.ErrExist).
+// the os package. New code should use errors.Is(err, fs.ErrExist).
 func IsExist(err error) bool {
        return underlyingErrorIs(err, ErrExist)
 }
@@ -88,7 +88,7 @@ func IsExist(err error) bool {
 // ErrNotExist as well as some syscall errors.
 //
 // This function predates errors.Is. It only supports errors returned by
-// the os package. New code should use errors.Is(err, os.ErrNotExist).
+// the os package. New code should use errors.Is(err, fs.ErrNotExist).
 func IsNotExist(err error) bool {
        return underlyingErrorIs(err, ErrNotExist)
 }
@@ -98,7 +98,7 @@ func IsNotExist(err error) bool {
 // as some syscall errors.
 //
 // This function predates errors.Is. It only supports errors returned by
-// the os package. New code should use errors.Is(err, os.ErrPermission).
+// the os package. New code should use errors.Is(err, fs.ErrPermission).
 func IsPermission(err error) bool {
        return underlyingErrorIs(err, ErrPermission)
 }
index 31ae05a21e8dce4b7d7fdac5bb520c730b717f10..580e915b73c3db1cf7a33005b143fee58f9ba62e 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !plan9
 // +build !plan9
 
 package os
index 7d5a19caa56518ce15d7c606f74196b5fed60b23..7a7c8609e272375284044f79598582fdd3a6818d 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows
 
 package os
index 6264ccc96679a6f7a267c00bb188add2459e981b..4ab6246d2ecafc466222f68d61e3eef56a188d9a 100644 (file)
@@ -33,7 +33,12 @@ func TestErrIsExist(t *testing.T) {
        }
 }
 
-func testErrNotExist(name string) string {
+func testErrNotExist(t *testing.T, name string) string {
+       originalWD, err := os.Getwd()
+       if err != nil {
+               t.Fatal(err)
+       }
+
        f, err := os.Open(name)
        if err == nil {
                f.Close()
@@ -45,7 +50,10 @@ func testErrNotExist(name string) string {
 
        err = os.Chdir(name)
        if err == nil {
-               return "Chdir should have failed"
+               if err := os.Chdir(originalWD); err != nil {
+                       t.Fatalf("Chdir should have failed, failed to restore original working directory: %v", err)
+               }
+               return "Chdir should have failed, restored original working directory"
        }
        if s := checkErrorPredicate("os.IsNotExist", os.IsNotExist, err, fs.ErrNotExist); s != "" {
                return s
@@ -54,21 +62,15 @@ func testErrNotExist(name string) string {
 }
 
 func TestErrIsNotExist(t *testing.T) {
-       tmpDir, err := os.MkdirTemp("", "_Go_ErrIsNotExist")
-       if err != nil {
-               t.Fatalf("create ErrIsNotExist tempdir: %s", err)
-               return
-       }
-       defer os.RemoveAll(tmpDir)
-
+       tmpDir := t.TempDir()
        name := filepath.Join(tmpDir, "NotExists")
-       if s := testErrNotExist(name); s != "" {
+       if s := testErrNotExist(t, name); s != "" {
                t.Fatal(s)
                return
        }
 
        name = filepath.Join(name, "NotExists2")
-       if s := testErrNotExist(name); s != "" {
+       if s := testErrNotExist(t, name); s != "" {
                t.Fatal(s)
                return
        }
index dd9f31791fdb6f2e5e96f0cb17f6476f9da7747c..3f419d54702094c918e2c1f14379d17a804d4e87 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris
 
 package os_test
index b8191c5ebc8f51b3db6d20eb7116b6bfe7286d29..aa0c14b7d46e36b295497ab1164ad3a7e2ab8729 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build windows
 // +build windows
 
 package os_test
index 3adce517848aab915dee423a3edb9915077a1397..e8554b0b122e750ed5ada1c32045c339e4ce48e7 100644 (file)
@@ -5,6 +5,7 @@
 package os_test
 
 import (
+       "errors"
        "fmt"
        "io/fs"
        "log"
@@ -71,9 +72,9 @@ func ExampleFileMode() {
        }
 }
 
-func ExampleIsNotExist() {
+func ExampleErrNotExist() {
        filename := "a-nonexistent-file"
-       if _, err := os.Stat(filename); os.IsNotExist(err) {
+       if _, err := os.Stat(filename); errors.Is(err, fs.ErrNotExist) {
                fmt.Println("file does not exist")
        }
        // Output:
index edb773a092b6d71d9a8c0ee521e7846659c444b4..bc75d4dd66c9103ccf27df5729baa074d4fa0cdd 100644 (file)
@@ -54,6 +54,9 @@ type ProcAttr struct {
        // standard error. An implementation may support additional entries,
        // depending on the underlying operating system. A nil entry corresponds
        // to that file being closed when the process starts.
+       // On Unix systems, StartProcess will change these File values
+       // to blocking mode, which means that SetDeadline will stop working
+       // and calling Close will not interrupt a Read or Write.
        Files []*File
 
        // Operating system-specific process creation attributes.
index 6f850204d6067f8b1501889b1f7095796b623ad1..3cfa30ee72477ee3c89fa096656138ebe860834f 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build linux && cgo
 // +build linux,cgo
 
 // On systems that use glibc, calling malloc can create a new arena,
index d4d67ac9336825ac2588dea9aec47cb870483051..7b2c0c0c111b35edcb2c7639e6cd0a250db752bb 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
 
 package exec_test
index 8b0c93f3826010185fb5cda7c30248b68bb1f704..d854e0de843d69eff3da155b0710812c412d068b 100644 (file)
@@ -488,7 +488,7 @@ func numOpenFDsAndroid(t *testing.T) (n int, lsof []byte) {
 }
 
 func TestExtraFilesFDShuffle(t *testing.T) {
-       t.Skip("flaky test; see https://golang.org/issue/5780")
+       testenv.SkipFlaky(t, 5780)
        switch runtime.GOOS {
        case "windows":
                t.Skip("no operating system support; skipping")
@@ -915,6 +915,16 @@ func TestHelperProcess(*testing.T) {
        case "sleep":
                time.Sleep(3 * time.Second)
                os.Exit(0)
+       case "pipehandle":
+               handle, _ := strconv.ParseUint(args[0], 16, 64)
+               pipe := os.NewFile(uintptr(handle), "")
+               _, err := fmt.Fprint(pipe, args[1])
+               if err != nil {
+                       fmt.Fprintf(os.Stderr, "writing to pipe failed: %v\n", err)
+                       os.Exit(1)
+               }
+               pipe.Close()
+               os.Exit(0)
        default:
                fmt.Fprintf(os.Stderr, "Unknown command %q\n", cmd)
                os.Exit(2)
@@ -1042,41 +1052,18 @@ func TestContextCancel(t *testing.T) {
        defer cancel()
        c := helperCommandContext(t, ctx, "cat")
 
-       r, w, err := os.Pipe()
-       if err != nil {
-               t.Fatal(err)
-       }
-       c.Stdin = r
-
-       stdout, err := c.StdoutPipe()
+       stdin, err := c.StdinPipe()
        if err != nil {
                t.Fatal(err)
        }
-       readDone := make(chan struct{})
-       go func() {
-               defer close(readDone)
-               var a [1024]byte
-               for {
-                       n, err := stdout.Read(a[:])
-                       if err != nil {
-                               if err != io.EOF {
-                                       t.Errorf("unexpected read error: %v", err)
-                               }
-                               return
-                       }
-                       t.Logf("%s", a[:n])
-               }
-       }()
+       defer stdin.Close()
 
        if err := c.Start(); err != nil {
                t.Fatal(err)
        }
 
-       if err := r.Close(); err != nil {
-               t.Fatal(err)
-       }
-
-       if _, err := io.WriteString(w, "echo"); err != nil {
+       // At this point the process is alive. Ensure it by sending data to stdin.
+       if _, err := io.WriteString(stdin, "echo"); err != nil {
                t.Fatal(err)
        }
 
@@ -1086,20 +1073,15 @@ func TestContextCancel(t *testing.T) {
        // should now fail.  Give the process a little while to die.
        start := time.Now()
        for {
-               if _, err := io.WriteString(w, "echo"); err != nil {
+               if _, err := io.WriteString(stdin, "echo"); err != nil {
                        break
                }
-               if time.Since(start) > time.Second {
+               if time.Since(start) > time.Minute {
                        t.Fatal("canceling context did not stop program")
                }
                time.Sleep(time.Millisecond)
        }
 
-       if err := w.Close(); err != nil {
-               t.Errorf("error closing write end of pipe: %v", err)
-       }
-       <-readDone
-
        if err := c.Wait(); err == nil {
                t.Error("program unexpectedly exited successfully")
        } else {
index 51c52427c2b418c7e88e3cf14dd188d5dabb817b..467c069e1ca48cb7fca9ea887d293cc210d44c1e 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !plan9 && !windows
 // +build !plan9,!windows
 
 package exec
diff --git a/libgo/go/os/exec/exec_windows_test.go b/libgo/go/os/exec/exec_windows_test.go
new file mode 100644 (file)
index 0000000..fbccffe
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build windows
+// +build windows
+
+package exec_test
+
+import (
+       "io"
+       "os"
+       "strconv"
+       "syscall"
+       "testing"
+)
+
+func TestPipePassing(t *testing.T) {
+       r, w, err := os.Pipe()
+       if err != nil {
+               t.Error(err)
+       }
+       const marker = "arrakis, dune, desert planet"
+       childProc := helperCommand(t, "pipehandle", strconv.FormatUint(uint64(w.Fd()), 16), marker)
+       childProc.SysProcAttr = &syscall.SysProcAttr{AdditionalInheritedHandles: []syscall.Handle{syscall.Handle(w.Fd())}}
+       err = childProc.Start()
+       if err != nil {
+               t.Error(err)
+       }
+       w.Close()
+       response, err := io.ReadAll(r)
+       if err != nil {
+               t.Error(err)
+       }
+       r.Close()
+       if string(response) != marker {
+               t.Errorf("got %q; want %q", string(response), marker)
+       }
+       err = childProc.Wait()
+       if err != nil {
+               t.Error(err)
+       }
+}
index 6750fb99b0f6a0053d9cbe33d3e2f5ba1d21b99e..4eac25fe6f402177eb596ff6fe5637f57ef0cd3a 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build js && wasm
 // +build js,wasm
 
 package exec
index bb5a3ece47786eeee1818eb2c7a848a1f63ef6aa..ebecc74d2a121912d55886e2ac0c90e8d56417bb 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package exec
index 23d150669f0ab12e5f10c7c88bc9b027e301a4f3..fe4df1a06107813627a5f11731c5e2a476e64476 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package exec
@@ -36,13 +37,7 @@ func TestLookPathUnixEmptyPath(t *testing.T) {
                t.Fatal("Close failed: ", err)
        }
 
-       pathenv := os.Getenv("PATH")
-       defer os.Setenv("PATH", pathenv)
-
-       err = os.Setenv("PATH", "")
-       if err != nil {
-               t.Fatal("Setenv failed: ", err)
-       }
+       t.Setenv("PATH", "")
 
        path, err := LookPath("exec_me")
        if err == nil {
index 8cc24da8cb41ce57fe9689833f09eba231ad7e33..a8c71831d8806e8e126162130ff118f5c1dd85b4 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 // This is a test program that verifies that it can read from
index 85801539116a2912f85b225c20356cc0493d8853..cc84f976696290ef79b4dfd138ac53ed62c7debe 100644 (file)
@@ -5,6 +5,7 @@
 package os
 
 import (
+       "internal/itoa"
        "runtime"
        "syscall"
        "time"
@@ -40,7 +41,7 @@ func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err e
 }
 
 func (p *Process) writeProcFile(file string, data string) error {
-       f, e := OpenFile("/proc/"+itoa(p.Pid)+"/"+file, O_WRONLY, 0)
+       f, e := OpenFile("/proc/"+itoa.Itoa(p.Pid)+"/"+file, O_WRONLY, 0)
        if e != nil {
                return e
        }
index aa8dfe0294046a1f83f60f316c0dde6529360bdc..eb5cbc8a953890f879e5b276d68ef628a94c61ee 100644 (file)
@@ -2,11 +2,13 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows
 
 package os
 
 import (
+       "internal/itoa"
        "internal/syscall/execenv"
        "runtime"
        "syscall"
@@ -102,13 +104,18 @@ func (p *ProcessState) String() string {
        res := ""
        switch {
        case status.Exited():
-               res = "exit status " + itoa(status.ExitStatus())
+               code := status.ExitStatus()
+               if runtime.GOOS == "windows" && uint(code) >= 1<<16 { // windows uses large hex numbers
+                       res = "exit status " + uitox(uint(code))
+               } else { // unix systems use small decimal integers
+                       res = "exit status " + itoa.Itoa(code) // unix
+               }
        case status.Signaled():
                res = "signal: " + status.Signal().String()
        case status.Stopped():
                res = "stop signal: " + status.StopSignal().String()
                if status.StopSignal() == syscall.SIGTRAP && status.TrapCause() != 0 {
-                       res += " (trap " + itoa(status.TrapCause()) + ")"
+                       res += " (trap " + itoa.Itoa(status.TrapCause()) + ")"
                }
        case status.Continued():
                res = "continued"
index 69eb6151f7d44464f2c2e18ea7b78c8e9a0aaf33..4ada050f5b68b456cf3cf25516cb06129ca49be4 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris
 
 package os
index d942cdb5e53f08e259334416a08602db96f4299f..f14b3519fbe759864fe6b824fd201f69b20b824c 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
 
 package os_test
index 5710401acdb92d44dca834d2ac9c42fe09b9b2d7..239bed198f7fd020f25de0d3f240d1ed7428d1ef 100644 (file)
@@ -45,16 +45,6 @@ func (p *Process) wait() (ps *ProcessState, err error) {
        return &ProcessState{p.Pid, syscall.WaitStatus{ExitCode: ec}, &u}, nil
 }
 
-func terminateProcess(pid, exitcode int) error {
-       h, e := syscall.OpenProcess(syscall.PROCESS_TERMINATE, false, uint32(pid))
-       if e != nil {
-               return NewSyscallError("OpenProcess", e)
-       }
-       defer syscall.CloseHandle(h)
-       e = syscall.TerminateProcess(h, uint32(exitcode))
-       return NewSyscallError("TerminateProcess", e)
-}
-
 func (p *Process) signal(sig Signal) error {
        handle := atomic.LoadUintptr(&p.handle)
        if handle == uintptr(syscall.InvalidHandle) {
@@ -64,16 +54,22 @@ func (p *Process) signal(sig Signal) error {
                return ErrProcessDone
        }
        if sig == Kill {
-               err := terminateProcess(p.Pid, 1)
+               var terminationHandle syscall.Handle
+               e := syscall.DuplicateHandle(^syscall.Handle(0), syscall.Handle(handle), ^syscall.Handle(0), &terminationHandle, syscall.PROCESS_TERMINATE, false, 0)
+               if e != nil {
+                       return NewSyscallError("DuplicateHandle", e)
+               }
                runtime.KeepAlive(p)
-               return err
+               defer syscall.CloseHandle(terminationHandle)
+               e = syscall.TerminateProcess(syscall.Handle(terminationHandle), 1)
+               return NewSyscallError("TerminateProcess", e)
        }
        // TODO(rsc): Handle Interrupt too?
        return syscall.Errno(syscall.EWINDOWS)
 }
 
 func (p *Process) release() error {
-       handle := atomic.LoadUintptr(&p.handle)
+       handle := atomic.SwapUintptr(&p.handle, uintptr(syscall.InvalidHandle))
        if handle == uintptr(syscall.InvalidHandle) {
                return syscall.EINVAL
        }
@@ -81,7 +77,6 @@ func (p *Process) release() error {
        if e != nil {
                return NewSyscallError("CloseHandle", e)
        }
-       atomic.StoreUintptr(&p.handle, uintptr(syscall.InvalidHandle))
        // no need for a finalizer anymore
        runtime.SetFinalizer(p, nil)
        return nil
index 7b8b83652c8953fc4f19ef12568d3aff7f3d86f2..625430ecfca1e53cb9af7fcc1c501eef286abcea 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || openbsd
 // +build aix openbsd
 
 package os
index a5947eaae1ed66ee9bc3a8706a81fc998377bded..ad7a4410dcdd03747b656befb5a12c5016535d49 100644 (file)
@@ -2,14 +2,18 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build plan9
 // +build plan9
 
 package os
 
-import "syscall"
+import (
+       "internal/itoa"
+       "syscall"
+)
 
 func executable() (string, error) {
-       fn := "/proc/" + itoa(Getpid()) + "/text"
+       fn := "/proc/" + itoa.Itoa(Getpid()) + "/text"
        f, err := Open(fn)
        if err != nil {
                return "", err
index 989a2208ca28773e04b2c82bd368baed2518b0dd..fdb239474c421d2ed8dc86647f89dd7beffcacbe 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build hurd || linux || netbsd || (js && wasm)
 // +build hurd linux netbsd js,wasm
 
 package os
@@ -11,10 +12,7 @@ import (
        "runtime"
 )
 
-// We query the executable path at init time to avoid the problem of
-// readlink returns a path appended with " (deleted)" when the original
-// binary gets deleted.
-var executablePath, executablePathErr = func() (string, error) {
+func executable() (string, error) {
        var procfn string
        switch runtime.GOOS {
        default:
@@ -24,9 +22,17 @@ var executablePath, executablePathErr = func() (string, error) {
        case "netbsd":
                procfn = "/proc/curproc/exe"
        }
-       return Readlink(procfn)
-}()
+       path, err := Readlink(procfn)
 
-func executable() (string, error) {
-       return executablePath, executablePathErr
+       // When the executable has been deleted then Readlink returns a
+       // path appended with " (deleted)".
+       return stringsTrimSuffix(path, " (deleted)"), err
+}
+
+// stringsTrimSuffix is the same as strings.TrimSuffix.
+func stringsTrimSuffix(s, suffix string) string {
+       if len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix {
+               return s[:len(s)-len(suffix)]
+       }
+       return s
 }
index f9a4b18f609ca2c2b3954d624024858018816a3a..039448b5573a920b97a8f68f17e293cd41273aec 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build freebsd || dragonfly
 // +build freebsd dragonfly
 
 package os
index f25ee0c95a1cdf11202b25557a72216c054abedc..719d6a61c3f6a333755be261fdeddfb85a1d38ae 100644 (file)
@@ -86,3 +86,68 @@ func init() {
                os.Exit(0)
        }
 }
+
+func TestExecutableDeleted(t *testing.T) {
+       testenv.MustHaveExec(t)
+       switch runtime.GOOS {
+       case "windows", "plan9":
+               t.Skipf("%v does not support deleting running binary", runtime.GOOS)
+       case "openbsd", "freebsd", "aix":
+               t.Skipf("%v does not support reading deleted binary name", runtime.GOOS)
+       }
+
+       dir := t.TempDir()
+
+       src := filepath.Join(dir, "testdel.go")
+       exe := filepath.Join(dir, "testdel.exe")
+
+       err := os.WriteFile(src, []byte(testExecutableDeletion), 0666)
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       out, err := osexec.Command(testenv.GoToolPath(t), "build", "-o", exe, src).CombinedOutput()
+       t.Logf("build output:\n%s", out)
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       out, err = osexec.Command(exe).CombinedOutput()
+       t.Logf("exec output:\n%s", out)
+       if err != nil {
+               t.Fatal(err)
+       }
+}
+
+const testExecutableDeletion = `package main
+
+import (
+       "fmt"
+       "os"
+)
+
+func main() {
+       before, err := os.Executable()
+       if err != nil {
+               fmt.Fprintf(os.Stderr, "failed to read executable name before deletion: %v\n", err)
+               os.Exit(1)
+       }
+
+       err = os.Remove(before)
+       if err != nil {
+               fmt.Fprintf(os.Stderr, "failed to remove executable: %v\n", err)
+               os.Exit(1)
+       }
+
+       after, err := os.Executable()
+       if err != nil {
+               fmt.Fprintf(os.Stderr, "failed to read executable name after deletion: %v\n", err)
+               os.Exit(1)
+       }
+
+       if before != after {
+               fmt.Fprintf(os.Stderr, "before and after do not match: %v != %v\n", before, after)
+               os.Exit(1)
+       }
+}
+`
index f4d399dfad4bfe4a9e6c031b1bbc914192e68679..dd2f8ec94a556d302952c08425210681f46fe220 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris
 
 package os
index f36fadb58bc3fc6ec6b5a8d4620e4bab7295d050..ff4f8995f8c7219c40223dd78fc10a77e2a6c2b3 100644 (file)
@@ -8,6 +8,7 @@ package os
 
 var (
        FixLongPath       = fixLongPath
+       CanUseLongPaths   = canUseLongPaths
        NewConsoleFile    = newConsoleFile
        CommandLineToArgv = commandLineToArgv
 )
index 2439192a9dde3a169f730b1dfe5c862c61850114..007ed2912933bbcde5fe99d1d877f89c5d790586 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd
 // +build darwin dragonfly freebsd linux netbsd openbsd
 
 package os_test
@@ -25,17 +26,9 @@ func TestFifoEOF(t *testing.T) {
        switch runtime.GOOS {
        case "android":
                t.Skip("skipping on Android; mkfifo syscall not available")
-       case "openbsd":
-               // On OpenBSD 6.2 this test just hangs for some reason.
-               t.Skip("skipping on OpenBSD; issue 25877")
        }
 
-       dir, err := os.MkdirTemp("", "TestFifoEOF")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(dir)
-
+       dir := t.TempDir()
        fifoName := filepath.Join(dir, "fifo")
        if err := syscall.Mkfifo(fifoName, 0600); err != nil {
                t.Fatal(err)
index 52dd94339b8ffbed5ceaffaec3edd002c19ca36d..e717f171e72580330de5f8ced30de0a24edc331c 100644 (file)
@@ -44,11 +44,13 @@ import (
        "errors"
        "internal/poll"
        "internal/testlog"
+       "internal/unsafeheader"
        "io"
        "io/fs"
        "runtime"
        "syscall"
        "time"
+       "unsafe"
 )
 
 // Name returns the name of the file as presented to Open.
@@ -246,7 +248,12 @@ func (f *File) Seek(offset int64, whence int) (ret int64, err error) {
 // WriteString is like Write, but writes the contents of string s rather than
 // a slice of bytes.
 func (f *File) WriteString(s string) (n int, err error) {
-       return f.Write([]byte(s))
+       var b []byte
+       hdr := (*unsafeheader.Slice)(unsafe.Pointer(&b))
+       hdr.Data = (*unsafeheader.String)(unsafe.Pointer(&s)).Data
+       hdr.Cap = len(s)
+       hdr.Len = len(s)
+       return f.Write(b)
 }
 
 // Mkdir creates a new directory with the specified name and permission
@@ -644,6 +651,17 @@ func (dir dirFS) Open(name string) (fs.File, error) {
        return f, nil
 }
 
+func (dir dirFS) Stat(name string) (fs.FileInfo, error) {
+       if !fs.ValidPath(name) || runtime.GOOS == "windows" && containsAny(name, `\:`) {
+               return nil, &PathError{Op: "stat", Path: name, Err: ErrInvalid}
+       }
+       f, err := Stat(string(dir) + "/" + name)
+       if err != nil {
+               return nil, err
+       }
+       return f, nil
+}
+
 // ReadFile reads the named file and returns the contents.
 // A successful call returns err == nil, not err == EOF.
 // Because ReadFile reads the whole file, it does not treat an EOF from Read
index 4f384e9211061d526dd6c3ca736572e79389235d..604aea607bcf304e4ac111fbdd4aeb4e3c596cc0 100644 (file)
@@ -440,6 +440,8 @@ func Link(oldname, newname string) error {
 }
 
 // Symlink creates newname as a symbolic link to oldname.
+// On Windows, a symlink to a non-existent oldname creates a file symlink;
+// if oldname is later created as a directory the symlink will not work.
 // If there is an error, it will be of type *LinkError.
 func Symlink(oldname, newname string) error {
        return &LinkError{"symlink", oldname, newname, syscall.EPLAN9}
index 95bf9e7b65906595e0c00686e277c78dbd01345e..21831a7031bba792d7897c78982c30cf3018386a 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows
 
 package os
index 5888d48f8193c357d756a3a71379f4fe4320bf0d..a31800bd6aa842ee4361a25ec45f5cac49309d39 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris
 
 package os
@@ -173,7 +174,7 @@ func newFile(fd uintptr, name string, kind newFileKind) *File {
                // with the netpoll system. That can happen for
                // a file descriptor that is not supported by
                // epoll/kqueue; for example, disk files on
-               // GNU/Linux systems. We assume that any real error
+               // Linux systems. We assume that any real error
                // will show up in later I/O.
        } else if pollable {
                // We successfully registered with netpoll, so put
@@ -261,6 +262,7 @@ func (file *file) close() error {
        var err error
        if file.dirinfo != nil {
                file.dirinfo.close()
+               file.dirinfo = nil
        }
        if e := file.pfd.Close(); e != nil {
                if e == poll.ErrFileClosing {
@@ -363,6 +365,8 @@ func Link(oldname, newname string) error {
 }
 
 // Symlink creates newname as a symbolic link to oldname.
+// On Windows, a symlink to a non-existent oldname creates a file symlink;
+// if oldname is later created as a directory the symlink will not work.
 // If there is an error, it will be of type *LinkError.
 func Symlink(oldname, newname string) error {
        e := ignoringEINTR(func() error {
index 734c655e6f7df13fdd34902431229d8215194c85..0cde45423b85e0614f344cfa49d32882f979b7c7 100644 (file)
@@ -615,11 +615,7 @@ func TestReaddirNValues(t *testing.T) {
        if testing.Short() {
                t.Skip("test.short; skipping")
        }
-       dir, err := os.MkdirTemp("", "")
-       if err != nil {
-               t.Fatalf("TempDir: %v", err)
-       }
-       defer RemoveAll(dir)
+       dir := t.TempDir()
        for i := 1; i <= 105; i++ {
                f, err := Create(filepath.Join(dir, fmt.Sprintf("%d", i)))
                if err != nil {
@@ -714,11 +710,7 @@ func TestReaddirStatFailures(t *testing.T) {
                // testing it wouldn't work.
                t.Skipf("skipping test on %v", runtime.GOOS)
        }
-       dir, err := os.MkdirTemp("", "")
-       if err != nil {
-               t.Fatalf("TempDir: %v", err)
-       }
-       defer RemoveAll(dir)
+       dir := t.TempDir()
        touch(t, filepath.Join(dir, "good1"))
        touch(t, filepath.Join(dir, "x")) // will disappear or have an error
        touch(t, filepath.Join(dir, "good2"))
@@ -1951,22 +1943,16 @@ func TestAppend(t *testing.T) {
 
 func TestStatDirWithTrailingSlash(t *testing.T) {
        // Create new temporary directory and arrange to clean it up.
-       path, err := os.MkdirTemp("", "_TestStatDirWithSlash_")
-       if err != nil {
-               t.Fatalf("TempDir: %s", err)
-       }
-       defer RemoveAll(path)
+       path := t.TempDir()
 
        // Stat of path should succeed.
-       _, err = Stat(path)
-       if err != nil {
+       if _, err := Stat(path); err != nil {
                t.Fatalf("stat %s failed: %s", path, err)
        }
 
        // Stat of path+"/" should succeed too.
        path += "/"
-       _, err = Stat(path)
-       if err != nil {
+       if _, err := Stat(path); err != nil {
                t.Fatalf("stat %s failed: %s", path, err)
        }
 }
@@ -2093,12 +2079,7 @@ func TestLargeWriteToConsole(t *testing.T) {
 func TestStatDirModeExec(t *testing.T) {
        const mode = 0111
 
-       path, err := os.MkdirTemp("", "go-build")
-       if err != nil {
-               t.Fatalf("Failed to create temp directory: %v", err)
-       }
-       defer RemoveAll(path)
-
+       path := t.TempDir()
        if err := Chmod(path, 0777); err != nil {
                t.Fatalf("Chmod %q 0777: %v", path, err)
        }
@@ -2162,12 +2143,7 @@ func TestStatStdin(t *testing.T) {
 func TestStatRelativeSymlink(t *testing.T) {
        testenv.MustHaveSymlink(t)
 
-       tmpdir, err := os.MkdirTemp("", "TestStatRelativeSymlink")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer RemoveAll(tmpdir)
-
+       tmpdir := t.TempDir()
        target := filepath.Join(tmpdir, "target")
        f, err := Create(target)
        if err != nil {
@@ -2775,3 +2751,21 @@ func TestReadFileProc(t *testing.T) {
                t.Fatalf("read %s: not newline-terminated: %q", name, data)
        }
 }
+
+func TestWriteStringAlloc(t *testing.T) {
+       if runtime.GOOS == "js" {
+               t.Skip("js allocates a lot during File.WriteString")
+       }
+       d := t.TempDir()
+       f, err := Create(filepath.Join(d, "whiteboard.txt"))
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer f.Close()
+       allocs := testing.AllocsPerRun(100, func() {
+               f.WriteString("I will not allocate when passed a string longer than 32 bytes.\n")
+       })
+       if allocs != 0 {
+               t.Errorf("expected 0 allocs for File.WriteString, got %v", allocs)
+       }
+}
index 9a5d7bf81c608a80938f84a836780e56a539c179..95ceb0daa36f553415a5b4d458667882cd33bec9 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris
 
 package os_test
index b0929b4f3085a5532e7b0ce5dc75ac9953804110..195c30f50efd8baf64e3c3a3e77920fea036928a 100644 (file)
@@ -29,22 +29,32 @@ import (
 // For TestRawConnReadWrite.
 type syscallDescriptor = syscall.Handle
 
-func TestSameWindowsFile(t *testing.T) {
-       temp, err := os.MkdirTemp("", "TestSameWindowsFile")
+// chdir changes the current working directory to the named directory,
+// and then restore the original working directory at the end of the test.
+func chdir(t *testing.T, dir string) {
+       olddir, err := os.Getwd()
        if err != nil {
-               t.Fatal(err)
+               t.Fatalf("chdir: %v", err)
        }
-       defer os.RemoveAll(temp)
-
-       wd, err := os.Getwd()
-       if err != nil {
-               t.Fatal(err)
+       if err := os.Chdir(dir); err != nil {
+               t.Fatalf("chdir %s: %v", dir, err)
        }
-       err = os.Chdir(temp)
+
+       t.Cleanup(func() {
+               if err := os.Chdir(olddir); err != nil {
+                       t.Errorf("chdir to original working directory %s: %v", olddir, err)
+                       os.Exit(1)
+               }
+       })
+}
+
+func TestSameWindowsFile(t *testing.T) {
+       temp, err := os.MkdirTemp("", "TestSameWindowsFile")
        if err != nil {
                t.Fatal(err)
        }
-       defer os.Chdir(wd)
+       defer os.RemoveAll(temp)
+       chdir(t, temp)
 
        f, err := os.Create("a")
        if err != nil {
@@ -94,16 +104,7 @@ func testDirLinks(t *testing.T, tests []dirLinkTest) {
                t.Fatal(err)
        }
        defer os.RemoveAll(tmpdir)
-
-       oldwd, err := os.Getwd()
-       if err != nil {
-               t.Fatal(err)
-       }
-       err = os.Chdir(tmpdir)
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.Chdir(oldwd)
+       chdir(t, tmpdir)
 
        dir := filepath.Join(tmpdir, "dir")
        err = os.Mkdir(dir, 0777)
@@ -444,15 +445,7 @@ func TestNetworkSymbolicLink(t *testing.T) {
        }
        defer os.RemoveAll(dir)
 
-       oldwd, err := os.Getwd()
-       if err != nil {
-               t.Fatal(err)
-       }
-       err = os.Chdir(dir)
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.Chdir(oldwd)
+       chdir(t, dir)
 
        shareName := "GoSymbolicLinkTestShare" // hope no conflictions
        sharePath := filepath.Join(dir, shareName)
@@ -604,16 +597,7 @@ func TestOpenVolumeName(t *testing.T) {
                t.Fatal(err)
        }
        defer os.RemoveAll(tmpdir)
-
-       wd, err := os.Getwd()
-       if err != nil {
-               t.Fatal(err)
-       }
-       err = os.Chdir(tmpdir)
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.Chdir(wd)
+       chdir(t, tmpdir)
 
        want := []string{"file1", "file2", "file3", "gopher.txt"}
        sort.Strings(want)
@@ -642,11 +626,7 @@ func TestOpenVolumeName(t *testing.T) {
 }
 
 func TestDeleteReadOnly(t *testing.T) {
-       tmpdir, err := os.MkdirTemp("", "TestDeleteReadOnly")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(tmpdir)
+       tmpdir := t.TempDir()
        p := filepath.Join(tmpdir, "a")
        // This sets FILE_ATTRIBUTE_READONLY.
        f, err := os.OpenFile(p, os.O_CREATE, 0400)
@@ -812,11 +792,7 @@ func compareCommandLineToArgvWithSyscall(t *testing.T, cmd string) {
 }
 
 func TestCmdArgs(t *testing.T) {
-       tmpdir, err := os.MkdirTemp("", "TestCmdArgs")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(tmpdir)
+       tmpdir := t.TempDir()
 
        const prog = `
 package main
@@ -831,8 +807,7 @@ func main() {
 }
 `
        src := filepath.Join(tmpdir, "main.go")
-       err = os.WriteFile(src, []byte(prog), 0666)
-       if err != nil {
+       if err := os.WriteFile(src, []byte(prog), 0666); err != nil {
                t.Fatal(err)
        }
 
@@ -979,21 +954,14 @@ func TestSymlinkCreation(t *testing.T) {
        }
        t.Parallel()
 
-       temp, err := os.MkdirTemp("", "TestSymlinkCreation")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(temp)
-
+       temp := t.TempDir()
        dummyFile := filepath.Join(temp, "file")
-       err = os.WriteFile(dummyFile, []byte(""), 0644)
-       if err != nil {
+       if err := os.WriteFile(dummyFile, []byte(""), 0644); err != nil {
                t.Fatal(err)
        }
 
        linkFile := filepath.Join(temp, "link")
-       err = os.Symlink(dummyFile, linkFile)
-       if err != nil {
+       if err := os.Symlink(dummyFile, linkFile); err != nil {
                t.Fatal(err)
        }
 }
@@ -1226,16 +1194,7 @@ func TestWindowsReadlink(t *testing.T) {
        if err != nil {
                t.Fatal(err)
        }
-
-       wd, err := os.Getwd()
-       if err != nil {
-               t.Fatal(err)
-       }
-       err = os.Chdir(tmpdir)
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.Chdir(wd)
+       chdir(t, tmpdir)
 
        vol := filepath.VolumeName(tmpdir)
        output, err := osexec.Command("cmd", "/c", "mountvol", vol, "/L").CombinedOutput()
index b79d9587118fd3b9867b5b112d140ea1238fa00e..4535abbc527b048c1ec2b21d43ba49d13f7f4d29 100644 (file)
@@ -6,7 +6,6 @@ package os_test
 
 import (
        "internal/testenv"
-       "os"
        . "os"
        "path/filepath"
        "runtime"
@@ -78,27 +77,19 @@ func TestMkdirAll(t *testing.T) {
 func TestMkdirAllWithSymlink(t *testing.T) {
        testenv.MustHaveSymlink(t)
 
-       tmpDir, err := os.MkdirTemp("", "TestMkdirAllWithSymlink-")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer RemoveAll(tmpDir)
-
+       tmpDir := t.TempDir()
        dir := tmpDir + "/dir"
-       err = Mkdir(dir, 0755)
-       if err != nil {
+       if err := Mkdir(dir, 0755); err != nil {
                t.Fatalf("Mkdir %s: %s", dir, err)
        }
 
        link := tmpDir + "/link"
-       err = Symlink("dir", link)
-       if err != nil {
+       if err := Symlink("dir", link); err != nil {
                t.Fatalf("Symlink %s: %s", link, err)
        }
 
        path := link + "/foo"
-       err = MkdirAll(path, 0755)
-       if err != nil {
+       if err := MkdirAll(path, 0755); err != nil {
                t.Errorf("MkdirAll %q: %s", path, err)
        }
 }
index 6ef6560dd40cb545d5245e27acd3b3a5ea213002..bb0b0a05da7363dd36c564b3983f12934adaf068 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris
 
 package os
index 87b1cac531790db476cb81094ff5bcfc2bd20ed8..a96245f358c99c51791903a09fddd14a4ac8e87c 100644 (file)
@@ -128,6 +128,10 @@ func dirname(path string) string {
        return vol + dir
 }
 
+// This is set via go:linkname on runtime.canUseLongPaths, and is true when the OS
+// supports opting into proper long path handling without the need for fixups.
+var canUseLongPaths bool
+
 // fixLongPath returns the extended-length (\\?\-prefixed) form of
 // path when needed, in order to avoid the default 260 character file
 // path limit imposed by Windows. If path is not easily converted to
@@ -137,6 +141,9 @@ func dirname(path string) string {
 //
 // See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath
 func fixLongPath(path string) string {
+       if canUseLongPaths {
+               return path
+       }
        // Do nothing (and don't allocate) if the path is "short".
        // Empirically (at least on the Windows Server 2013 builder),
        // the kernel is arbitrarily okay with < 248 bytes. That
index 869db8fd6c328df59a867cf9564d3b552fe20200..e960bcb19c69476352a9765ba3e5877a6fd9a1db 100644 (file)
@@ -12,6 +12,9 @@ import (
 )
 
 func TestFixLongPath(t *testing.T) {
+       if os.CanUseLongPaths {
+               return
+       }
        // 248 is long enough to trigger the longer-than-248 checks in
        // fixLongPath, but short enough not to make a path component
        // longer than 255, which is illegal on Windows. (which
@@ -46,12 +49,22 @@ func TestFixLongPath(t *testing.T) {
        }
 }
 
-func TestMkdirAllExtendedLength(t *testing.T) {
-       tmpDir, err := os.MkdirTemp("", "TestMkdirAllExtendedLength")
-       if err != nil {
-               t.Fatal(err)
+func TestMkdirAllLongPath(t *testing.T) {
+       tmpDir := t.TempDir()
+       path := tmpDir
+       for i := 0; i < 100; i++ {
+               path += `\another-path-component`
+       }
+       if err := os.MkdirAll(path, 0777); err != nil {
+               t.Fatalf("MkdirAll(%q) failed; %v", path, err)
+       }
+       if err := os.RemoveAll(tmpDir); err != nil {
+               t.Fatalf("RemoveAll(%q) failed; %v", tmpDir, err)
        }
-       defer os.RemoveAll(tmpDir)
+}
+
+func TestMkdirAllExtendedLength(t *testing.T) {
+       tmpDir := t.TempDir()
 
        const prefix = `\\?\`
        if len(tmpDir) < 4 || tmpDir[:4] != prefix {
@@ -62,14 +75,12 @@ func TestMkdirAllExtendedLength(t *testing.T) {
                tmpDir = prefix + fullPath
        }
        path := tmpDir + `\dir\`
-       err = os.MkdirAll(path, 0777)
-       if err != nil {
+       if err := os.MkdirAll(path, 0777); err != nil {
                t.Fatalf("MkdirAll(%q) failed: %v", path, err)
        }
 
        path = path + `.\dir2`
-       err = os.MkdirAll(path, 0777)
-       if err == nil {
+       if err := os.MkdirAll(path, 0777); err == nil {
                t.Fatalf("MkdirAll(%q) should have failed, but did not", path)
        }
 }
index 0ef894b476bed9386dbdc837042b3c4b869b3bd7..bf6d081db5b83c9cfe8e47d392fba4db71fd4eaa 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build freebsd netbsd openbsd
+//go:build dragonfly || freebsd || netbsd || openbsd
+// +build dragonfly freebsd netbsd openbsd
 
 package os
 
index 026ce62b9a642c67c5b15720b541851fdd623ed9..71b8cb8e25be5706532908826dfb25d5e6b768ed 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build illumos
 // +build illumos
 
 package os
index 115d6baa190a272123d3573cca6a66464c686181..097b32e7eb33cf0414a28209c681b399449e07ba 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build aix darwin dragonfly js,wasm solaris,!illumos
+//go:build aix || darwin || (js && wasm) || (solaris && !illumos)
+// +build aix darwin js,wasm solaris,!illumos
 
 package os
 
index b98e53845c67ab36a50d7fe13e8357cda93ecf77..41a1e9c78aa36542a892392b63ae136cfd3403be 100644 (file)
@@ -3,6 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // Test broken pipes on Unix systems.
+//go:build !plan9 && !js
 // +build !plan9,!js
 
 package os_test
@@ -441,12 +442,14 @@ func TestFdReadRace(t *testing.T) {
        defer r.Close()
        defer w.Close()
 
-       c := make(chan bool)
+       const count = 10
+
+       c := make(chan bool, 1)
        var wg sync.WaitGroup
        wg.Add(1)
        go func() {
                defer wg.Done()
-               var buf [10]byte
+               var buf [count]byte
                r.SetReadDeadline(time.Now().Add(time.Minute))
                c <- true
                if _, err := r.Read(buf[:]); os.IsTimeout(err) {
@@ -465,8 +468,9 @@ func TestFdReadRace(t *testing.T) {
                r.Fd()
 
                // The bug was that Fd would hang until Read timed out.
-               // If the bug is fixed, then closing r here will cause
-               // the Read to exit before the timeout expires.
+               // If the bug is fixed, then writing to w and closing r here
+               // will cause the Read to exit before the timeout expires.
+               w.Write(make([]byte, count))
                r.Close()
        }()
 
index 9e11cda8c9aa9bdb5ab77e7805c67173a32d29b5..ffc598b0618987c1a9c5928c7de6896e11df63eb 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !plan9
 // +build !plan9
 
 package os
index 2554f5b087846b1c72e3153cb8bceaae2231716d..8aebaf87a60760623531ffc402e12f0feeba3ab2 100644 (file)
@@ -3,6 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // Test use of raw connections.
+//go:build !plan9 && !js
 // +build !plan9,!js
 
 package os_test
index 1d145dadb0870dea710871a360d68125d37cd5c7..cb6a59abdb2cf578847aa200bfc9c822aab080b3 100644 (file)
@@ -106,7 +106,7 @@ func TestCopyFileRange(t *testing.T) {
                                t.Fatal(err)
                        }
                        if n != int64(len(data)) {
-                               t.Fatalf("transfered %d, want %d", n, len(data))
+                               t.Fatalf("transferred %d, want %d", n, len(data))
                        }
                        if !hook.called {
                                t.Fatalf("should have called poll.CopyFileRange")
@@ -130,7 +130,7 @@ func TestCopyFileRange(t *testing.T) {
                                t.Fatal(err)
                        }
                        if n != int64(len(data)) {
-                               t.Fatalf("transfered %d, want %d", n, len(data))
+                               t.Fatalf("transferred %d, want %d", n, len(data))
                        }
                        if !hook.called {
                                t.Fatalf("should have called poll.CopyFileRange")
@@ -162,7 +162,7 @@ func TestCopyFileRange(t *testing.T) {
                                t.Fatal(err)
                        }
                        if n != int64(len(data)) {
-                               t.Fatalf("transfered %d, want %d", n, len(data))
+                               t.Fatalf("transferred %d, want %d", n, len(data))
                        }
                        if !hook.called {
                                t.Fatalf("should have called poll.CopyFileRange")
index 65429d0cab24341d673a7a1550abc9be0a37cac9..826760f3df65cc290470e171032e16a62c57b013 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !linux
 // +build !linux
 
 package os
index f9eafa1fb08443dc73ce3a0fb15c981b2bfcb119..4e55577dc2ab214dd477bd16bb61490d701603b0 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package os
index a4cde5a52c596b71de9a9abebbba65b4fd3550be..966f3f59bc10468c992e9c577fa67f0cef131ff0 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !aix && !darwin && !dragonfly && !freebsd && !hurd && !linux && !netbsd && !openbsd && !solaris
 // +build !aix,!darwin,!dragonfly,!freebsd,!hurd,!linux,!netbsd,!openbsd,!solaris
 
 package os
index 3a2f6e37591632db2711afff5a4e571d9f03002c..08dfdd8ec0644703cf505b973b21a58c5396cbec 100644 (file)
@@ -15,12 +15,7 @@ import (
 )
 
 func TestRemoveAll(t *testing.T) {
-       tmpDir, err := os.MkdirTemp("", "TestRemoveAll-")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer RemoveAll(tmpDir)
-
+       tmpDir := t.TempDir()
        if err := RemoveAll(""); err != nil {
                t.Errorf("RemoveAll(\"\"): %v; want nil", err)
        }
@@ -128,12 +123,7 @@ func TestRemoveAllLarge(t *testing.T) {
                t.Skip("skipping in short mode")
        }
 
-       tmpDir, err := os.MkdirTemp("", "TestRemoveAll-")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer RemoveAll(tmpDir)
-
+       tmpDir := t.TempDir()
        path := filepath.Join(tmpDir, "_TestRemoveAllLarge_")
 
        // Make directory with 1000 files and remove.
@@ -236,12 +226,7 @@ func TestRemoveAllDot(t *testing.T) {
 func TestRemoveAllDotDot(t *testing.T) {
        t.Parallel()
 
-       tempDir, err := os.MkdirTemp("", "TestRemoveAllDotDot-")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer RemoveAll(tempDir)
-
+       tempDir := t.TempDir()
        subdir := filepath.Join(tempDir, "x")
        subsubdir := filepath.Join(subdir, "y")
        if err := MkdirAll(subsubdir, 0777); err != nil {
@@ -261,12 +246,7 @@ func TestRemoveAllDotDot(t *testing.T) {
 func TestRemoveReadOnlyDir(t *testing.T) {
        t.Parallel()
 
-       tempDir, err := os.MkdirTemp("", "TestRemoveReadOnlyDir-")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer RemoveAll(tempDir)
-
+       tempDir := t.TempDir()
        subdir := filepath.Join(tempDir, "x")
        if err := Mkdir(subdir, 0); err != nil {
                t.Fatal(err)
@@ -298,12 +278,7 @@ func TestRemoveAllButReadOnlyAndPathError(t *testing.T) {
 
        t.Parallel()
 
-       tempDir, err := os.MkdirTemp("", "TestRemoveAllButReadOnly-")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer RemoveAll(tempDir)
-
+       tempDir := t.TempDir()
        dirs := []string{
                "a",
                "a/x",
@@ -347,7 +322,7 @@ func TestRemoveAllButReadOnlyAndPathError(t *testing.T) {
                defer Chmod(d, 0777)
        }
 
-       err = RemoveAll(tempDir)
+       err := RemoveAll(tempDir)
        if err == nil {
                t.Fatal("RemoveAll succeeded unexpectedly")
        }
@@ -389,12 +364,7 @@ func TestRemoveUnreadableDir(t *testing.T) {
 
        t.Parallel()
 
-       tempDir, err := os.MkdirTemp("", "TestRemoveAllButReadOnly-")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer RemoveAll(tempDir)
-
+       tempDir := t.TempDir()
        target := filepath.Join(tempDir, "d0", "d1", "d2")
        if err := MkdirAll(target, 0755); err != nil {
                t.Fatal(err)
@@ -413,12 +383,7 @@ func TestRemoveAllWithMoreErrorThanReqSize(t *testing.T) {
                t.Skip("skipping in short mode")
        }
 
-       tmpDir, err := os.MkdirTemp("", "TestRemoveAll-")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer RemoveAll(tmpDir)
-
+       tmpDir := t.TempDir()
        path := filepath.Join(tmpDir, "_TestRemoveAllWithMoreErrorThanReqSize_")
 
        // Make directory with 1025 read-only files.
@@ -443,7 +408,7 @@ func TestRemoveAllWithMoreErrorThanReqSize(t *testing.T) {
 
        // This call should not hang, even on a platform that disallows file deletion
        // from read-only directories.
-       err = RemoveAll(path)
+       err := RemoveAll(path)
 
        if Getuid() == 0 {
                // On many platforms, root can remove files from read-only directories.
index 2229d36954f096d17af6f3385c984a284477bf9a..7af61d2d81746f9c73e5947381174c05e4b04ef1 100644 (file)
@@ -50,7 +50,7 @@ If the Go program is started with either SIGHUP or SIGINT ignored
 If the Go program is started with a non-empty signal mask, that will
 generally be honored. However, some signals are explicitly unblocked:
 the synchronous signals, SIGILL, SIGTRAP, SIGSTKFLT, SIGCHLD, SIGPROF,
-and, on GNU/Linux, signals 32 (SIGCANCEL) and 33 (SIGSETXID)
+and, on Linux, signals 32 (SIGCANCEL) and 33 (SIGSETXID)
 (SIGCANCEL and SIGSETXID are used internally by glibc). Subprocesses
 started by os.Exec, or by the os/exec package, will inherit the
 modified signal mask.
@@ -129,9 +129,7 @@ If the non-Go code installs any signal handlers, it must use the
 SA_ONSTACK flag with sigaction. Failing to do so is likely to cause
 the program to crash if the signal is received. Go programs routinely
 run with a limited stack, and therefore set up an alternate signal
-stack. Also, the Go standard library expects that any signal handlers
-will use the SA_RESTART flag. Failing to do so may cause some library
-calls to return "interrupted system call" errors.
+stack.
 
 If the non-Go code installs a signal handler for any of the
 synchronous signals (SIGBUS, SIGFPE, SIGSEGV), then it should record
@@ -178,7 +176,7 @@ will initialize signals at global constructor time.  For
 shared library is loaded.
 
 If the Go runtime sees an existing signal handler for the SIGCANCEL or
-SIGSETXID signals (which are used only on GNU/Linux), it will turn on
+SIGSETXID signals (which are used only on Linux), it will turn on
 the SA_ONSTACK flag and otherwise keep the signal handler.
 
 For the synchronous signals and SIGPIPE, the Go runtime will install a
index a0af37a5bb3196ed9a7a87d32f370313665e53f4..3f7795b8cf9558dfb4a1b0b573ae1eaee21cbc11 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
 
 package signal_test
index dd0aee1cb2b203f5665916f5cc8fb3c8cf51a2e3..4ed3eb44e17131ac66fd31c6e0c496dc2f23dfd9 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build (aix || darwin || dragonfly || freebsd || hurd || (linux && !android) || netbsd || openbsd || solaris) && cgo
 // +build aix darwin dragonfly freebsd hurd linux,!android netbsd openbsd solaris
 // +build cgo
 
index a8a485613f584fb773dc7f3d74a27de66260f450..e1e4509e2a723b9ae4df542a485703a7fde79b82 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build (darwin || dragonfly || freebsd || (linux && !android) || netbsd || openbsd) && cgo
 // +build darwin dragonfly freebsd linux,!android netbsd openbsd
 // +build cgo
 
index 2e553d0b0f0c763427e8dbd6e72d74f6e8cd3a32..7abe1ec5a0a5954464b92dc79cb497bc6feeec04 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build linux
 // +build linux
 
 package signal
index 10bfdc3ff10a8bd8570335aaac5f802836a73576..8357199aa4ad64749d70a48eb9b48a2ac41c7f65 100644 (file)
@@ -5,6 +5,7 @@
 package signal
 
 import (
+       "internal/itoa"
        "os"
        "runtime"
        "syscall"
@@ -155,23 +156,8 @@ func TestStop(t *testing.T) {
        }
 }
 
-func itoa(val int) string {
-       if val < 0 {
-               return "-" + itoa(-val)
-       }
-       var buf [32]byte // big enough for int64
-       i := len(buf) - 1
-       for val >= 10 {
-               buf[i] = byte(val%10 + '0')
-               i--
-               val /= 10
-       }
-       buf[i] = byte(val + '0')
-       return string(buf[i:])
-}
-
 func postNote(pid int, note string) error {
-       f, err := os.OpenFile("/proc/"+itoa(pid)+"/note", os.O_WRONLY, 0)
+       f, err := os.OpenFile("/proc/"+itoa.Itoa(pid)+"/note", os.O_WRONLY, 0)
        if err != nil {
                return err
        }
index 1f89780c455f04f56a0232fdb5f3e61f13618623..c653c344fa192d6a3db0b150871ca932c7139a2b 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package signal
@@ -17,6 +18,7 @@ import (
        "runtime"
        "runtime/trace"
        "strconv"
+       "strings"
        "sync"
        "syscall"
        "testing"
@@ -30,6 +32,11 @@ import (
 // The current value is set based on flakes observed in the Go builders.
 var settleTime = 100 * time.Millisecond
 
+// fatalWaitingTime is an absurdly long time to wait for signals to be
+// delivered but, using it, we (hopefully) eliminate test flakes on the
+// build servers. See #46736 for discussion.
+var fatalWaitingTime = 30 * time.Second
+
 func init() {
        if testenv.Builder() == "solaris-amd64-oraclerel" {
                // The solaris-amd64-oraclerel builder has been observed to time out in
@@ -46,6 +53,13 @@ func init() {
                //
                // See https://golang.org/issue/33174.
                settleTime = 11 * time.Second
+       } else if runtime.GOOS == "linux" && strings.HasPrefix(runtime.GOARCH, "ppc64") {
+               // Older linux kernels seem to have some hiccups delivering the signal
+               // in a timely manner on ppc64 and ppc64le. When running on a
+               // ppc64le/ubuntu 16.04/linux 4.4 host the time can vary quite
+               // substantially even on a idle system. 5 seconds is twice any value
+               // observed when running 10000 tests on such a system.
+               settleTime = 5 * time.Second
        } else if s := os.Getenv("GO_TEST_TIMEOUT_SCALE"); s != "" {
                if scale, err := strconv.Atoi(s); err == nil {
                        settleTime *= time.Duration(scale)
@@ -75,7 +89,7 @@ func waitSig1(t *testing.T, c <-chan os.Signal, sig os.Signal, all bool) {
        // General user code should filter out all unexpected signals instead of just
        // SIGURG, but since os/signal is tightly coupled to the runtime it seems
        // appropriate to be stricter here.
-       for time.Since(start) < settleTime {
+       for time.Since(start) < fatalWaitingTime {
                select {
                case s := <-c:
                        if s == sig {
@@ -88,7 +102,7 @@ func waitSig1(t *testing.T, c <-chan os.Signal, sig os.Signal, all bool) {
                        timer.Reset(settleTime / 10)
                }
        }
-       t.Fatalf("timeout after %v waiting for %v", settleTime, sig)
+       t.Fatalf("timeout after %v waiting for %v", fatalWaitingTime, sig)
 }
 
 // quiesce waits until we can be reasonably confident that all pending signals
index c18db0c46189a7a9e418c41e1fb24c0ca445b797..a0c7ffbdb54e4f3fc180a70917addb59dceb711f 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows
 
 package signal
index 8d20ccddfcc43c282583bb10b541b9cd4528619f..3badf5ba575b24de3a77895dcee9e21a6e9ffc10 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build js && wasm
 // +build js,wasm
 
 package os
index c409f0ff18e2216982d43a98f33391392ef36953..8d99f6460964c67ca02818ee98df6af32294f13b 100644 (file)
@@ -185,30 +185,22 @@ func testSymlinkSameFile(t *testing.T, path, link string) {
 func TestDirAndSymlinkStats(t *testing.T) {
        testenv.MustHaveSymlink(t)
 
-       tmpdir, err := os.MkdirTemp("", "TestDirAndSymlinkStats")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(tmpdir)
-
+       tmpdir := t.TempDir()
        dir := filepath.Join(tmpdir, "dir")
-       err = os.Mkdir(dir, 0777)
-       if err != nil {
+       if err := os.Mkdir(dir, 0777); err != nil {
                t.Fatal(err)
        }
        testDirStats(t, dir)
 
        dirlink := filepath.Join(tmpdir, "link")
-       err = os.Symlink(dir, dirlink)
-       if err != nil {
+       if err := os.Symlink(dir, dirlink); err != nil {
                t.Fatal(err)
        }
        testSymlinkStats(t, dirlink, true)
        testSymlinkSameFile(t, dir, dirlink)
 
        linklink := filepath.Join(tmpdir, "linklink")
-       err = os.Symlink(dirlink, linklink)
-       if err != nil {
+       if err := os.Symlink(dirlink, linklink); err != nil {
                t.Fatal(err)
        }
        testSymlinkStats(t, linklink, true)
@@ -218,30 +210,22 @@ func TestDirAndSymlinkStats(t *testing.T) {
 func TestFileAndSymlinkStats(t *testing.T) {
        testenv.MustHaveSymlink(t)
 
-       tmpdir, err := os.MkdirTemp("", "TestFileAndSymlinkStats")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(tmpdir)
-
+       tmpdir := t.TempDir()
        file := filepath.Join(tmpdir, "file")
-       err = os.WriteFile(file, []byte(""), 0644)
-       if err != nil {
+       if err := os.WriteFile(file, []byte(""), 0644); err != nil {
                t.Fatal(err)
        }
        testFileStats(t, file)
 
        filelink := filepath.Join(tmpdir, "link")
-       err = os.Symlink(file, filelink)
-       if err != nil {
+       if err := os.Symlink(file, filelink); err != nil {
                t.Fatal(err)
        }
        testSymlinkStats(t, filelink, false)
        testSymlinkSameFile(t, file, filelink)
 
        linklink := filepath.Join(tmpdir, "linklink")
-       err = os.Symlink(filelink, linklink)
-       if err != nil {
+       if err := os.Symlink(filelink, linklink); err != nil {
                t.Fatal(err)
        }
        testSymlinkStats(t, linklink, false)
@@ -252,20 +236,13 @@ func TestFileAndSymlinkStats(t *testing.T) {
 func TestSymlinkWithTrailingSlash(t *testing.T) {
        testenv.MustHaveSymlink(t)
 
-       tmpdir, err := os.MkdirTemp("", "TestSymlinkWithTrailingSlash")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(tmpdir)
-
+       tmpdir := t.TempDir()
        dir := filepath.Join(tmpdir, "dir")
-       err = os.Mkdir(dir, 0777)
-       if err != nil {
+       if err := os.Mkdir(dir, 0777); err != nil {
                t.Fatal(err)
        }
        dirlink := filepath.Join(tmpdir, "link")
-       err = os.Symlink(dir, dirlink)
-       if err != nil {
+       if err := os.Symlink(dir, dirlink); err != nil {
                t.Fatal(err)
        }
        dirlinkWithSlash := dirlink + string(os.PathSeparator)
index 7873bf9e95dd2873d8552aac1cbb1c10b21df651..6ae26ad540fac66c5d051a095657d2c76f8aa9d3 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris
 
 package os
index c09b1ac202889a2f86416dcee0b9f92165faf9a2..ab23d8111d3b4e8bf8f2df3e21b84b59f9f87707 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || (js && wasm) || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd js,wasm netbsd openbsd solaris
 
 package os
index c15850692cd75470888bde254afbe5268e674617..9979b43e8e69d011470c91da9e4521cfbe7fe9f5 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !aix && !darwin && !dragonfly && !freebsd && (!js || !wasm) && !netbsd && !openbsd && !solaris
 // +build !aix
 // +build !darwin
 // +build !dragonfly
index cba9fa3e8d41de985a6f6c45eb293b4be322ea2f..35643e0d2f1bfa98da184063a52b2e2877f56295 100644 (file)
@@ -6,28 +6,34 @@
 
 package os
 
-// Convert integer to decimal string
-func itoa(val int) string {
+// itox converts val (an int) to a hexdecimal string.
+func itox(val int) string {
        if val < 0 {
-               return "-" + uitoa(uint(-val))
+               return "-" + uitox(uint(-val))
        }
-       return uitoa(uint(val))
+       return uitox(uint(val))
 }
 
-// Convert unsigned integer to decimal string
-func uitoa(val uint) string {
+const hex = "0123456789abcdef"
+
+// uitox converts val (a uint) to a hexdecimal string.
+func uitox(val uint) string {
        if val == 0 { // avoid string allocation
-               return "0"
+               return "0x0"
        }
-       var buf [20]byte // big enough for 64bit value base 10
+       var buf [20]byte // big enough for 64bit value base 16 + 0x
        i := len(buf) - 1
-       for val >= 10 {
-               q := val / 10
-               buf[i] = byte('0' + val - q*10)
+       for val >= 16 {
+               q := val / 16
+               buf[i] = hex[val%16]
                i--
                val = q
        }
-       // val < 10
-       buf[i] = byte('0' + val)
+       // val < 16
+       buf[i] = hex[val%16]
+       i--
+       buf[i] = 'x'
+       i--
+       buf[i] = '0'
        return string(buf[i:])
 }
index b1698f5d4c763cb84ef0758e2baceaa7799fa590..1e245eb53a2d947f2b0d48252a59099c5e947fcc 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || (js && wasm) || netbsd || openbsd
 // +build darwin dragonfly freebsd js,wasm netbsd openbsd
 
 package os
index e860654f81204fbc54221282c43a044d4e11c3fe..4d6a64e8ebeaec86baadf818747eab59e825b504 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build js && wasm
 // +build js,wasm
 
 package os
index 37b5a47d2e289bec08081ab22214e7ec884e33d8..aab683e4db85c900abfb0742938c58f8863a8618 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package os
index 1ad44f1163fa58b90eca41cf9b49d55270cd60da..5b681fcebfea1799decbbd709a6ca6ee304215ef 100644 (file)
@@ -4,7 +4,10 @@
 
 package os
 
-import "errors"
+import (
+       "errors"
+       "internal/itoa"
+)
 
 // fastrand provided by runtime.
 // We generate random temporary file names so that there's a good
@@ -13,7 +16,7 @@ import "errors"
 func fastrand() uint32
 
 func nextRandom() string {
-       return uitoa(uint(fastrand()))
+       return itoa.Uitoa(uint(fastrand()))
 }
 
 // CreateTemp creates a new temporary file in the directory dir,
index 0a39f463336a128d889bbdd70661ac5209cf38b9..6d65e420f044ef5df3f606fb3b1aab93fbd57348 100644 (file)
@@ -2,9 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !js
-// +build !plan9
-// +build !windows
+//go:build !js && !plan9 && !windows
+// +build !js,!plan9,!windows
 
 package os_test
 
index c0259ae0e8411f791fadfd3a57ed3f6d9c44620b..e9b8b8ba3ac7af2de64026385ee26881f21d8277 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !windows
-// +build !plan9
+//go:build !windows && !plan9
+// +build !windows,!plan9
 
 package os
 
index eb6ab505ce84da23656e78ff5342f35b130d0a76..3f4014c36334e0704f5584f6c4f0be74151b8006 100644 (file)
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build (aix || darwin || dragonfly || freebsd || hurd || (!android && linux) || netbsd || openbsd || solaris) && cgo && !osusergo
 // +build aix darwin dragonfly freebsd hurd !android,linux netbsd openbsd solaris
-// +build cgo,!osusergo
+// +build cgo
+// +build !osusergo
 
 package user
 
index 1d341aa427d4cb42aa794efbf09a844e4003a041..9ec32b3a7889694953d795b8c811fd5500478970 100644 (file)
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build (darwin || dragonfly || freebsd || (!android && linux) || netbsd || openbsd || solaris) && cgo && !osusergo
 // +build darwin dragonfly freebsd !android,linux netbsd openbsd solaris
-// +build cgo,!osusergo
+// +build cgo
+// +build !osusergo
 
 package user
 
index 5b9f3f9a1d01a00b10fdcae485f24f569c3cf41f..93feb80924ce943dee17fdb18dd2358a468c0261 100644 (file)
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build cgo && !osusergo
+// +build cgo,!osusergo
+
 package user
 
 import "fmt"
similarity index 70%
rename from libgo/go/os/user/listgroups_solaris.go
rename to libgo/go/os/user/listgroups_illumos.go
index f3cbf6ce4a0bac532dfb5360ae72b50a02171e07..d25e0339b99593d909c012cbdc274de242f68dad 100644 (file)
@@ -1,11 +1,12 @@
-// Copyright 2016 The Go Authors. All rights reserved.
+// Copyright 2021 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build cgo && !osusergo
 // +build cgo,!osusergo
 
 // Even though this file requires no C, it is used to provide a
-// listGroup stub because all the other Solaris calls work.  Otherwise,
+// listGroup stub because all the other illumos calls work.  Otherwise,
 // this stub will conflict with the lookup_stubs.go fallback.
 
 package user
@@ -13,5 +14,5 @@ package user
 import "fmt"
 
 func listGroups(u *User) ([]string, error) {
-       return nil, fmt.Errorf("user: list groups for %s: not supported on Solaris", u.Username)
+       return nil, fmt.Errorf("user: list groups for %s: not supported on illumos", u.Username)
 }
index af04c0518f2d9515367b789f0bdaab389e0cc594..38bf807f52a5f3b3e8a5604138a4aeccce6e5fdc 100644 (file)
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build dragonfly darwin freebsd hurd !android,linux netbsd openbsd
-// +build cgo,!osusergo
+//go:build (dragonfly || darwin || freebsd || hurd || (!android && linux) || netbsd || openbsd || (solaris && !illumos)) && cgo && !osusergo
+// +build dragonfly darwin freebsd hurd !android,linux netbsd openbsd solaris,!illumos
+// +build cgo
+// +build !osusergo
 
 package user
 
index 8ca30b8c274709181a498be767a8ae6d0a17bc1a..151aab49c203d7a0f75b418941819aa69ad634e1 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build android
 // +build android
 
 package user
index 178d814dda07f581267b5684ea8d5f352559b8e8..c975a11964c11c83d7e6b721bc16a62ac00f14bf 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build (!cgo && !windows && !plan9) || android || (osusergo && !windows && !plan9)
 // +build !cgo,!windows,!plan9 android osusergo,!windows,!plan9
 
 package user
index 0f5e82d86f8918646cca7bf2e0e1619d007fc13a..28b96340e15378be85942ecfb680e882f2b5e5e8 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build (aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || (!android && linux) || netbsd || openbsd || solaris) && (!cgo || osusergo)
 // +build aix darwin dragonfly freebsd hurd js,wasm !android,linux netbsd openbsd solaris
 // +build !cgo osusergo
 
@@ -32,23 +33,72 @@ type lineFunc func(line []byte) (v interface{}, err error)
 // readColonFile parses r as an /etc/group or /etc/passwd style file, running
 // fn for each row. readColonFile returns a value, an error, or (nil, nil) if
 // the end of the file is reached without a match.
-func readColonFile(r io.Reader, fn lineFunc) (v interface{}, err error) {
-       bs := bufio.NewScanner(r)
-       for bs.Scan() {
-               line := bs.Bytes()
+//
+// readCols is the minimum number of colon-separated fields that will be passed
+// to fn; in a long line additional fields may be silently discarded.
+func readColonFile(r io.Reader, fn lineFunc, readCols int) (v interface{}, err error) {
+       rd := bufio.NewReader(r)
+
+       // Read the file line-by-line.
+       for {
+               var isPrefix bool
+               var wholeLine []byte
+
+               // Read the next line. We do so in chunks (as much as reader's
+               // buffer is able to keep), check if we read enough columns
+               // already on each step and store final result in wholeLine.
+               for {
+                       var line []byte
+                       line, isPrefix, err = rd.ReadLine()
+
+                       if err != nil {
+                               // We should return (nil, nil) if EOF is reached
+                               // without a match.
+                               if err == io.EOF {
+                                       err = nil
+                               }
+                               return nil, err
+                       }
+
+                       // Simple common case: line is short enough to fit in a
+                       // single reader's buffer.
+                       if !isPrefix && len(wholeLine) == 0 {
+                               wholeLine = line
+                               break
+                       }
+
+                       wholeLine = append(wholeLine, line...)
+
+                       // Check if we read the whole line (or enough columns)
+                       // already.
+                       if !isPrefix || bytes.Count(wholeLine, []byte{':'}) >= readCols {
+                               break
+                       }
+               }
+
                // There's no spec for /etc/passwd or /etc/group, but we try to follow
                // the same rules as the glibc parser, which allows comments and blank
                // space at the beginning of a line.
-               line = bytes.TrimSpace(line)
-               if len(line) == 0 || line[0] == '#' {
+               wholeLine = bytes.TrimSpace(wholeLine)
+               if len(wholeLine) == 0 || wholeLine[0] == '#' {
                        continue
                }
-               v, err = fn(line)
+               v, err = fn(wholeLine)
                if v != nil || err != nil {
                        return
                }
+
+               // If necessary, skip the rest of the line
+               for ; isPrefix; _, isPrefix, err = rd.ReadLine() {
+                       if err != nil {
+                               // We should return (nil, nil) if EOF is reached without a match.
+                               if err == io.EOF {
+                                       err = nil
+                               }
+                               return nil, err
+                       }
+               }
        }
-       return nil, bs.Err()
 }
 
 func matchGroupIndexValue(value string, idx int) lineFunc {
@@ -79,7 +129,7 @@ func matchGroupIndexValue(value string, idx int) lineFunc {
 }
 
 func findGroupId(id string, r io.Reader) (*Group, error) {
-       if v, err := readColonFile(r, matchGroupIndexValue(id, 2)); err != nil {
+       if v, err := readColonFile(r, matchGroupIndexValue(id, 2), 3); err != nil {
                return nil, err
        } else if v != nil {
                return v.(*Group), nil
@@ -88,7 +138,7 @@ func findGroupId(id string, r io.Reader) (*Group, error) {
 }
 
 func findGroupName(name string, r io.Reader) (*Group, error) {
-       if v, err := readColonFile(r, matchGroupIndexValue(name, 0)); err != nil {
+       if v, err := readColonFile(r, matchGroupIndexValue(name, 0), 3); err != nil {
                return nil, err
        } else if v != nil {
                return v.(*Group), nil
@@ -143,7 +193,7 @@ func findUserId(uid string, r io.Reader) (*User, error) {
        if e != nil {
                return nil, errors.New("user: invalid userid " + uid)
        }
-       if v, err := readColonFile(r, matchUserIndexValue(uid, 2)); err != nil {
+       if v, err := readColonFile(r, matchUserIndexValue(uid, 2), 6); err != nil {
                return nil, err
        } else if v != nil {
                return v.(*User), nil
@@ -152,7 +202,7 @@ func findUserId(uid string, r io.Reader) (*User, error) {
 }
 
 func findUsername(name string, r io.Reader) (*User, error) {
-       if v, err := readColonFile(r, matchUserIndexValue(name, 0)); err != nil {
+       if v, err := readColonFile(r, matchUserIndexValue(name, 0), 6); err != nil {
                return nil, err
        } else if v != nil {
                return v.(*User), nil
index 72d3b4753445b081fc7fb638eb33a3fc5155ed2a..060cfe186f5ced2d288611965300d1163bda5571 100644 (file)
@@ -2,18 +2,20 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build (aix || darwin || dragonfly || freebsd || (!android && linux) || netbsd || openbsd || solaris) && !cgo
 // +build aix darwin dragonfly freebsd !android,linux netbsd openbsd solaris
 // +build !cgo
 
 package user
 
 import (
+       "fmt"
        "reflect"
        "strings"
        "testing"
 )
 
-const testGroupFile = `# See the opendirectoryd(8) man page for additional 
+var testGroupFile = `# See the opendirectoryd(8) man page for additional 
 # information about Open Directory.
 ##
 nobody:*:-2:
@@ -29,7 +31,7 @@ daemon:*:1:root
 # comment:*:4:found
      # comment:*:4:found
 kmem:*:2:root
-`
+` + largeGroup()
 
 var groupTests = []struct {
        in   string
@@ -48,9 +50,20 @@ var groupTests = []struct {
        {testGroupFile, "invalidgid", ""},
        {testGroupFile, "indented", "7"},
        {testGroupFile, "# comment", ""},
+       {testGroupFile, "largegroup", "1000"},
        {"", "emptyfile", ""},
 }
 
+// Generate a proper "largegroup" entry for testGroupFile string
+func largeGroup() (res string) {
+       var b strings.Builder
+       b.WriteString("largegroup:x:1000:user1")
+       for i := 2; i <= 7500; i++ {
+               fmt.Fprintf(&b, ",user%d", i)
+       }
+       return b.String()
+}
+
 func TestFindGroupName(t *testing.T) {
        for _, tt := range groupTests {
                got, err := findGroupName(tt.name, strings.NewReader(tt.in))
index 8c4c817c2b63cd1a0d798b4d3cb91f7274423ec7..49920317bed93b9c7c32baea3d4f809c2127f538 100644 (file)
@@ -132,7 +132,7 @@ func TestGroupIds(t *testing.T) {
        if runtime.GOOS == "aix" {
                t.Skip("skipping GroupIds, see golang.org/issue/30563")
        }
-       if runtime.GOOS == "solaris" || runtime.GOOS == "illumos" {
+       if runtime.GOOS == "illumos" {
                t.Skip("skipping GroupIds, see golang.org/issue/14709")
        }
        user, err := Current()
index cb875abdbb4849703c6f05e265ea4e8be3e0e445..783a66f77e08a1672de0af1f5973030ea2434762 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build aix darwin dragonfly hurd js,wasm netbsd openbsd solaris
+//go:build aix || darwin || hurd || (js && wasm) || openbsd || solaris
+// +build aix darwin hurd js,wasm openbsd solaris
 
 package os
 
index 5420b2db732ab184b43bd787758c95e4f519ec85..45b370a802e8ae1ae14f76d138085e761d35c0b4 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build freebsd
+//go:build dragonfly || freebsd || netbsd
+// +build dragonfly freebsd netbsd
 
 package os
 
@@ -22,9 +23,9 @@ func (p *Process) blockUntilWaitable() (bool, error) {
                // The arguments on 32-bit FreeBSD look like the following:
                // - freebsd32_wait6_args{ idtype, id1, id2, status, options, wrusage, info } or
                // - freebsd32_wait6_args{ idtype, pad, id1, id2, status, options, wrusage, info } when PAD64_REQUIRED=1 on ARM, MIPS or PowerPC
-               if runtime.GOARCH == "386" {
+               if runtime.GOOS == "freebsd" && runtime.GOARCH == "386" {
                        _, _, errno = syscall.Syscall9(syscall.SYS_WAIT6, _P_PID, uintptr(p.Pid), 0, 0, syscall.WEXITED|syscall.WNOWAIT, 0, 0, 0, 0)
-               } else if runtime.GOARCH == "arm" {
+               } else if runtime.GOOS == "freebsd" && runtime.GOARCH == "arm" {
                        _, _, errno = syscall.Syscall9(syscall.SYS_WAIT6, _P_PID, 0, uintptr(p.Pid), 0, 0, syscall.WEXITED|syscall.WNOWAIT, 0, 0, 0)
                } else {
                        _, _, errno = syscall.Syscall6(syscall.SYS_WAIT6, _P_PID, uintptr(p.Pid), 0, syscall.WEXITED|syscall.WNOWAIT, 0, 0)
@@ -34,7 +35,9 @@ func (p *Process) blockUntilWaitable() (bool, error) {
                }
        }
        runtime.KeepAlive(p)
-       if errno != 0 {
+       if errno == syscall.ENOSYS {
+               return false, nil
+       } else if errno != 0 {
                return false, NewSyscallError("wait6", errno)
        }
        return true, nil
index 2c39f9bcd94febb5a47b01e1196a5df286b656c1..d7c97518b7a72c755e714f1725d1e21fd5277de1 100644 (file)
@@ -5,6 +5,7 @@
 // We used to used this code for Darwin, but according to issue #19314
 // waitid returns if the process is stopped, even when using WEXITED.
 
+//go:build linux
 // +build linux
 
 package os
@@ -22,7 +23,7 @@ const _P_PID = 1
 // It does not actually call p.Wait.
 func (p *Process) blockUntilWaitable() (bool, error) {
        // The waitid system call expects a pointer to a siginfo_t,
-       // which is 128 bytes on all GNU/Linux systems.
+       // which is 128 bytes on all Linux systems.
        // On darwin/amd64, it requires 104 bytes.
        // We don't care about the values it returns.
        var siginfo [16]uint64
index c9d694451889b8aee80e9029bf082fee2da3d3dd..4ce10095e67360e21f62352d7bce451e93cc69ae 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !windows && !plan9
 // +build !windows,!plan9
 
 package filepath_test
index c8a818fd6e9a739cd91ef4eceecf89d68d4a9686..d72efcebe6130505a2c30f4ddeb081291a63b011 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !windows && !plan9
 // +build !windows,!plan9
 
 package filepath_test
index 0204225584aebffa610c5474f02865bb4c826de9..3d90982cab92d9b06de3af0e1901a1541521ee27 100644 (file)
@@ -182,12 +182,7 @@ var globSymlinkTests = []struct {
 func TestGlobSymlink(t *testing.T) {
        testenv.MustHaveSymlink(t)
 
-       tmpDir, err := os.MkdirTemp("", "globsymlink")
-       if err != nil {
-               t.Fatal("creating temp dir:", err)
-       }
-       defer os.RemoveAll(tmpDir)
-
+       tmpDir := t.TempDir()
        for _, tt := range globSymlinkTests {
                path := Join(tmpDir, tt.path)
                dest := Join(tmpDir, tt.dest)
@@ -268,18 +263,7 @@ func TestWindowsGlob(t *testing.T) {
                t.Skipf("skipping windows specific test")
        }
 
-       tmpDir, err := os.MkdirTemp("", "TestWindowsGlob")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(tmpDir)
-
-       // /tmp may itself be a symlink
-       tmpDir, err = EvalSymlinks(tmpDir)
-       if err != nil {
-               t.Fatal("eval symlink for tmp dir:", err)
-       }
-
+       tmpDir := tempDirCanonical(t)
        if len(tmpDir) < 3 {
                t.Fatalf("tmpDir path %q is too short", tmpDir)
        }
@@ -324,15 +308,13 @@ func TestWindowsGlob(t *testing.T) {
        // test absolute paths
        for _, test := range tests {
                var p string
-               err = test.globAbs(tmpDir, tmpDir)
-               if err != nil {
+               if err := test.globAbs(tmpDir, tmpDir); err != nil {
                        t.Error(err)
                }
                // test C:\*Documents and Settings\...
                p = tmpDir
                p = strings.Replace(p, `:\`, `:\*`, 1)
-               err = test.globAbs(tmpDir, p)
-               if err != nil {
+               if err := test.globAbs(tmpDir, p); err != nil {
                        t.Error(err)
                }
                // test C:\Documents and Settings*\...
@@ -340,8 +322,7 @@ func TestWindowsGlob(t *testing.T) {
                p = strings.Replace(p, `:\`, `:`, 1)
                p = strings.Replace(p, `\`, `*\`, 1)
                p = strings.Replace(p, `:`, `:\`, 1)
-               err = test.globAbs(tmpDir, p)
-               if err != nil {
+               if err := test.globAbs(tmpDir, p); err != nil {
                        t.Error(err)
                }
        }
index 2e7b439355a669bf830bab9f5131a52dbaceced9..b56534deadecfe27ae4bf9afab06fe7182c758b1 100644 (file)
@@ -275,7 +275,11 @@ func Rel(basepath, targpath string) (string, error) {
        targ = targ[len(targVol):]
        if base == "." {
                base = ""
+       } else if base == "" && volumeNameLen(baseVol) > 2 /* isUNC */ {
+               // Treat any targetpath matching `\\host\share` basepath as absolute path.
+               base = string(Separator)
        }
+
        // Can't use IsAbs - `\a` and `a` are both relative in Windows.
        baseSlashed := len(base) > 0 && base[0] == Separator
        targSlashed := len(targ) > 0 && targ[0] == Separator
@@ -336,7 +340,7 @@ func Rel(basepath, targpath string) (string, error) {
 // as an error by any function.
 var SkipDir error = fs.SkipDir
 
-// WalkFunc is the type of the function called by Walk to visit each each
+// WalkFunc is the type of the function called by Walk to visit each
 // file or directory.
 //
 // The path argument contains the argument to Walk as a prefix.
index 51ea6845b91285f8a21fe1f54978dffc3446c803..1be17df04662cbf06d4566927e42c55cd2bc4b14 100644 (file)
@@ -413,6 +413,25 @@ func mark(d fs.DirEntry, err error, errors *[]error, clear bool) error {
        return nil
 }
 
+// chdir changes the current working directory to the named directory,
+// and then restore the original working directory at the end of the test.
+func chdir(t *testing.T, dir string) {
+       olddir, err := os.Getwd()
+       if err != nil {
+               t.Fatalf("getwd %s: %v", dir, err)
+       }
+       if err := os.Chdir(dir); err != nil {
+               t.Fatalf("chdir %s: %v", dir, err)
+       }
+
+       t.Cleanup(func() {
+               if err := os.Chdir(olddir); err != nil {
+                       t.Errorf("restore original working directory %s: %v", olddir, err)
+                       os.Exit(1)
+               }
+       })
+}
+
 func chtmpdir(t *testing.T) (restore func()) {
        oldwd, err := os.Getwd()
        if err != nil {
@@ -433,6 +452,19 @@ func chtmpdir(t *testing.T) (restore func()) {
        }
 }
 
+// tempDirCanonical returns a temporary directory for the test to use, ensuring
+// that the returned path does not contain symlinks.
+func tempDirCanonical(t *testing.T) string {
+       dir := t.TempDir()
+
+       cdir, err := filepath.EvalSymlinks(dir)
+       if err != nil {
+               t.Errorf("tempDirCanonical: %v", err)
+       }
+
+       return cdir
+}
+
 func TestWalk(t *testing.T) {
        walk := func(root string, fn fs.WalkDirFunc) error {
                return filepath.Walk(root, func(path string, info fs.FileInfo, err error) error {
@@ -461,11 +493,7 @@ func testWalk(t *testing.T, walk func(string, fs.WalkDirFunc) error, errVisit in
                defer restore()
        }
 
-       tmpDir, err := os.MkdirTemp("", "TestWalk")
-       if err != nil {
-               t.Fatal("creating temp dir:", err)
-       }
-       defer os.RemoveAll(tmpDir)
+       tmpDir := t.TempDir()
 
        origDir, err := os.Getwd()
        if err != nil {
@@ -565,11 +593,7 @@ func touch(t *testing.T, name string) {
 }
 
 func TestWalkSkipDirOnFile(t *testing.T) {
-       td, err := os.MkdirTemp("", "walktest")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(td)
+       td := t.TempDir()
 
        if err := os.MkdirAll(filepath.Join(td, "dir"), 0755); err != nil {
                t.Fatal(err)
@@ -593,7 +617,7 @@ func TestWalkSkipDirOnFile(t *testing.T) {
        check := func(t *testing.T, walk func(root string) error, root string) {
                t.Helper()
                sawFoo2 = false
-               err = walk(root)
+               err := walk(root)
                if err != nil {
                        t.Fatal(err)
                }
@@ -615,11 +639,7 @@ func TestWalkSkipDirOnFile(t *testing.T) {
 }
 
 func TestWalkFileError(t *testing.T) {
-       td, err := os.MkdirTemp("", "walktest")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(td)
+       td := t.TempDir()
 
        touch(t, filepath.Join(td, "foo"))
        touch(t, filepath.Join(td, "bar"))
@@ -640,7 +660,7 @@ func TestWalkFileError(t *testing.T) {
                return os.Lstat(path)
        }
        got := map[string]error{}
-       err = filepath.Walk(td, func(path string, fi fs.FileInfo, err error) error {
+       err := filepath.Walk(td, func(path string, fi fs.FileInfo, err error) error {
                rel, _ := filepath.Rel(td, path)
                got[filepath.ToSlash(rel)] = err
                return nil
@@ -894,14 +914,11 @@ func testEvalSymlinksAfterChdir(t *testing.T, wd, path, want string) {
 func TestEvalSymlinks(t *testing.T) {
        testenv.MustHaveSymlink(t)
 
-       tmpDir, err := os.MkdirTemp("", "evalsymlink")
-       if err != nil {
-               t.Fatal("creating temp dir:", err)
-       }
-       defer os.RemoveAll(tmpDir)
+       tmpDir := t.TempDir()
 
        // /tmp may itself be a symlink! Avoid the confusion, although
        // it means trusting the thing we're testing.
+       var err error
        tmpDir, err = filepath.EvalSymlinks(tmpDir)
        if err != nil {
                t.Fatal("eval symlink for tmp dir:", err)
@@ -980,14 +997,10 @@ func TestEvalSymlinksIsNotExist(t *testing.T) {
 func TestIssue13582(t *testing.T) {
        testenv.MustHaveSymlink(t)
 
-       tmpDir, err := os.MkdirTemp("", "issue13582")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(tmpDir)
+       tmpDir := t.TempDir()
 
        dir := filepath.Join(tmpDir, "dir")
-       err = os.Mkdir(dir, 0755)
+       err := os.Mkdir(dir, 0755)
        if err != nil {
                t.Fatal(err)
        }
@@ -1067,12 +1080,7 @@ var absTests = []string{
 }
 
 func TestAbs(t *testing.T) {
-       root, err := os.MkdirTemp("", "TestAbs")
-       if err != nil {
-               t.Fatal("TempDir failed: ", err)
-       }
-       defer os.RemoveAll(root)
-
+       root := t.TempDir()
        wd, err := os.Getwd()
        if err != nil {
                t.Fatal("getwd failed: ", err)
@@ -1138,11 +1146,7 @@ func TestAbs(t *testing.T) {
 // We test it separately from all other absTests because the empty string is not
 // a valid path, so it can't be used with os.Stat.
 func TestAbsEmptyString(t *testing.T) {
-       root, err := os.MkdirTemp("", "TestAbsEmptyString")
-       if err != nil {
-               t.Fatal("TempDir failed: ", err)
-       }
-       defer os.RemoveAll(root)
+       root := t.TempDir()
 
        wd, err := os.Getwd()
        if err != nil {
@@ -1230,6 +1234,7 @@ var winreltests = []RelTests{
        {`C:\Projects`, `c:\projects\src`, `src`},
        {`C:\Projects`, `c:\projects`, `.`},
        {`C:\Projects\a\..`, `c:\projects`, `.`},
+       {`\\host\share`, `\\host\share\file.txt`, `file.txt`},
 }
 
 func TestRel(t *testing.T) {
@@ -1360,11 +1365,7 @@ func TestBug3486(t *testing.T) { // https://golang.org/issue/3486
 }
 
 func testWalkSymlink(t *testing.T, mklink func(target, link string) error) {
-       tmpdir, err := os.MkdirTemp("", "testWalkSymlink")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(tmpdir)
+       tmpdir := t.TempDir()
 
        wd, err := os.Getwd()
        if err != nil {
@@ -1410,14 +1411,10 @@ func TestWalkSymlink(t *testing.T) {
 }
 
 func TestIssue29372(t *testing.T) {
-       tmpDir, err := os.MkdirTemp("", "TestIssue29372")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(tmpDir)
+       tmpDir := t.TempDir()
 
        path := filepath.Join(tmpDir, "file.txt")
-       err = os.WriteFile(path, nil, 0644)
+       err := os.WriteFile(path, nil, 0644)
        if err != nil {
                t.Fatal(err)
        }
@@ -1446,11 +1443,7 @@ func TestEvalSymlinksAboveRoot(t *testing.T) {
 
        t.Parallel()
 
-       tmpDir, err := os.MkdirTemp("", "TestEvalSymlinksAboveRoot")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(tmpDir)
+       tmpDir := t.TempDir()
 
        evalTmpDir, err := filepath.EvalSymlinks(tmpDir)
        if err != nil {
@@ -1480,11 +1473,16 @@ func TestEvalSymlinksAboveRoot(t *testing.T) {
        // Try different numbers of "..".
        for _, i := range []int{c, c + 1, c + 2} {
                check := strings.Join([]string{evalTmpDir, strings.Join(dd[:i], string(os.PathSeparator)), evalTmpDir[len(vol)+1:], "b", "file"}, string(os.PathSeparator))
-               if resolved, err := filepath.EvalSymlinks(check); err != nil {
+               resolved, err := filepath.EvalSymlinks(check)
+               switch {
+               case runtime.GOOS == "darwin" && errors.Is(err, fs.ErrNotExist):
+                       // On darwin, the temp dir is sometimes cleaned up mid-test (issue 37910).
+                       testenv.SkipFlaky(t, 37910)
+               case err != nil:
                        t.Errorf("EvalSymlinks(%q) failed: %v", check, err)
-               } else if !strings.HasSuffix(resolved, wantSuffix) {
+               case !strings.HasSuffix(resolved, wantSuffix):
                        t.Errorf("EvalSymlinks(%q) = %q does not end with %q", check, resolved, wantSuffix)
-               } else {
+               default:
                        t.Logf("EvalSymlinks(%q) = %q", check, resolved)
                }
        }
@@ -1499,16 +1497,7 @@ func TestEvalSymlinksAboveRootChdir(t *testing.T) {
                t.Fatal(err)
        }
        defer os.RemoveAll(tmpDir)
-
-       wd, err := os.Getwd()
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.Chdir(wd)
-
-       if err := os.Chdir(tmpDir); err != nil {
-               t.Fatal(err)
-       }
+       chdir(t, tmpDir)
 
        subdir := filepath.Join("a", "b")
        if err := os.MkdirAll(subdir, 0777); err != nil {
index 57341ed7d90f18e9f3e6f5732ea144626bca0b55..b0a63914c1de63a1886c57358bd55eacb7d6c4b1 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris
 
 package filepath
index d20e63a987e9ad7a9986c5ecc05b4db5f92beb74..657945a81a3361797b7b4768b2fa8d721b0ccece 100644 (file)
@@ -1,3 +1,4 @@
+//go:build !windows
 // +build !windows
 
 package filepath
index 8342267a66b02fa14926aea86e2c0958ed5afc42..23adc4f15ea61f4731ad7d4e8dd0a39f127662e6 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build (linux && cgo) || (darwin && cgo) || (freebsd && cgo) || (hurd && cgo)
 // +build linux,cgo darwin,cgo freebsd,cgo hurd,cgo
 
 package plugin
index 0f9adb77b84bc68612197ee93589ca26a2c9a73d..215becc4be3d6074900885e0da767f44b3acf1ad 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build (!hurd && !linux && !freebsd && !darwin) || !cgo
 // +build !hurd,!linux,!freebsd,!darwin !cgo
 
 package plugin
index 30b79edaad7c4fc75915b2a8ed5c558b290c8f33..4ce912132c911f27219fb6d0f7057aeb1e33a50e 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !linux || (linux && !arm64)
 // +build !linux linux,!arm64
 
 package plugin_test
index c73ef471e55d15a869393586f5d20700e167deda..7fa815f3ad38ceeea00ca79463b37bf48160ba0b 100644 (file)
@@ -15,6 +15,8 @@ import (
        "math/rand"
        "os"
        . "reflect"
+       "reflect/internal/example1"
+       "reflect/internal/example2"
        "runtime"
        "sort"
        "strconv"
@@ -1945,6 +1947,22 @@ func BenchmarkCall(b *testing.B) {
        })
 }
 
+type myint int64
+
+func (i *myint) inc() {
+       *i = *i + 1
+}
+
+func BenchmarkCallMethod(b *testing.B) {
+       b.ReportAllocs()
+       z := new(myint)
+
+       v := ValueOf(z.inc)
+       for i := 0; i < b.N; i++ {
+               v.Call(nil)
+       }
+}
+
 func BenchmarkCallArgCopy(b *testing.B) {
        byteArray := func(n int) Value {
                return Zero(ArrayOf(n, TypeOf(byte(0))))
@@ -2903,6 +2921,7 @@ func TestFieldPkgPath(t *testing.T) {
                index    []int
                pkgPath  string
                embedded bool
+               exported bool
        }
 
        checkPkgPath := func(name string, s []pkgpathTest) {
@@ -2914,27 +2933,63 @@ func TestFieldPkgPath(t *testing.T) {
                        if got, want := f.Anonymous, test.embedded; got != want {
                                t.Errorf("%s: Field(%d).Anonymous = %v, want %v", name, test.index, got, want)
                        }
+                       if got, want := f.IsExported(), test.exported; got != want {
+                               t.Errorf("%s: Field(%d).IsExported = %v, want %v", name, test.index, got, want)
+                       }
                }
        }
 
        checkPkgPath("testStruct", []pkgpathTest{
-               {[]int{0}, "", false},             // Exported
-               {[]int{1}, "reflect_test", false}, // unexported
-               {[]int{2}, "", true},              // OtherPkgFields
-               {[]int{2, 0}, "", false},          // OtherExported
-               {[]int{2, 1}, "reflect", false},   // otherUnexported
-               {[]int{3}, "reflect_test", true},  // int
-               {[]int{4}, "reflect_test", true},  // *x
+               {[]int{0}, "", false, true},              // Exported
+               {[]int{1}, "reflect_test", false, false}, // unexported
+               {[]int{2}, "", true, true},               // OtherPkgFields
+               {[]int{2, 0}, "", false, true},           // OtherExported
+               {[]int{2, 1}, "reflect", false, false},   // otherUnexported
+               {[]int{3}, "reflect_test", true, false},  // int
+               {[]int{4}, "reflect_test", true, false},  // *x
        })
 
        type localOtherPkgFields OtherPkgFields
        typ = TypeOf(localOtherPkgFields{})
        checkPkgPath("localOtherPkgFields", []pkgpathTest{
-               {[]int{0}, "", false},        // OtherExported
-               {[]int{1}, "reflect", false}, // otherUnexported
+               {[]int{0}, "", false, true},         // OtherExported
+               {[]int{1}, "reflect", false, false}, // otherUnexported
        })
 }
 
+func TestMethodPkgPath(t *testing.T) {
+       type I interface {
+               x()
+               X()
+       }
+       typ := TypeOf((*interface {
+               I
+               y()
+               Y()
+       })(nil)).Elem()
+
+       tests := []struct {
+               name     string
+               pkgPath  string
+               exported bool
+       }{
+               {"X", "", true},
+               {"Y", "", true},
+               {"x", "reflect_test", false},
+               {"y", "reflect_test", false},
+       }
+
+       for _, test := range tests {
+               m, _ := typ.MethodByName(test.name)
+               if got, want := m.PkgPath, test.pkgPath; got != want {
+                       t.Errorf("MethodByName(%q).PkgPath = %q, want %q", test.name, got, want)
+               }
+               if got, want := m.IsExported(), test.exported; got != want {
+                       t.Errorf("MethodByName(%q).IsExported = %v, want %v", test.name, got, want)
+               }
+       }
+}
+
 func TestVariadicType(t *testing.T) {
        // Test example from Type documentation.
        var f func(x int, y ...float64)
@@ -3765,8 +3820,22 @@ type Empty struct{}
 type MyStruct struct {
        x int `some:"tag"`
 }
+type MyStruct1 struct {
+       x struct {
+               int `some:"bar"`
+       }
+}
+type MyStruct2 struct {
+       x struct {
+               int `some:"foo"`
+       }
+}
 type MyString string
 type MyBytes []byte
+type MyBytesArrayPtr0 *[0]byte
+type MyBytesArrayPtr *[4]byte
+type MyBytesArray0 [0]byte
+type MyBytesArray [4]byte
 type MyRunes []int32
 type MyFunc func()
 type MyByte byte
@@ -4073,6 +4142,30 @@ var convertTests = []struct {
        {V(MyString("runes♝")), V(MyRunes("runes♝"))},
        {V(MyRunes("runes♕")), V(MyString("runes♕"))},
 
+       // slice to array pointer
+       {V([]byte(nil)), V((*[0]byte)(nil))},
+       {V([]byte{}), V(new([0]byte))},
+       {V([]byte{7}), V(&[1]byte{7})},
+       {V(MyBytes([]byte(nil))), V((*[0]byte)(nil))},
+       {V(MyBytes([]byte{})), V(new([0]byte))},
+       {V(MyBytes([]byte{9})), V(&[1]byte{9})},
+       {V([]byte(nil)), V(MyBytesArrayPtr0(nil))},
+       {V([]byte{}), V(MyBytesArrayPtr0(new([0]byte)))},
+       {V([]byte{1, 2, 3, 4}), V(MyBytesArrayPtr(&[4]byte{1, 2, 3, 4}))},
+       {V(MyBytes([]byte{})), V(MyBytesArrayPtr0(new([0]byte)))},
+       {V(MyBytes([]byte{5, 6, 7, 8})), V(MyBytesArrayPtr(&[4]byte{5, 6, 7, 8}))},
+
+       {V([]byte(nil)), V((*MyBytesArray0)(nil))},
+       {V([]byte{}), V((*MyBytesArray0)(new([0]byte)))},
+       {V([]byte{1, 2, 3, 4}), V(&MyBytesArray{1, 2, 3, 4})},
+       {V(MyBytes([]byte(nil))), V((*MyBytesArray0)(nil))},
+       {V(MyBytes([]byte{})), V((*MyBytesArray0)(new([0]byte)))},
+       {V(MyBytes([]byte{5, 6, 7, 8})), V(&MyBytesArray{5, 6, 7, 8})},
+       {V(new([0]byte)), V(new(MyBytesArray0))},
+       {V(new(MyBytesArray0)), V(new([0]byte))},
+       {V(MyBytesArrayPtr0(nil)), V((*[0]byte)(nil))},
+       {V((*[0]byte)(nil)), V(MyBytesArrayPtr0(nil))},
+
        // named types and equal underlying types
        {V(new(int)), V(new(integer))},
        {V(new(integer)), V(new(int))},
@@ -4115,6 +4208,9 @@ var convertTests = []struct {
                x int `some:"bar"`
        }{}), V(MyStruct{})},
 
+       {V(MyStruct1{}), V(MyStruct2{})},
+       {V(MyStruct2{}), V(MyStruct1{})},
+
        // can convert *byte and *MyByte
        {V((*byte)(nil)), V((*MyByte)(nil))},
        {V((*MyByte)(nil)), V((*byte)(nil))},
@@ -4218,6 +4314,9 @@ func TestConvert(t *testing.T) {
 
                // vout1 represents the in value converted to the in type.
                v1 := tt.in
+               if !v1.CanConvert(t1) {
+                       t.Errorf("ValueOf(%T(%[1]v)).CanConvert(%s) = false, want true", tt.in.Interface(), t1)
+               }
                vout1 := v1.Convert(t1)
                out1 := vout1.Interface()
                if vout1.Type() != tt.in.Type() || !DeepEqual(out1, tt.in.Interface()) {
@@ -4225,11 +4324,17 @@ func TestConvert(t *testing.T) {
                }
 
                // vout2 represents the in value converted to the out type.
+               if !v1.CanConvert(t2) {
+                       t.Errorf("ValueOf(%T(%[1]v)).CanConvert(%s) = false, want true", tt.in.Interface(), t2)
+               }
                vout2 := v1.Convert(t2)
                out2 := vout2.Interface()
                if vout2.Type() != tt.out.Type() || !DeepEqual(out2, tt.out.Interface()) {
                        t.Errorf("ValueOf(%T(%[1]v)).Convert(%s) = %T(%[3]v), want %T(%[4]v)", tt.in.Interface(), t2, out2, tt.out.Interface())
                }
+               if got, want := vout2.Kind(), vout2.Type().Kind(); got != want {
+                       t.Errorf("ValueOf(%T(%[1]v)).Convert(%s) has internal kind %v want %v", tt.in.Interface(), t1, got, want)
+               }
 
                // vout3 represents a new value of the out type, set to vout2.  This makes
                // sure the converted value vout2 is really usable as a regular value.
@@ -4274,6 +4379,22 @@ func TestConvert(t *testing.T) {
        }
 }
 
+func TestConvertPanic(t *testing.T) {
+       s := make([]byte, 4)
+       p := new([8]byte)
+       v := ValueOf(s)
+       pt := TypeOf(p)
+       if !v.Type().ConvertibleTo(pt) {
+               t.Errorf("[]byte should be convertible to *[8]byte")
+       }
+       if v.CanConvert(pt) {
+               t.Errorf("slice with length 4 should not be convertible to *[8]byte")
+       }
+       shouldPanic("reflect: cannot convert slice with length 4 to pointer to array with length 8", func() {
+               _ = v.Convert(pt)
+       })
+}
+
 var gFloat32 float32
 
 func TestConvertNaNs(t *testing.T) {
@@ -4612,6 +4733,14 @@ func TestArrayOfDirectIface(t *testing.T) {
        }
 }
 
+// Ensure passing in negative lengths panics.
+// See https://golang.org/issue/43603
+func TestArrayOfPanicOnNegativeLength(t *testing.T) {
+       shouldPanic("reflect: negative length passed to ArrayOf", func() {
+               ArrayOf(-1, TypeOf(byte(0)))
+       })
+}
+
 func TestSliceOf(t *testing.T) {
        // check construction and use of type not in binary
        type T int
@@ -6357,148 +6486,142 @@ func clobber() {
        runtime.GC()
 }
 
-type funcLayoutTest struct {
-       rcvr, t                  Type
-       size, argsize, retOffset uintptr
-       stack                    []byte // pointer bitmap: 1 is pointer, 0 is scalar
-       gc                       []byte
-}
-
-var funcLayoutTests []funcLayoutTest
-
-func init() {
-       var argAlign uintptr = PtrSize
-       roundup := func(x uintptr, a uintptr) uintptr {
-               return (x + a - 1) / a * a
-       }
-
-       funcLayoutTests = append(funcLayoutTests,
-               funcLayoutTest{
-                       nil,
-                       ValueOf(func(a, b string) string { return "" }).Type(),
-                       6 * PtrSize,
-                       4 * PtrSize,
-                       4 * PtrSize,
-                       []byte{1, 0, 1, 0, 1},
-                       []byte{1, 0, 1, 0, 1},
-               })
+/*
 
+func TestFuncLayout(t *testing.T) {
+       align := func(x uintptr) uintptr {
+               return (x + PtrSize - 1) &^ (PtrSize - 1)
+       }
        var r []byte
        if PtrSize == 4 {
                r = []byte{0, 0, 0, 1}
        } else {
                r = []byte{0, 0, 1}
        }
-       funcLayoutTests = append(funcLayoutTests,
-               funcLayoutTest{
-                       nil,
-                       ValueOf(func(a, b, c uint32, p *byte, d uint16) {}).Type(),
-                       roundup(roundup(3*4, PtrSize)+PtrSize+2, argAlign),
-                       roundup(3*4, PtrSize) + PtrSize + 2,
-                       roundup(roundup(3*4, PtrSize)+PtrSize+2, argAlign),
-                       r,
-                       r,
-               })
-
-       funcLayoutTests = append(funcLayoutTests,
-               funcLayoutTest{
-                       nil,
-                       ValueOf(func(a map[int]int, b uintptr, c interface{}) {}).Type(),
-                       4 * PtrSize,
-                       4 * PtrSize,
-                       4 * PtrSize,
-                       []byte{1, 0, 1, 1},
-                       []byte{1, 0, 1, 1},
-               })
 
        type S struct {
                a, b uintptr
                c, d *byte
        }
-       funcLayoutTests = append(funcLayoutTests,
-               funcLayoutTest{
-                       nil,
-                       ValueOf(func(a S) {}).Type(),
-                       4 * PtrSize,
-                       4 * PtrSize,
-                       4 * PtrSize,
-                       []byte{0, 0, 1, 1},
-                       []byte{0, 0, 1, 1},
-               })
-
-       funcLayoutTests = append(funcLayoutTests,
-               funcLayoutTest{
-                       ValueOf((*byte)(nil)).Type(),
-                       ValueOf(func(a uintptr, b *int) {}).Type(),
-                       roundup(3*PtrSize, argAlign),
-                       3 * PtrSize,
-                       roundup(3*PtrSize, argAlign),
-                       []byte{1, 0, 1},
-                       []byte{1, 0, 1},
-               })
 
-       funcLayoutTests = append(funcLayoutTests,
-               funcLayoutTest{
-                       nil,
-                       ValueOf(func(a uintptr) {}).Type(),
-                       roundup(PtrSize, argAlign),
-                       PtrSize,
-                       roundup(PtrSize, argAlign),
-                       []byte{},
-                       []byte{},
-               })
-
-       funcLayoutTests = append(funcLayoutTests,
-               funcLayoutTest{
-                       nil,
-                       ValueOf(func() uintptr { return 0 }).Type(),
-                       PtrSize,
-                       0,
-                       0,
-                       []byte{},
-                       []byte{},
-               })
-
-       funcLayoutTests = append(funcLayoutTests,
-               funcLayoutTest{
-                       ValueOf(uintptr(0)).Type(),
-                       ValueOf(func(a uintptr) {}).Type(),
-                       2 * PtrSize,
-                       2 * PtrSize,
-                       2 * PtrSize,
-                       []byte{1},
-                       []byte{1},
+       type test struct {
+               rcvr, typ                  Type
+               size, argsize, retOffset   uintptr
+               stack, gc, inRegs, outRegs []byte // pointer bitmap: 1 is pointer, 0 is scalar
+               intRegs, floatRegs         int
+               floatRegSize               uintptr
+       }
+       tests := []test{
+               {
+                       typ:       ValueOf(func(a, b string) string { return "" }).Type(),
+                       size:      6 * PtrSize,
+                       argsize:   4 * PtrSize,
+                       retOffset: 4 * PtrSize,
+                       stack:     []byte{1, 0, 1, 0, 1},
+                       gc:        []byte{1, 0, 1, 0, 1},
+               },
+               {
+                       typ:       ValueOf(func(a, b, c uint32, p *byte, d uint16) {}).Type(),
+                       size:      align(align(3*4) + PtrSize + 2),
+                       argsize:   align(3*4) + PtrSize + 2,
+                       retOffset: align(align(3*4) + PtrSize + 2),
+                       stack:     r,
+                       gc:        r,
+               },
+               {
+                       typ:       ValueOf(func(a map[int]int, b uintptr, c interface{}) {}).Type(),
+                       size:      4 * PtrSize,
+                       argsize:   4 * PtrSize,
+                       retOffset: 4 * PtrSize,
+                       stack:     []byte{1, 0, 1, 1},
+                       gc:        []byte{1, 0, 1, 1},
+               },
+               {
+                       typ:       ValueOf(func(a S) {}).Type(),
+                       size:      4 * PtrSize,
+                       argsize:   4 * PtrSize,
+                       retOffset: 4 * PtrSize,
+                       stack:     []byte{0, 0, 1, 1},
+                       gc:        []byte{0, 0, 1, 1},
+               },
+               {
+                       rcvr:      ValueOf((*byte)(nil)).Type(),
+                       typ:       ValueOf(func(a uintptr, b *int) {}).Type(),
+                       size:      3 * PtrSize,
+                       argsize:   3 * PtrSize,
+                       retOffset: 3 * PtrSize,
+                       stack:     []byte{1, 0, 1},
+                       gc:        []byte{1, 0, 1},
+               },
+               {
+                       typ:       ValueOf(func(a uintptr) {}).Type(),
+                       size:      PtrSize,
+                       argsize:   PtrSize,
+                       retOffset: PtrSize,
+                       stack:     []byte{},
+                       gc:        []byte{},
+               },
+               {
+                       typ:       ValueOf(func() uintptr { return 0 }).Type(),
+                       size:      PtrSize,
+                       argsize:   0,
+                       retOffset: 0,
+                       stack:     []byte{},
+                       gc:        []byte{},
+               },
+               {
+                       rcvr:      ValueOf(uintptr(0)).Type(),
+                       typ:       ValueOf(func(a uintptr) {}).Type(),
+                       size:      2 * PtrSize,
+                       argsize:   2 * PtrSize,
+                       retOffset: 2 * PtrSize,
+                       stack:     []byte{1},
+                       gc:        []byte{1},
                        // Note: this one is tricky, as the receiver is not a pointer. But we
                        // pass the receiver by reference to the autogenerated pointer-receiver
                        // version of the function.
-               })
-}
-
-func TestFuncLayout(t *testing.T) {
-       t.Skip("gccgo does not use funcLayout")
-       for _, lt := range funcLayoutTests {
-               typ, argsize, retOffset, stack, gc, ptrs := FuncLayout(lt.t, lt.rcvr)
-               if typ.Size() != lt.size {
-                       t.Errorf("funcLayout(%v, %v).size=%d, want %d", lt.t, lt.rcvr, typ.Size(), lt.size)
-               }
-               if argsize != lt.argsize {
-                       t.Errorf("funcLayout(%v, %v).argsize=%d, want %d", lt.t, lt.rcvr, argsize, lt.argsize)
-               }
-               if retOffset != lt.retOffset {
-                       t.Errorf("funcLayout(%v, %v).retOffset=%d, want %d", lt.t, lt.rcvr, retOffset, lt.retOffset)
-               }
-               if !bytes.Equal(stack, lt.stack) {
-                       t.Errorf("funcLayout(%v, %v).stack=%v, want %v", lt.t, lt.rcvr, stack, lt.stack)
-               }
-               if !bytes.Equal(gc, lt.gc) {
-                       t.Errorf("funcLayout(%v, %v).gc=%v, want %v", lt.t, lt.rcvr, gc, lt.gc)
-               }
-               if ptrs && len(stack) == 0 || !ptrs && len(stack) > 0 {
-                       t.Errorf("funcLayout(%v, %v) pointers flag=%v, want %v", lt.t, lt.rcvr, ptrs, !ptrs)
+               },
+               // TODO(mknyszek): Add tests for non-zero register count.
+       }
+       for _, lt := range tests {
+               name := lt.typ.String()
+               if lt.rcvr != nil {
+                       name = lt.rcvr.String() + "." + name
                }
+               t.Run(name, func(t *testing.T) {
+                       defer SetArgRegs(SetArgRegs(lt.intRegs, lt.floatRegs, lt.floatRegSize))
+
+                       typ, argsize, retOffset, stack, gc, inRegs, outRegs, ptrs := FuncLayout(lt.typ, lt.rcvr)
+                       if typ.Size() != lt.size {
+                               t.Errorf("funcLayout(%v, %v).size=%d, want %d", lt.typ, lt.rcvr, typ.Size(), lt.size)
+                       }
+                       if argsize != lt.argsize {
+                               t.Errorf("funcLayout(%v, %v).argsize=%d, want %d", lt.typ, lt.rcvr, argsize, lt.argsize)
+                       }
+                       if retOffset != lt.retOffset {
+                               t.Errorf("funcLayout(%v, %v).retOffset=%d, want %d", lt.typ, lt.rcvr, retOffset, lt.retOffset)
+                       }
+                       if !bytes.Equal(stack, lt.stack) {
+                               t.Errorf("funcLayout(%v, %v).stack=%v, want %v", lt.typ, lt.rcvr, stack, lt.stack)
+                       }
+                       if !bytes.Equal(gc, lt.gc) {
+                               t.Errorf("funcLayout(%v, %v).gc=%v, want %v", lt.typ, lt.rcvr, gc, lt.gc)
+                       }
+                       if !bytes.Equal(inRegs, lt.inRegs) {
+                               t.Errorf("funcLayout(%v, %v).inRegs=%v, want %v", lt.typ, lt.rcvr, inRegs, lt.inRegs)
+                       }
+                       if !bytes.Equal(outRegs, lt.outRegs) {
+                               t.Errorf("funcLayout(%v, %v).outRegs=%v, want %v", lt.typ, lt.rcvr, outRegs, lt.outRegs)
+                       }
+                       if ptrs && len(stack) == 0 || !ptrs && len(stack) > 0 {
+                               t.Errorf("funcLayout(%v, %v) pointers flag=%v, want %v", lt.typ, lt.rcvr, ptrs, !ptrs)
+                       }
+               })
        }
 }
 
+*/
+
 func verifyGCBits(t *testing.T, typ Type, bits []byte) {
        heapBits := GCBits(New(typ).Interface())
        if !bytes.Equal(heapBits, bits) {
@@ -6861,21 +6984,6 @@ func TestExported(t *testing.T) {
 }
 */
 
-type embed struct {
-       EmbedWithUnexpMeth
-}
-
-/*
-func TestNameBytesAreAligned(t *testing.T) {
-       typ := TypeOf(embed{})
-       b := FirstMethodNameBytes(typ)
-       v := uintptr(unsafe.Pointer(b))
-       if v%unsafe.Alignof((*byte)(nil)) != 0 {
-               t.Errorf("reflect.name.bytes pointer is not aligned: %x", v)
-       }
-}
-*/
-
 func TestTypeStrings(t *testing.T) {
        type stringTest struct {
                typ  Type
@@ -7215,3 +7323,13 @@ func iterateToString(it *MapIter) string {
        sort.Strings(got)
        return "[" + strings.Join(got, ", ") + "]"
 }
+
+func TestConvertibleTo(t *testing.T) {
+       t1 := ValueOf(example1.MyStruct{}).Type()
+       t2 := ValueOf(example2.MyStruct{}).Type()
+
+       // Shouldn't raise stack overflow
+       if t1.ConvertibleTo(t2) {
+               t.Fatalf("(%s).ConvertibleTo(%s) = true, want false", t1, t2)
+       }
+}
diff --git a/libgo/go/reflect/internal/example1/example.go b/libgo/go/reflect/internal/example1/example.go
new file mode 100644 (file)
index 0000000..0f829a8
--- /dev/null
@@ -0,0 +1,6 @@
+package example1
+
+type MyStruct struct {
+       MyStructs []MyStruct
+       MyStruct  *MyStruct
+}
diff --git a/libgo/go/reflect/internal/example2/example.go b/libgo/go/reflect/internal/example2/example.go
new file mode 100644 (file)
index 0000000..df64ba1
--- /dev/null
@@ -0,0 +1,6 @@
+package example2
+
+type MyStruct struct {
+       MyStructs []MyStruct
+       MyStruct  *MyStruct
+}
index c05ec6872edc381d365d1a7e63180fff8cc58bda..0c394a20d2446984f725490d0cdb295c91dd4428 100644 (file)
@@ -108,9 +108,15 @@ type Type interface {
        AssignableTo(u Type) bool
 
        // ConvertibleTo reports whether a value of the type is convertible to type u.
+       // Even if ConvertibleTo returns true, the conversion may still panic.
+       // For example, a slice of type []T is convertible to *[N]T,
+       // but the conversion will panic if its length is less than N.
        ConvertibleTo(u Type) bool
 
        // Comparable reports whether values of this type are comparable.
+       // Even if Comparable returns true, the comparison may still panic.
+       // For example, values of interface type are comparable,
+       // but the comparison will panic if their dynamic type is not comparable.
        Comparable() bool
 
        // Methods applicable only to some types, depending on Kind.
@@ -224,7 +230,7 @@ type Type interface {
 // See https://golang.org/issue/4876 for more details.
 
 /*
- * These data structures are known to the compiler (../../cmd/internal/gc/reflect.go).
+ * These data structures are known to the compiler (../../cmd/internal/reflectdata/reflect.go).
  * A few are known to ../runtime/type.go to convey to debuggers.
  * They are also known to ../runtime/type.go.
  */
@@ -419,12 +425,13 @@ type structType struct {
 // Method represents a single method.
 type Method struct {
        // Name is the method name.
+       Name string
+
        // PkgPath is the package path that qualifies a lower case (unexported)
        // method name. It is empty for upper case (exported) method names.
        // The combination of PkgPath and Name uniquely identifies a method
        // in a method set.
        // See https://golang.org/ref/spec#Uniqueness_of_identifiers
-       Name    string
        PkgPath string
 
        Type  Type  // method type
@@ -432,6 +439,11 @@ type Method struct {
        Index int   // index for Type.Method
 }
 
+// IsExported reports whether the method is exported.
+func (m Method) IsExported() bool {
+       return m.PkgPath == ""
+}
+
 const (
        kindDirectIface = 1 << 5
        kindGCProg      = 1 << 6 // Type.gc points to GC program
@@ -828,6 +840,7 @@ func (t *interfaceType) MethodByName(name string) (m Method, ok bool) {
 type StructField struct {
        // Name is the field name.
        Name string
+
        // PkgPath is the package path that qualifies a lower case (unexported)
        // field name. It is empty for upper case (exported) field names.
        // See https://golang.org/ref/spec#Uniqueness_of_identifiers
@@ -840,6 +853,11 @@ type StructField struct {
        Anonymous bool      // is an embedded field
 }
 
+// IsExported reports whether the field is exported.
+func (f StructField) IsExported() bool {
+       return f.PkgPath == ""
+}
+
 // A StructTag is the tag string in a struct field.
 //
 // By convention, tag strings are a concatenation of
@@ -1300,7 +1318,7 @@ func haveIdenticalType(T, V Type, cmpTags bool) bool {
                return T == V
        }
 
-       if T.Name() != V.Name() || T.Kind() != V.Kind() {
+       if T.Name() != V.Name() || T.Kind() != V.Kind() || T.PkgPath() != V.PkgPath() {
                return false
        }
 
@@ -1529,7 +1547,7 @@ func MapOf(key, elem Type) Type {
 
        // Make a map type.
        // Note: flag values must match those used in the TMAP case
-       // in ../cmd/compile/internal/gc/reflect.go:dtypesym.
+       // in ../cmd/compile/internal/reflectdata/reflect.go:writeType.
        var imap interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil)
        mt := **(**mapType)(unsafe.Pointer(&imap))
        mt.string = &s
@@ -2257,8 +2275,7 @@ func runtimeStructField(field StructField) (structField, string) {
                panic("reflect.StructOf: field \"" + field.Name + "\" is anonymous but has PkgPath set")
        }
 
-       exported := field.PkgPath == ""
-       if exported {
+       if field.IsExported() {
                // Best-effort check for misuse.
                // Since this field will be treated as exported, not much harm done if Unicode lowercase slips through.
                c := field.Name[0]
@@ -2298,7 +2315,7 @@ func runtimeStructField(field StructField) (structField, string) {
 
 // typeptrdata returns the length in bytes of the prefix of t
 // containing pointer data. Anything after this offset is scalar data.
-// keep in sync with ../cmd/compile/internal/gc/reflect.go
+// keep in sync with ../cmd/compile/internal/reflectdata/reflect.go
 func typeptrdata(t *rtype) uintptr {
        switch t.Kind() {
        case Struct:
@@ -2322,25 +2339,29 @@ func typeptrdata(t *rtype) uintptr {
        }
 }
 
-// See cmd/compile/internal/gc/reflect.go for derivation of constant.
+// See cmd/compile/internal/reflectdata/reflect.go for derivation of constant.
 const maxPtrmaskBytes = 2048
 
-// ArrayOf returns the array type with the given count and element type.
+// ArrayOf returns the array type with the given length and element type.
 // For example, if t represents int, ArrayOf(5, t) represents [5]int.
 //
 // If the resulting type would be larger than the available address space,
 // ArrayOf panics.
-func ArrayOf(count int, elem Type) Type {
+func ArrayOf(length int, elem Type) Type {
+       if length < 0 {
+               panic("reflect: negative length passed to ArrayOf")
+       }
+
        typ := elem.(*rtype)
 
        // Look in cache.
-       ckey := cacheKey{Array, typ, nil, uintptr(count)}
+       ckey := cacheKey{Array, typ, nil, uintptr(length)}
        if array, ok := lookupCache.Load(ckey); ok {
                return array.(Type)
        }
 
        // Look in known types.
-       s := "[" + strconv.Itoa(count) + "]" + *typ.string
+       s := "[" + strconv.Itoa(length) + "]" + *typ.string
        if tt := lookupType(s); tt != nil {
                array := (*arrayType)(unsafe.Pointer(toType(tt).(*rtype)))
                if array.elem == typ {
@@ -2358,28 +2379,27 @@ func ArrayOf(count int, elem Type) Type {
 
        // gccgo uses a different hash.
        // array.hash = fnv1(typ.hash, '[')
-       // for n := uint32(count); n > 0; n >>= 8 {
+       // for n := uint32(length); n > 0; n >>= 8 {
        //      array.hash = fnv1(array.hash, byte(n))
        // }
        // array.hash = fnv1(array.hash, ']')
        array.hash = typ.hash + 1 + 13
-
        array.elem = typ
        array.ptrToThis = nil
        if typ.size > 0 {
                max := ^uintptr(0) / typ.size
-               if uintptr(count) > max {
+               if uintptr(length) > max {
                        panic("reflect.ArrayOf: array size would exceed virtual address space")
                }
        }
-       array.size = typ.size * uintptr(count)
-       if count > 0 && typ.ptrdata != 0 {
-               array.ptrdata = typ.size*uintptr(count-1) + typ.ptrdata
+       array.size = typ.size * uintptr(length)
+       if length > 0 && typ.ptrdata != 0 {
+               array.ptrdata = typ.size*uintptr(length-1) + typ.ptrdata
        }
        array.align = typ.align
        array.fieldAlign = typ.fieldAlign
        array.uncommonType = nil
-       array.len = uintptr(count)
+       array.len = uintptr(length)
        array.slice = SliceOf(elem).(*rtype)
 
        switch {
@@ -2388,7 +2408,7 @@ func ArrayOf(count int, elem Type) Type {
                array.gcdata = nil
                array.ptrdata = 0
 
-       case count == 1:
+       case length == 1:
                // In memory, 1-element array looks just like the element.
                array.kind |= typ.kind & kindGCProg
                array.gcdata = typ.gcdata
@@ -2397,7 +2417,7 @@ func ArrayOf(count int, elem Type) Type {
        case typ.kind&kindGCProg == 0 && array.size <= maxPtrmaskBytes*8*ptrSize:
                // Element is small with pointer mask; array is still small.
                // Create direct pointer mask by turning each 1 bit in elem
-               // into count 1 bits in larger mask.
+               // into length 1 bits in larger mask.
                mask := make([]byte, (array.ptrdata/ptrSize+7)/8)
                emitGCMask(mask, 0, typ, array.len)
                array.gcdata = &mask[0]
@@ -2418,14 +2438,14 @@ func ArrayOf(count int, elem Type) Type {
                                prog = appendVarint(prog, elemWords-elemPtrs-1)
                        }
                }
-               // Repeat count-1 times.
+               // Repeat length-1 times.
                if elemWords < 0x80 {
                        prog = append(prog, byte(elemWords|0x80))
                } else {
                        prog = append(prog, 0x80)
                        prog = appendVarint(prog, elemWords)
                }
-               prog = appendVarint(prog, uintptr(count)-1)
+               prog = appendVarint(prog, uintptr(length)-1)
                prog = append(prog, 0)
                *(*uint32)(unsafe.Pointer(&prog[0])) = uint32(len(prog) - 4)
                array.kind |= kindGCProg
@@ -2439,9 +2459,9 @@ func ArrayOf(count int, elem Type) Type {
        array.equal = nil
        if eequal := etyp.equal; eequal != nil {
                array.equal = func(p, q unsafe.Pointer) bool {
-                       for i := 0; i < count; i++ {
-                               pi := arrayAt(p, i, esize, "i < count")
-                               qi := arrayAt(q, i, esize, "i < count")
+                       for i := 0; i < length; i++ {
+                               pi := arrayAt(p, i, esize, "i < length")
+                               qi := arrayAt(q, i, esize, "i < length")
                                if !eequal(pi, qi) {
                                        return false
                                }
@@ -2451,7 +2471,7 @@ func ArrayOf(count int, elem Type) Type {
        }
 
        switch {
-       case count == 1 && !ifaceIndir(typ):
+       case length == 1 && !ifaceIndir(typ):
                // array of 1 direct iface type can be direct
                array.kind |= kindDirectIface
        default:
index 0b4f094f1b757e2c8e9958ed7fe66b55f3c61d40..300ef1a82ad2e80249781fcd38dca9ef5843befd 100644 (file)
@@ -5,6 +5,7 @@
 package reflect
 
 import (
+       "internal/itoa"
        "internal/unsafeheader"
        "math"
        "runtime"
@@ -350,6 +351,8 @@ func (v Value) CallSlice(in []Value) []Value {
 
 var callGC bool // for testing; see TestCallMethodJump
 
+const debugReflectCall = false
+
 func (v Value) call(op string, in []Value) []Value {
        // Get function pointer, type.
        t := (*funcType)(unsafe.Pointer(v.typ))
@@ -372,8 +375,9 @@ func (v Value) call(op string, in []Value) []Value {
 
        isSlice := op == "CallSlice"
        n := t.NumIn()
+       isVariadic := t.IsVariadic()
        if isSlice {
-               if !t.IsVariadic() {
+               if !isVariadic {
                        panic("reflect: CallSlice of non-variadic function")
                }
                if len(in) < n {
@@ -383,13 +387,13 @@ func (v Value) call(op string, in []Value) []Value {
                        panic("reflect: CallSlice with too many input arguments")
                }
        } else {
-               if t.IsVariadic() {
+               if isVariadic {
                        n--
                }
                if len(in) < n {
                        panic("reflect: Call with too few input arguments")
                }
-               if !t.IsVariadic() && len(in) > n {
+               if !isVariadic && len(in) > n {
                        panic("reflect: Call with too many input arguments")
                }
        }
@@ -403,7 +407,7 @@ func (v Value) call(op string, in []Value) []Value {
                        panic("reflect: " + op + " using " + xt.String() + " as type " + targ.String())
                }
        }
-       if !isSlice && t.IsVariadic() {
+       if !isSlice && isVariadic {
                // prepare slice for remaining values
                m := len(in) - n
                slice := MakeSlice(t.In(n), m, m)
@@ -857,10 +861,16 @@ func valueInterface(v Value, safe bool) interface{} {
        return packEface(v)
 }
 
-// InterfaceData returns the interface v's value as a uintptr pair.
+// InterfaceData returns a pair of unspecified uintptr values.
 // It panics if v's Kind is not Interface.
+//
+// In earlier versions of Go, this function returned the interface's
+// value as a uintptr pair. As of Go 1.4, the implementation of
+// interface values precludes any defined use of InterfaceData.
+//
+// Deprecated: The memory representation of interface values is not
+// compatible with InterfaceData.
 func (v Value) InterfaceData() [2]uintptr {
-       // TODO: deprecate this
        v.mustBe(Interface)
        // We treat this as a read operation, so we allow
        // it even for unexported data, because the caller
@@ -2200,9 +2210,14 @@ func New(typ Type) Value {
                panic("reflect: New(nil)")
        }
        t := typ.(*rtype)
+       pt := t.ptrTo()
+       if ifaceIndir(pt) {
+               // This is a pointer to a go:notinheap type.
+               panic("reflect: New of type that may not be allocated in heap (possibly undefined cgo C type)")
+       }
        ptr := unsafe_New(t)
        fl := flag(Ptr)
-       return Value{t.ptrTo(), ptr, fl}
+       return Value{pt, ptr, fl}
 }
 
 // NewAt returns a Value representing a pointer to a value of the
@@ -2255,7 +2270,7 @@ func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value
 
 // Convert returns the value v converted to type t.
 // If the usual Go conversion rules do not allow conversion
-// of the value v to type t, Convert panics.
+// of the value v to type t, or if converting v to type t panics, Convert panics.
 func (v Value) Convert(t Type) Value {
        if v.flag&flagMethod != 0 {
                v = makeMethodValue("Convert", v)
@@ -2267,6 +2282,26 @@ func (v Value) Convert(t Type) Value {
        return op(v, t)
 }
 
+// CanConvert reports whether the value v can be converted to type t.
+// If v.CanConvert(t) returns true then v.Convert(t) will not panic.
+func (v Value) CanConvert(t Type) bool {
+       vt := v.Type()
+       if !vt.ConvertibleTo(t) {
+               return false
+       }
+       // Currently the only conversion that is OK in terms of type
+       // but that can panic depending on the value is converting
+       // from slice to pointer-to-array.
+       if vt.Kind() == Slice && t.Kind() == Ptr && t.Elem().Kind() == Array {
+               n := t.Elem().Len()
+               h := (*unsafeheader.Slice)(v.ptr)
+               if n > h.Len {
+                       return false
+               }
+       }
+       return true
+}
+
 // convertOp returns the function to convert a value of type src
 // to a value of type dst. If the conversion is illegal, convertOp returns nil.
 func convertOp(dst, src *rtype) func(Value, Type) Value {
@@ -2326,6 +2361,11 @@ func convertOp(dst, src *rtype) func(Value, Type) Value {
                                return cvtRunesString
                        }
                }
+               // "x is a slice, T is a pointer-to-array type,
+               // and the slice and array types have identical element types."
+               if dst.Kind() == Ptr && dst.Elem().Kind() == Array && src.Elem() == dst.Elem().Elem() {
+                       return cvtSliceArrayPtr
+               }
 
        case Chan:
                if dst.Kind() == Chan && specialChannelAssignability(dst, src) {
@@ -2519,6 +2559,16 @@ func cvtStringRunes(v Value, t Type) Value {
        return makeRunes(v.flag.ro(), []rune(v.String()), t)
 }
 
+// convertOp: []T -> *[N]T
+func cvtSliceArrayPtr(v Value, t Type) Value {
+       n := t.Elem().Len()
+       h := (*unsafeheader.Slice)(v.ptr)
+       if n > h.Len {
+               panic("reflect: cannot convert slice with length " + itoa.Itoa(h.Len) + " to pointer to array with length " + itoa.Itoa(n))
+       }
+       return Value{t.common(), h.Data, v.flag&^(flagIndir|flagAddr|flagKindMask) | flag(Ptr)}
+}
+
 // convertOp: direct copy
 func cvtDirect(v Value, typ Type) Value {
        f := v.flag
diff --git a/libgo/go/reflect/visiblefields.go b/libgo/go/reflect/visiblefields.go
new file mode 100644 (file)
index 0000000..1a2b535
--- /dev/null
@@ -0,0 +1,105 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package reflect
+
+// VisibleFields returns all the visible fields in t, which must be a
+// struct type. A field is defined as visible if it's accessible
+// directly with a FieldByName call. The returned fields include fields
+// inside anonymous struct members and unexported fields. They follow
+// the same order found in the struct, with anonymous fields followed
+// immediately by their promoted fields.
+//
+// For each element e of the returned slice, the corresponding field
+// can be retrieved from a value v of type t by calling v.FieldByIndex(e.Index).
+func VisibleFields(t Type) []StructField {
+       if t == nil {
+               panic("reflect: VisibleFields(nil)")
+       }
+       if t.Kind() != Struct {
+               panic("reflect.VisibleFields of non-struct type")
+       }
+       w := &visibleFieldsWalker{
+               byName:   make(map[string]int),
+               visiting: make(map[Type]bool),
+               fields:   make([]StructField, 0, t.NumField()),
+               index:    make([]int, 0, 2),
+       }
+       w.walk(t)
+       // Remove all the fields that have been hidden.
+       // Use an in-place removal that avoids copying in
+       // the common case that there are no hidden fields.
+       j := 0
+       for i := range w.fields {
+               f := &w.fields[i]
+               if f.Name == "" {
+                       continue
+               }
+               if i != j {
+                       // A field has been removed. We need to shuffle
+                       // all the subsequent elements up.
+                       w.fields[j] = *f
+               }
+               j++
+       }
+       return w.fields[:j]
+}
+
+type visibleFieldsWalker struct {
+       byName   map[string]int
+       visiting map[Type]bool
+       fields   []StructField
+       index    []int
+}
+
+// walk walks all the fields in the struct type t, visiting
+// fields in index preorder and appending them to w.fields
+// (this maintains the required ordering).
+// Fields that have been overridden have their
+// Name field cleared.
+func (w *visibleFieldsWalker) walk(t Type) {
+       if w.visiting[t] {
+               return
+       }
+       w.visiting[t] = true
+       for i := 0; i < t.NumField(); i++ {
+               f := t.Field(i)
+               w.index = append(w.index, i)
+               add := true
+               if oldIndex, ok := w.byName[f.Name]; ok {
+                       old := &w.fields[oldIndex]
+                       if len(w.index) == len(old.Index) {
+                               // Fields with the same name at the same depth
+                               // cancel one another out. Set the field name
+                               // to empty to signify that has happened, and
+                               // there's no need to add this field.
+                               old.Name = ""
+                               add = false
+                       } else if len(w.index) < len(old.Index) {
+                               // The old field loses because it's deeper than the new one.
+                               old.Name = ""
+                       } else {
+                               // The old field wins because it's shallower than the new one.
+                               add = false
+                       }
+               }
+               if add {
+                       // Copy the index so that it's not overwritten
+                       // by the other appends.
+                       f.Index = append([]int(nil), w.index...)
+                       w.byName[f.Name] = len(w.fields)
+                       w.fields = append(w.fields, f)
+               }
+               if f.Anonymous {
+                       if f.Type.Kind() == Ptr {
+                               f.Type = f.Type.Elem()
+                       }
+                       if f.Type.Kind() == Struct {
+                               w.walk(f.Type)
+                       }
+               }
+               w.index = w.index[:len(w.index)-1]
+       }
+       delete(w.visiting, t)
+}
diff --git a/libgo/go/reflect/visiblefields_test.go b/libgo/go/reflect/visiblefields_test.go
new file mode 100644 (file)
index 0000000..915bbee
--- /dev/null
@@ -0,0 +1,330 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package reflect_test
+
+import (
+       . "reflect"
+       "testing"
+)
+
+type structField struct {
+       name  string
+       index []int
+}
+
+var fieldsTests = []struct {
+       testName string
+       val      interface{}
+       expect   []structField
+}{{
+       testName: "SimpleStruct",
+       val: struct {
+               A int
+               B string
+               C bool
+       }{},
+       expect: []structField{{
+               name:  "A",
+               index: []int{0},
+       }, {
+               name:  "B",
+               index: []int{1},
+       }, {
+               name:  "C",
+               index: []int{2},
+       }},
+}, {
+       testName: "NonEmbeddedStructMember",
+       val: struct {
+               A struct {
+                       X int
+               }
+       }{},
+       expect: []structField{{
+               name:  "A",
+               index: []int{0},
+       }},
+}, {
+       testName: "EmbeddedExportedStruct",
+       val: struct {
+               SFG
+       }{},
+       expect: []structField{{
+               name:  "SFG",
+               index: []int{0},
+       }, {
+               name:  "F",
+               index: []int{0, 0},
+       }, {
+               name:  "G",
+               index: []int{0, 1},
+       }},
+}, {
+       testName: "EmbeddedUnexportedStruct",
+       val: struct {
+               sFG
+       }{},
+       expect: []structField{{
+               name:  "sFG",
+               index: []int{0},
+       }, {
+               name:  "F",
+               index: []int{0, 0},
+       }, {
+               name:  "G",
+               index: []int{0, 1},
+       }},
+}, {
+       testName: "TwoEmbeddedStructsWithCancellingMembers",
+       val: struct {
+               SFG
+               SF
+       }{},
+       expect: []structField{{
+               name:  "SFG",
+               index: []int{0},
+       }, {
+               name:  "G",
+               index: []int{0, 1},
+       }, {
+               name:  "SF",
+               index: []int{1},
+       }},
+}, {
+       testName: "EmbeddedStructsWithSameFieldsAtDifferentDepths",
+       val: struct {
+               SFGH3
+               SG1
+               SFG2
+               SF2
+               L int
+       }{},
+       expect: []structField{{
+               name:  "SFGH3",
+               index: []int{0},
+       }, {
+               name:  "SFGH2",
+               index: []int{0, 0},
+       }, {
+               name:  "SFGH1",
+               index: []int{0, 0, 0},
+       }, {
+               name:  "SFGH",
+               index: []int{0, 0, 0, 0},
+       }, {
+               name:  "H",
+               index: []int{0, 0, 0, 0, 2},
+       }, {
+               name:  "SG1",
+               index: []int{1},
+       }, {
+               name:  "SG",
+               index: []int{1, 0},
+       }, {
+               name:  "G",
+               index: []int{1, 0, 0},
+       }, {
+               name:  "SFG2",
+               index: []int{2},
+       }, {
+               name:  "SFG1",
+               index: []int{2, 0},
+       }, {
+               name:  "SFG",
+               index: []int{2, 0, 0},
+       }, {
+               name:  "SF2",
+               index: []int{3},
+       }, {
+               name:  "SF1",
+               index: []int{3, 0},
+       }, {
+               name:  "SF",
+               index: []int{3, 0, 0},
+       }, {
+               name:  "L",
+               index: []int{4},
+       }},
+}, {
+       testName: "EmbeddedPointerStruct",
+       val: struct {
+               *SF
+       }{},
+       expect: []structField{{
+               name:  "SF",
+               index: []int{0},
+       }, {
+               name:  "F",
+               index: []int{0, 0},
+       }},
+}, {
+       testName: "EmbeddedNotAPointer",
+       val: struct {
+               M
+       }{},
+       expect: []structField{{
+               name:  "M",
+               index: []int{0},
+       }},
+}, {
+       testName: "RecursiveEmbedding",
+       val:      Rec1{},
+       expect: []structField{{
+               name:  "Rec2",
+               index: []int{0},
+       }, {
+               name:  "F",
+               index: []int{0, 0},
+       }, {
+               name:  "Rec1",
+               index: []int{0, 1},
+       }},
+}, {
+       testName: "RecursiveEmbedding2",
+       val:      Rec2{},
+       expect: []structField{{
+               name:  "F",
+               index: []int{0},
+       }, {
+               name:  "Rec1",
+               index: []int{1},
+       }, {
+               name:  "Rec2",
+               index: []int{1, 0},
+       }},
+}, {
+       testName: "RecursiveEmbedding3",
+       val:      RS3{},
+       expect: []structField{{
+               name:  "RS2",
+               index: []int{0},
+       }, {
+               name:  "RS1",
+               index: []int{1},
+       }, {
+               name:  "i",
+               index: []int{1, 0},
+       }},
+}}
+
+type SFG struct {
+       F int
+       G int
+}
+
+type SFG1 struct {
+       SFG
+}
+
+type SFG2 struct {
+       SFG1
+}
+
+type SFGH struct {
+       F int
+       G int
+       H int
+}
+
+type SFGH1 struct {
+       SFGH
+}
+
+type SFGH2 struct {
+       SFGH1
+}
+
+type SFGH3 struct {
+       SFGH2
+}
+
+type SF struct {
+       F int
+}
+
+type SF1 struct {
+       SF
+}
+
+type SF2 struct {
+       SF1
+}
+
+type SG struct {
+       G int
+}
+
+type SG1 struct {
+       SG
+}
+
+type sFG struct {
+       F int
+       G int
+}
+
+type RS1 struct {
+       i int
+}
+
+type RS2 struct {
+       RS1
+}
+
+type RS3 struct {
+       RS2
+       RS1
+}
+
+type M map[string]interface{}
+
+type Rec1 struct {
+       *Rec2
+}
+
+type Rec2 struct {
+       F string
+       *Rec1
+}
+
+func TestFields(t *testing.T) {
+       for _, test := range fieldsTests {
+               test := test
+               t.Run(test.testName, func(t *testing.T) {
+                       typ := TypeOf(test.val)
+                       fields := VisibleFields(typ)
+                       if got, want := len(fields), len(test.expect); got != want {
+                               t.Fatalf("unexpected field count; got %d want %d", got, want)
+                       }
+
+                       for j, field := range fields {
+                               expect := test.expect[j]
+                               t.Logf("field %d: %s", j, expect.name)
+                               gotField := typ.FieldByIndex(field.Index)
+                               // Unfortunately, FieldByIndex does not return
+                               // a field with the same index that we passed in,
+                               // so we set it to the expected value so that
+                               // it can be compared later with the result of FieldByName.
+                               gotField.Index = field.Index
+                               expectField := typ.FieldByIndex(expect.index)
+                               // ditto.
+                               expectField.Index = expect.index
+                               if !DeepEqual(gotField, expectField) {
+                                       t.Fatalf("unexpected field result\ngot %#v\nwant %#v", gotField, expectField)
+                               }
+
+                               // Sanity check that we can actually access the field by the
+                               // expected name.
+                               gotField1, ok := typ.FieldByName(expect.name)
+                               if !ok {
+                                       t.Fatalf("field %q not accessible by name", expect.name)
+                               }
+                               if !DeepEqual(gotField1, expectField) {
+                                       t.Fatalf("unexpected FieldByName result; got %#v want %#v", gotField1, expectField)
+                               }
+                       }
+               })
+       }
+}
index 7b86b41156e17a684ad0321191b5f08c53f4e8d7..6444bc12f90ebdfd34d446c9973edbe01eb1f412 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !race
 // +build !race
 
 package regexp
index 87c49b074fa48655b3510cc31443bd645436cb6d..64c2239d905fdff2e26df72ba42b51cc1c85caca 100644 (file)
@@ -97,6 +97,7 @@ var findTests = []FindTest{
        {`\B`, "xx", build(1, 1, 1)},
        {`\B`, "x y", nil},
        {`\B`, "xx yy", build(2, 1, 1, 4, 4)},
+       {`(|a)*`, "aa", build(3, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2)},
 
        // RE2 tests
        {`[^\S\s]`, "abcd", nil},
index 32264d5f1ef41bda4eb4ae76b1b0dcf96871a6aa..6a42eda391c2c7ad09068c687ca1d84cbd95356f 100644 (file)
@@ -142,7 +142,7 @@ var onePassTests = []struct {
        {`^(?:(a)|(?:a*))$`, false},
        {`^(?:(?:(?:.(?:$))?))$`, true},
        {`^abcd$`, true},
-       {`^(?:(?:a{0,})*?)$`, true},
+       {`^(?:(?:a{0,})*?)$`, false},
        {`^(?:(?:a+)*)$`, true},
        {`^(?:(?:a|(?:aa)))$`, true},
        {`^(?:[^\s\S])$`, true},
index 7524d628fe1686697a03a2e8e06a3928302d79e1..c9f9fa024bf10d0981d5f61f309b1251c64cf756 100644 (file)
@@ -57,8 +57,9 @@ func (l1 patchList) append(p *Prog, l2 patchList) patchList {
 
 // A frag represents a compiled program fragment.
 type frag struct {
-       i   uint32    // index of first instruction
-       out patchList // where to record end instruction
+       i        uint32    // index of first instruction
+       out      patchList // where to record end instruction
+       nullable bool      // whether fragment can match empty string
 }
 
 type compiler struct {
@@ -159,7 +160,7 @@ func (c *compiler) compile(re *Regexp) frag {
 
 func (c *compiler) inst(op InstOp) frag {
        // TODO: impose length limit
-       f := frag{i: uint32(len(c.p.Inst))}
+       f := frag{i: uint32(len(c.p.Inst)), nullable: true}
        c.p.Inst = append(c.p.Inst, Inst{Op: op})
        return f
 }
@@ -194,7 +195,7 @@ func (c *compiler) cat(f1, f2 frag) frag {
        // TODO: elide nop
 
        f1.out.patch(c.p, f2.i)
-       return frag{f1.i, f2.out}
+       return frag{f1.i, f2.out, f1.nullable && f2.nullable}
 }
 
 func (c *compiler) alt(f1, f2 frag) frag {
@@ -211,6 +212,7 @@ func (c *compiler) alt(f1, f2 frag) frag {
        i.Out = f1.i
        i.Arg = f2.i
        f.out = f1.out.append(c.p, f2.out)
+       f.nullable = f1.nullable || f2.nullable
        return f
 }
 
@@ -228,7 +230,12 @@ func (c *compiler) quest(f1 frag, nongreedy bool) frag {
        return f
 }
 
-func (c *compiler) star(f1 frag, nongreedy bool) frag {
+// loop returns the fragment for the main loop of a plus or star.
+// For plus, it can be used after changing the entry to f1.i.
+// For star, it can be used directly when f1 can't match an empty string.
+// (When f1 can match an empty string, f1* must be implemented as (f1+)?
+// to get the priority match order correct.)
+func (c *compiler) loop(f1 frag, nongreedy bool) frag {
        f := c.inst(InstAlt)
        i := &c.p.Inst[f.i]
        if nongreedy {
@@ -242,8 +249,17 @@ func (c *compiler) star(f1 frag, nongreedy bool) frag {
        return f
 }
 
+func (c *compiler) star(f1 frag, nongreedy bool) frag {
+       if f1.nullable {
+               // Use (f1+)? to get priority match order correct.
+               // See golang.org/issue/46123.
+               return c.quest(c.plus(f1, nongreedy), nongreedy)
+       }
+       return c.loop(f1, nongreedy)
+}
+
 func (c *compiler) plus(f1 frag, nongreedy bool) frag {
-       return frag{f1.i, c.star(f1, nongreedy).out}
+       return frag{f1.i, c.loop(f1, nongreedy).out, f1.nullable}
 }
 
 func (c *compiler) empty(op EmptyOp) frag {
@@ -255,6 +271,7 @@ func (c *compiler) empty(op EmptyOp) frag {
 
 func (c *compiler) rune(r []rune, flags Flags) frag {
        f := c.inst(InstRune)
+       f.nullable = false
        i := &c.p.Inst[f.i]
        i.Rune = r
        flags &= FoldCase // only relevant flag is FoldCase
index 50bfa3d4bef6d4643c1c6b4ff49673c6ec8fa244..5603aea22898f657231ef484240c51869b7b1271 100644 (file)
@@ -88,6 +88,21 @@ var compileTests = []struct {
   1*   empty 4 -> 2
   2    anynotnl -> 3
   3    match
+`},
+       {"(?:|a)+", `  0        fail
+  1    nop -> 4
+  2    rune1 "a" -> 4
+  3*   alt -> 1, 2
+  4    alt -> 3, 5
+  5    match
+`},
+       {"(?:|a)*", `  0        fail
+  1    nop -> 4
+  2    rune1 "a" -> 4
+  3    alt -> 1, 2
+  4    alt -> 3, 6
+  5*   alt -> 3, 6
+  6    match
 `},
 }
 
index 7859290ba1dd0dc354b3149e16f364b2a1015794..1776b1ff96b66dc2e19da99062a9db3ce93d28bd 100644 (file)
@@ -124,24 +124,20 @@ E ((a))                   abc             (0,1)(0,1)(0,1)
 E      (a)b(c)                 abc             (0,3)(0,1)(2,3)
 E      a+b+c                   aabbabc         (4,7)
 E      a*                      aaa             (0,3)
-#E     (a*)*                   -               (0,0)(0,0)
-E      (a*)*                   -               (0,0)(?,?)      RE2/Go
+E      (a*)*                   -               (0,0)(0,0)
 E      (a*)+                   -               (0,0)(0,0)
-#E     (a*|b)*                 -               (0,0)(0,0)
-E      (a*|b)*                 -               (0,0)(?,?)      RE2/Go
+E      (a*|b)*                 -               (0,0)(0,0)
 E      (a+|b)*                 ab              (0,2)(1,2)
 E      (a+|b)+                 ab              (0,2)(1,2)
 E      (a+|b)?                 ab              (0,1)(0,1)
 BE     [^ab]*                  cde             (0,3)
-#E     (^)*                    -               (0,0)(0,0)
-E      (^)*                    -               (0,0)(?,?)      RE2/Go
+E      (^)*                    -               (0,0)(0,0)
 BE     a*                      NULL            (0,0)
 E      ([abc])*d               abbbcd          (0,6)(4,5)
 E      ([abc])*bcd             abcd            (0,4)(0,1)
 E      a|b|c|d|e               e               (0,1)
 E      (a|b|c|d|e)f            ef              (0,2)(0,1)
-#E     ((a*|b))*               -               (0,0)(0,0)(0,0)
-E      ((a*|b))*               -               (0,0)(?,?)(?,?) RE2/Go
+E      ((a*|b))*               -               (0,0)(0,0)(0,0)
 BE     abcd*efg                abcdefg         (0,7)
 BE     ab*                     xabyabbbz       (1,3)
 BE     ab*                     xayabbbz        (1,2)
index 2e18fbb917070347df82ed24978b62884652a037..68d9c99996a1c7b22f898101b1e5a2510b5f3451 100644 (file)
@@ -1,8 +1,7 @@
 NOTE   null subexpression matches : 2002-06-06
 
 E      (a*)*           a               (0,1)(0,1)
-#E     SAME            x               (0,0)(0,0)
-E      SAME            x               (0,0)(?,?)      RE2/Go
+E      SAME            x               (0,0)(0,0)
 E      SAME            aaaaaa          (0,6)(0,6)
 E      SAME            aaaaaax         (0,6)(0,6)
 E      (a*)+           a               (0,1)(0,1)
@@ -19,8 +18,7 @@ E     SAME            aaaaaa          (0,6)(0,6)
 E      SAME            aaaaaax         (0,6)(0,6)
 
 E      ([a]*)*         a               (0,1)(0,1)
-#E     SAME            x               (0,0)(0,0)
-E      SAME            x               (0,0)(?,?)      RE2/Go
+E      SAME            x               (0,0)(0,0)
 E      SAME            aaaaaa          (0,6)(0,6)
 E      SAME            aaaaaax         (0,6)(0,6)
 E      ([a]*)+         a               (0,1)(0,1)
@@ -28,8 +26,7 @@ E     SAME            x               (0,0)(0,0)
 E      SAME            aaaaaa          (0,6)(0,6)
 E      SAME            aaaaaax         (0,6)(0,6)
 E      ([^b]*)*        a               (0,1)(0,1)
-#E     SAME            b               (0,0)(0,0)
-E      SAME            b               (0,0)(?,?)      RE2/Go
+E      SAME            b               (0,0)(0,0)
 E      SAME            aaaaaa          (0,6)(0,6)
 E      SAME            aaaaaab         (0,6)(0,6)
 E      ([ab]*)*        a               (0,1)(0,1)
@@ -41,11 +38,9 @@ E    SAME            bbbbbb          (0,6)(0,6)
 E      SAME            aaaabcde        (0,5)(0,5)
 E      ([^a]*)*        b               (0,1)(0,1)
 E      SAME            bbbbbb          (0,6)(0,6)
-#E     SAME            aaaaaa          (0,0)(0,0)
-E      SAME            aaaaaa          (0,0)(?,?)      RE2/Go
+E      SAME            aaaaaa          (0,0)(0,0)
 E      ([^ab]*)*       ccccxx          (0,6)(0,6)
-#E     SAME            ababab          (0,0)(0,0)
-E      SAME            ababab          (0,0)(?,?)      RE2/Go
+E      SAME            ababab          (0,0)(0,0)
 
 E      ((z)+|a)*       zabcde          (0,2)(1,2)
 
@@ -65,8 +60,7 @@ B     \(a*\)*\(x\)\(\1\)      axa     (0,3)(0,1)(1,2)(2,3)
 B      \(a*\)*\(x\)\(\1\)\(x\) axax    (0,4)(0,1)(1,2)(2,3)(3,4)
 B      \(a*\)*\(x\)\(\1\)\(x\) axxa    (0,3)(1,1)(1,2)(2,2)(2,3)
 
-#E     (a*)*(x)                x       (0,1)(0,0)(0,1)
-E      (a*)*(x)                x       (0,1)(?,?)(0,1) RE2/Go
+E      (a*)*(x)                x       (0,1)(0,0)(0,1)
 E      (a*)*(x)                ax      (0,2)(0,1)(1,2)
 E      (a*)*(x)                axa     (0,2)(0,1)(1,2)
 
index a357f280169150b1d351c3fd5ed9a9eeff4ce66f..6638476dec0ae8eb102fff1d339d99b1a3e9f412 100644 (file)
Binary files a/libgo/go/regexp/testdata/re2-exhaustive.txt.bz2 and b/libgo/go/regexp/testdata/re2-exhaustive.txt.bz2 differ
index 4d02e9cebd687a01767295533905bd5c8ae56b8f..8c4098a4f185be5e7ae5406dacb53abd6bd8e0cb 100644 (file)
@@ -1,5 +1,5 @@
 # RE2 basic search tests built by make log
-# Thu Sep 8 13:43:43 EDT 2011
+# Wed May 12 12:13:22 EDT 2021
 Regexp.SearchTests
 strings
 ""
@@ -227,22 +227,6 @@ regexps
 0-0;0-0;0-0;0-0
 strings
 ""
-""
-regexps
-"a*"
-0-0;0-0;0-0;0-0
-0-0;0-0;0-0;0-0
-"^(?:a*)$"
-0-0;0-0;0-0;0-0
-0-0;0-0;0-0;0-0
-"^(?:a*)"
-0-0;0-0;0-0;0-0
-0-0;0-0;0-0;0-0
-"(?:a*)$"
-0-0;0-0;0-0;0-0
-0-0;0-0;0-0;0-0
-strings
-""
 "xabcdx"
 regexps
 "ab|cd"
@@ -3651,6 +3635,86 @@ regexps
 0-1;0-1;0-1;0-1
 strings
 ""
+"a"
+regexps
+"a\\C+"
+-;-;-;-
+-;-;-;-
+"^(?:a\\C+)$"
+-;-;-;-
+-;-;-;-
+"^(?:a\\C+)"
+-;-;-;-
+-;-;-;-
+"(?:a\\C+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"a"
+regexps
+"a\\C?"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a\\C?)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a\\C?)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:a\\C?)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"a"
+regexps
+"a\\C*?"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a\\C*?)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a\\C*?)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:a\\C*?)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"a"
+regexps
+"a\\C+?"
+-;-;-;-
+-;-;-;-
+"^(?:a\\C+?)$"
+-;-;-;-
+-;-;-;-
+"^(?:a\\C+?)"
+-;-;-;-
+-;-;-;-
+"(?:a\\C+?)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"a"
+regexps
+"a\\C??"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a\\C??)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a\\C??)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:a\\C??)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
 "baba"
 regexps
 "a\\C*|ba\\C"
@@ -3666,7 +3730,50 @@ regexps
 -;-;-;-
 -;1-4;-;1-4
 strings
-"abc"
+""
+"Inc."
 regexps
-"a.*?c|a.*?b"
+"\\w*I\\w*"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:\\w*I\\w*)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\w*I\\w*)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:\\w*I\\w*)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aaa"
+regexps
+"(?:|a)*"
+0-0;0-0;0-0;0-0
+0-3;0-0;0-3;0-3
+"^(?:(?:|a)*)$"
+0-0;0-0;0-0;0-0
+0-3;0-3;0-3;0-3
+"^(?:(?:|a)*)"
+0-0;0-0;0-0;0-0
+0-3;0-0;0-3;0-3
+"(?:(?:|a)*)$"
+0-0;0-0;0-0;0-0
+0-3;0-3;0-3;0-3
+strings
+""
+"aaa"
+regexps
+"(?:|a)+"
+0-0;0-0;0-0;0-0
+0-3;0-0;0-3;0-3
+"^(?:(?:|a)+)$"
+0-0;0-0;0-0;0-0
+0-3;0-3;0-3;0-3
+"^(?:(?:|a)+)"
+0-0;0-0;0-0;0-0
+0-3;0-0;0-3;0-3
+"(?:(?:|a)+)$"
+0-0;0-0;0-0;0-0
 0-3;0-3;0-3;0-3
diff --git a/libgo/go/runtime/abi_test.go b/libgo/go/runtime/abi_test.go
new file mode 100644 (file)
index 0000000..b27b012
--- /dev/null
@@ -0,0 +1,112 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build goexperiment.regabireflect
+// +build goexperiment.regabireflect
+
+// This file contains tests specific to making sure the register ABI
+// works in a bunch of contexts in the runtime.
+
+package runtime_test
+
+import (
+       "internal/testenv"
+       "os"
+       "os/exec"
+       "runtime"
+       "strings"
+       "testing"
+       "time"
+)
+
+var regConfirmRun chan int
+
+//go:registerparams
+func regFinalizerPointer(v *Tint) (int, float32, [10]byte) {
+       regConfirmRun <- *(*int)(v)
+       return 5151, 4.0, [10]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
+}
+
+//go:registerparams
+func regFinalizerIface(v Tinter) (int, float32, [10]byte) {
+       regConfirmRun <- *(*int)(v.(*Tint))
+       return 5151, 4.0, [10]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
+}
+
+func TestFinalizerRegisterABI(t *testing.T) {
+       testenv.MustHaveExec(t)
+
+       // Actually run the test in a subprocess because we don't want
+       // finalizers from other tests interfering.
+       if os.Getenv("TEST_FINALIZER_REGABI") != "1" {
+               cmd := testenv.CleanCmdEnv(exec.Command(os.Args[0], "-test.run=TestFinalizerRegisterABI", "-test.v"))
+               cmd.Env = append(cmd.Env, "TEST_FINALIZER_REGABI=1")
+               out, err := cmd.CombinedOutput()
+               if !strings.Contains(string(out), "PASS\n") || err != nil {
+                       t.Fatalf("%s\n(exit status %v)", string(out), err)
+               }
+               return
+       }
+
+       // Optimistically clear any latent finalizers from e.g. the testing
+       // package before continuing.
+       //
+       // It's possible that a finalizer only becomes available to run
+       // after this point, which would interfere with the test and could
+       // cause a crash, but because we're running in a separate process
+       // it's extremely unlikely.
+       runtime.GC()
+       runtime.GC()
+
+       // fing will only pick the new IntRegArgs up if it's currently
+       // sleeping and wakes up, so wait for it to go to sleep.
+       success := false
+       for i := 0; i < 100; i++ {
+               if runtime.FinalizerGAsleep() {
+                       success = true
+                       break
+               }
+               time.Sleep(20 * time.Millisecond)
+       }
+       if !success {
+               t.Fatal("finalizer not asleep?")
+       }
+
+       // argRegsBefore := runtime.SetIntArgRegs(abi.IntArgRegs)
+       // defer runtime.SetIntArgRegs(argRegsBefore)
+
+       tests := []struct {
+               name         string
+               fin          interface{}
+               confirmValue int
+       }{
+               {"Pointer", regFinalizerPointer, -1},
+               {"Interface", regFinalizerIface, -2},
+       }
+       for i := range tests {
+               test := &tests[i]
+               t.Run(test.name, func(t *testing.T) {
+                       regConfirmRun = make(chan int)
+
+                       x := new(Tint)
+                       *x = (Tint)(test.confirmValue)
+                       runtime.SetFinalizer(x, test.fin)
+
+                       runtime.KeepAlive(x)
+
+                       // Queue the finalizer.
+                       runtime.GC()
+                       runtime.GC()
+
+                       select {
+                       case <-time.After(time.Second):
+                               t.Fatal("finalizer failed to execute")
+                       case gotVal := <-regConfirmRun:
+                               if gotVal != test.confirmValue {
+                                       t.Fatalf("wrong finalizer executed? got %d, want %d", gotVal, test.confirmValue)
+                               }
+                       }
+               })
+       }
+}
index b5b22cfd0f8c33944eefb1426abddc1d579d203c..4408eab37d69a1e50e11f067b2a63404f6f16b07 100644 (file)
@@ -216,7 +216,6 @@ func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr {
        case kindStruct:
                s := (*structtype)(unsafe.Pointer(t))
                for _, f := range s.fields {
-                       // TODO: maybe we could hash several contiguous fields all at once.
                        if f.name != nil && *f.name == "_" {
                                continue
                        }
index 3ca617b21eb00dfc0b701f8d993186c7035b67b3..3178f1a154cec36bafe578cb6379b2b452316454 100644 (file)
@@ -2,12 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !linux
-// +build !darwin
-// +build !dragonfly
-// +build !freebsd
-// +build !netbsd
-// +build !solaris
+//go:build !linux && !darwin && !dragonfly && !freebsd && !netbsd && !solaris
+// +build !linux,!darwin,!dragonfly,!freebsd,!netbsd,!solaris
 
 package runtime
 
diff --git a/libgo/go/runtime/cgo/handle.go b/libgo/go/runtime/cgo/handle.go
new file mode 100644 (file)
index 0000000..720acca
--- /dev/null
@@ -0,0 +1,109 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cgo
+
+import (
+       "sync"
+       "sync/atomic"
+)
+
+// Handle provides a way to pass values that contain Go pointers
+// (pointers to memory allocated by Go) between Go and C without
+// breaking the cgo pointer passing rules. A Handle is an integer
+// value that can represent any Go value. A Handle can be passed
+// through C and back to Go, and Go code can use the Handle to
+// retrieve the original Go value.
+//
+// The underlying type of Handle is guaranteed to fit in an integer type
+// that is large enough to hold the bit pattern of any pointer. The zero
+// value of a Handle is not valid, and thus is safe to use as a sentinel
+// in C APIs.
+//
+// For instance, on the Go side:
+//
+//     package main
+//
+//     /*
+//     #include <stdint.h> // for uintptr_t
+//
+//     extern void MyGoPrint(uintptr_t handle);
+//     void myprint(uintptr_t handle);
+//     */
+//     import "C"
+//     import "runtime/cgo"
+//
+//     //export MyGoPrint
+//     func MyGoPrint(handle C.uintptr_t) {
+//             h := cgo.Handle(handle)
+//             val := h.Value().(string)
+//             println(val)
+//             h.Delete()
+//     }
+//
+//     func main() {
+//             val := "hello Go"
+//             C.myprint(C.uintptr_t(cgo.NewHandle(val)))
+//             // Output: hello Go
+//     }
+//
+// and on the C side:
+//
+//     #include <stdint.h> // for uintptr_t
+//
+//     // A Go function
+//     extern void MyGoPrint(uintptr_t handle);
+//
+//     // A C function
+//     void myprint(uintptr_t handle) {
+//         MyGoPrint(handle);
+//     }
+type Handle uintptr
+
+// NewHandle returns a handle for a given value.
+//
+// The handle is valid until the program calls Delete on it. The handle
+// uses resources, and this package assumes that C code may hold on to
+// the handle, so a program must explicitly call Delete when the handle
+// is no longer needed.
+//
+// The intended use is to pass the returned handle to C code, which
+// passes it back to Go, which calls Value.
+func NewHandle(v interface{}) Handle {
+       h := atomic.AddUintptr(&handleIdx, 1)
+       if h == 0 {
+               panic("runtime/cgo: ran out of handle space")
+       }
+
+       handles.Store(h, v)
+       return Handle(h)
+}
+
+// Value returns the associated Go value for a valid handle.
+//
+// The method panics if the handle is invalid.
+func (h Handle) Value() interface{} {
+       v, ok := handles.Load(uintptr(h))
+       if !ok {
+               panic("runtime/cgo: misuse of an invalid Handle")
+       }
+       return v
+}
+
+// Delete invalidates a handle. This method should only be called once
+// the program no longer needs to pass the handle to C and the C code
+// no longer has a copy of the handle value.
+//
+// The method panics if the handle is invalid.
+func (h Handle) Delete() {
+       _, ok := handles.LoadAndDelete(uintptr(h))
+       if !ok {
+               panic("runtime/cgo: misuse of an invalid Handle")
+       }
+}
+
+var (
+       handles   = sync.Map{} // map[Handle]interface{}
+       handleIdx uintptr      // atomic
+)
diff --git a/libgo/go/runtime/cgo/handle_test.go b/libgo/go/runtime/cgo/handle_test.go
new file mode 100644 (file)
index 0000000..738051a
--- /dev/null
@@ -0,0 +1,103 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cgo
+
+import (
+       "reflect"
+       "testing"
+)
+
+func TestHandle(t *testing.T) {
+       v := 42
+
+       tests := []struct {
+               v1 interface{}
+               v2 interface{}
+       }{
+               {v1: v, v2: v},
+               {v1: &v, v2: &v},
+               {v1: nil, v2: nil},
+       }
+
+       for _, tt := range tests {
+               h1 := NewHandle(tt.v1)
+               h2 := NewHandle(tt.v2)
+
+               if uintptr(h1) == 0 || uintptr(h2) == 0 {
+                       t.Fatalf("NewHandle returns zero")
+               }
+
+               if uintptr(h1) == uintptr(h2) {
+                       t.Fatalf("Duplicated Go values should have different handles, but got equal")
+               }
+
+               h1v := h1.Value()
+               h2v := h2.Value()
+               if !reflect.DeepEqual(h1v, h2v) || !reflect.DeepEqual(h1v, tt.v1) {
+                       t.Fatalf("Value of a Handle got wrong, got %+v %+v, want %+v", h1v, h2v, tt.v1)
+               }
+
+               h1.Delete()
+               h2.Delete()
+       }
+
+       siz := 0
+       handles.Range(func(k, v interface{}) bool {
+               siz++
+               return true
+       })
+       if siz != 0 {
+               t.Fatalf("handles are not cleared, got %d, want %d", siz, 0)
+       }
+}
+
+func TestInvalidHandle(t *testing.T) {
+       t.Run("zero", func(t *testing.T) {
+               h := Handle(0)
+
+               defer func() {
+                       if r := recover(); r != nil {
+                               return
+                       }
+                       t.Fatalf("Delete of zero handle did not trigger a panic")
+               }()
+
+               h.Delete()
+       })
+
+       t.Run("invalid", func(t *testing.T) {
+               h := NewHandle(42)
+
+               defer func() {
+                       if r := recover(); r != nil {
+                               h.Delete()
+                               return
+                       }
+                       t.Fatalf("Invalid handle did not trigger a panic")
+               }()
+
+               Handle(h + 1).Delete()
+       })
+}
+
+func BenchmarkHandle(b *testing.B) {
+       b.Run("non-concurrent", func(b *testing.B) {
+               for i := 0; i < b.N; i++ {
+                       h := NewHandle(i)
+                       _ = h.Value()
+                       h.Delete()
+               }
+       })
+       b.Run("concurrent", func(b *testing.B) {
+               b.RunParallel(func(pb *testing.PB) {
+                       var v int
+                       for pb.Next() {
+                               h := NewHandle(v)
+                               _ = h.Value()
+                               h.Delete()
+                       }
+               })
+       })
+}
index 79fe65cb23425c63be9862790b5f064a9d90256c..0495d67f867d8c70d9dac53a29a7ab43d73c55fc 100644 (file)
@@ -15,6 +15,8 @@ import (
 //go:linkname cgoCheckPointer
 //go:linkname cgoCheckResult
 
+var ncgocall uint64 // number of cgo calls in total for dead m
+
 // Pointer checking for cgo code.
 
 // We want to detect all cases where a program that does not use
index 85d3e04ffff4a26d54db4692c340544346787873..4aae89fd4992a57990c449094b934372430481bd 100644 (file)
@@ -636,7 +636,7 @@ func TestNoShrinkStackWhileParking(t *testing.T) {
        // channel. See issue 40641 for more details on the problem.
        //
        // The way we try to induce this failure is to set up two
-       // goroutines: a sender and a reciever that communicate across
+       // goroutines: a sender and a receiver that communicate across
        // a channel. We try to set up a situation where the sender
        // grows its stack temporarily then *fully* blocks on a channel
        // often. Meanwhile a GC is triggered so that we try to get a
@@ -676,7 +676,7 @@ func TestNoShrinkStackWhileParking(t *testing.T) {
                go send(c, done)
                // Wait a little bit before triggering
                // the GC to make sure the sender and
-               // reciever have gotten into their groove.
+               // receiver have gotten into their groove.
                time.Sleep(50 * time.Microsecond)
                runtime.GC()
                <-done
@@ -713,8 +713,6 @@ func TestSelectDuplicateChannel(t *testing.T) {
        c <- 8 // wake up B.  This operation used to fail because c.recvq was corrupted (it tries to wake up an already running G instead of B)
 }
 
-var selectSink interface{}
-
 func TestSelectStackAdjust(t *testing.T) {
        // Test that channel receive slots that contain local stack
        // pointers are adjusted correctly by stack shrinking.
@@ -771,20 +769,8 @@ func TestSelectStackAdjust(t *testing.T) {
        <-ready2
        time.Sleep(10 * time.Millisecond)
 
-       // Force concurrent GC a few times.
-       var before, after runtime.MemStats
-       runtime.ReadMemStats(&before)
-       for i := 0; i < 100; i++ {
-               selectSink = new([1 << 20]byte)
-               runtime.ReadMemStats(&after)
-               if after.NumGC-before.NumGC >= 2 {
-                       goto done
-               }
-               runtime.Gosched()
-       }
-       t.Fatal("failed to trigger concurrent GC")
-done:
-       selectSink = nil
+       // Force concurrent GC to shrink the stacks.
+       runtime.GC()
 
        // Wake selects.
        close(d)
index e52f7df5b2bd3261c62e771208dc549ad14d05c1..ad3ad29cb2fe3876534c0bd314a34f21781be0c3 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 package runtime
@@ -9,6 +10,11 @@ package runtime
 import "unsafe"
 
 func checkptrAlignment(p unsafe.Pointer, elem *_type, n uintptr) {
+       // nil pointer is always suitably aligned (#47430).
+       if p == nil {
+               return
+       }
+
        // Check that (*[n]elem)(p) is appropriately aligned.
        // Note that we allow unaligned pointers if the types they point to contain
        // no pointers themselves. See issue 37298.
@@ -18,11 +24,32 @@ func checkptrAlignment(p unsafe.Pointer, elem *_type, n uintptr) {
        }
 
        // Check that (*[n]elem)(p) doesn't straddle multiple heap objects.
-       if size := n * elem.size; size > 1 && checkptrBase(p) != checkptrBase(add(p, size-1)) {
+       // TODO(mdempsky): Fix #46938 so we don't need to worry about overflow here.
+       if checkptrStraddles(p, n*elem.size) {
                throw("checkptr: converted pointer straddles multiple allocations")
        }
 }
 
+// checkptrStraddles reports whether the first size-bytes of memory
+// addressed by ptr is known to straddle more than one Go allocation.
+func checkptrStraddles(ptr unsafe.Pointer, size uintptr) bool {
+       if size <= 1 {
+               return false
+       }
+
+       // Check that add(ptr, size-1) won't overflow. This avoids the risk
+       // of producing an illegal pointer value (assuming ptr is legal).
+       if uintptr(ptr) >= -(size - 1) {
+               return true
+       }
+       end := add(ptr, size-1)
+
+       // TODO(mdempsky): Detect when [ptr, end] contains Go allocations,
+       // but neither ptr nor end point into one themselves.
+
+       return checkptrBase(ptr) != checkptrBase(end)
+}
+
 func checkptrArithmetic(p unsafe.Pointer, originals []unsafe.Pointer) {
        if 0 < uintptr(p) && uintptr(p) < minLegalPointer {
                throw("checkptr: pointer arithmetic computed bad pointer value")
index bd2d00f117a7d0e2e6780de0b59c7be6e9746833..3e4246970f9cf5e991de250cf305a568d08d71c8 100644 (file)
@@ -30,10 +30,13 @@ func TestCheckPtr(t *testing.T) {
        }{
                {"CheckPtrAlignmentPtr", "fatal error: checkptr: misaligned pointer conversion\n"},
                {"CheckPtrAlignmentNoPtr", ""},
+               {"CheckPtrAlignmentNilPtr", ""},
                {"CheckPtrArithmetic", "fatal error: checkptr: pointer arithmetic result points to invalid allocation\n"},
                {"CheckPtrArithmetic2", "fatal error: checkptr: pointer arithmetic result points to invalid allocation\n"},
                {"CheckPtrSize", "fatal error: checkptr: converted pointer straddles multiple allocations\n"},
                {"CheckPtrSmall", "fatal error: checkptr: pointer arithmetic computed bad pointer value\n"},
+               {"CheckPtrSliceOK", ""},
+               {"CheckPtrSliceFail", "fatal error: checkptr: unsafe.Slice result straddles multiple allocations\n"},
        }
 
        for _, tc := range testCases {
index 43f0a6705f5d6603549a0e58c310681830b87037..55ad0d112e73575d246d24f8573617a8355b3acf 100644 (file)
@@ -103,7 +103,16 @@ func (p *cpuProfile) add(gp *g, stk []uintptr) {
                // because otherwise its write barrier behavior may not
                // be correct. See the long comment there before
                // changing the argument here.
-               cpuprof.log.write(&gp.labels, nanotime(), hdr[:], stk)
+               //
+               // Note: it can happen on Windows, where we are calling
+               // p.add with a gp that is not the current g, that gp is nil,
+               // meaning we interrupted a system thread with no g.
+               // Avoid faulting in that case.
+               var tagPtr *unsafe.Pointer
+               if gp != nil {
+                       tagPtr = &gp.labels
+               }
+               cpuprof.log.write(tagPtr, nanotime(), hdr[:], stk)
        }
 
        atomic.Store(&prof.signalLock, 0)
index c41a58bafd0bd02f7128ed25ed3acb3727cdd521..84e3ce3675a54d19d8627a513e93c2298d86be08 100644 (file)
@@ -2,13 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// // +build !arm
-// // +build !arm64
-// // +build !mips64
-// // +build !mips64le
-// // +build !mips
-// // +build !mipsle
-// // +build !wasm
+//-go:build !arm && !arm64 && !mips64 && !mips64le && !mips && !mipsle && !wasm
+// -build !arm,!arm64,!mips64,!mips64le,!mips,!mipsle,!wasm
 
 package runtime
 
index b0198ffa2b6ed55604182c261c8898eda5f26109..6ad42b22a121757096e05878e6289d445dd750df 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build cgo
 // +build cgo
 
 package runtime_test
@@ -290,6 +291,18 @@ func TestCgoTracebackContext(t *testing.T) {
        }
 }
 
+func TestCgoTracebackContextPreemption(t *testing.T) {
+       t.Parallel()
+       if runtime.Compiler == "gccgo" {
+               t.Skip("gccgo does not have SetCgoTraceback")
+       }
+       got := runTestProg(t, "testprogcgo", "TracebackContextPreemption")
+       want := "OK\n"
+       if got != want {
+               t.Errorf("expected %q got %v", want, got)
+       }
+}
+
 func testCgoPprof(t *testing.T, buildArg, runArg, top, bottom string) {
        t.Parallel()
        if runtime.GOOS != "linux" || (runtime.GOARCH != "amd64" && runtime.GOARCH != "ppc64le") {
index 06c197ec2b2388a99948d87ee56b4bab573a2849..5f61476f217069a841cb0e3d4d62822d24fdeba0 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build windows || plan9 || (js && wasm)
 // +build windows plan9 js,wasm
 
 package runtime_test
index 102b1a5f476ee892bee72733cddb423ed67bc6bf..15c60008dbf13c200c1274b5139c8e1ba7f68e48 100644 (file)
@@ -474,14 +474,6 @@ func TestRecoverBeforePanicAfterGoexit2(t *testing.T) {
 }
 
 func TestNetpollDeadlock(t *testing.T) {
-       if os.Getenv("GO_BUILDER_NAME") == "darwin-amd64-10_12" {
-               // A suspected kernel bug in macOS 10.12 occasionally results in
-               // an apparent deadlock when dialing localhost. The errors have not
-               // been observed on newer versions of the OS, so we don't plan to work
-               // around them. See https://golang.org/issue/22019.
-               testenv.SkipFlaky(t, 22019)
-       }
-
        t.Parallel()
        output := runTestProg(t, "testprognet", "NetpollDeadlock")
        want := "done\n"
index 69aecd576baa054a7fe604847d8532361ba9b2cd..9dac167077a135795095e7848ac8c66bd260d04a 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package runtime_test
@@ -12,7 +13,6 @@ import (
        "io"
        "os"
        "os/exec"
-       "path/filepath"
        "runtime"
        "strings"
        "sync"
@@ -69,7 +69,8 @@ func TestCrashDumpsAllThreads(t *testing.T) {
                t.Skipf("skipping; not supported on %v", runtime.GOOS)
        }
 
-       if runtime.GOOS == "openbsd" && runtime.GOARCH == "mips64" {
+       if runtime.GOOS == "openbsd" && (runtime.GOARCH == "arm" || runtime.GOARCH == "mips64") {
+               // This may be ncpu < 2 related...
                t.Skipf("skipping; test fails on %s/%s - see issue #42464", runtime.GOOS, runtime.GOARCH)
        }
 
@@ -77,31 +78,14 @@ func TestCrashDumpsAllThreads(t *testing.T) {
                t.Skip("skipping; SIGQUIT is blocked, see golang.org/issue/19196")
        }
 
-       // We don't use executeTest because we need to kill the
-       // program while it is running.
-
        testenv.MustHaveGoBuild(t)
 
-       t.Parallel()
-
-       dir, err := os.MkdirTemp("", "go-build")
-       if err != nil {
-               t.Fatalf("failed to create temp directory: %v", err)
-       }
-       defer os.RemoveAll(dir)
-
-       if err := os.WriteFile(filepath.Join(dir, "main.go"), []byte(crashDumpsAllThreadsSource), 0666); err != nil {
-               t.Fatalf("failed to create Go file: %v", err)
-       }
-
-       cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", "a.exe", "main.go")
-       cmd.Dir = dir
-       out, err := testenv.CleanCmdEnv(cmd).CombinedOutput()
+       exe, err := buildTestProg(t, "testprog")
        if err != nil {
-               t.Fatalf("building source: %v\n%s", err, out)
+               t.Fatal(err)
        }
 
-       cmd = exec.Command(filepath.Join(dir, "a.exe"))
+       cmd := exec.Command(exe, "CrashDumpsAllThreads")
        cmd = testenv.CleanCmdEnv(cmd)
        cmd.Env = append(cmd.Env,
                "GOTRACEBACK=crash",
@@ -123,9 +107,12 @@ func TestCrashDumpsAllThreads(t *testing.T) {
        if err != nil {
                t.Fatal(err)
        }
+       defer rp.Close()
+
        cmd.ExtraFiles = []*os.File{wp}
 
        if err := cmd.Start(); err != nil {
+               wp.Close()
                t.Fatalf("starting program: %v", err)
        }
 
@@ -147,59 +134,14 @@ func TestCrashDumpsAllThreads(t *testing.T) {
        // We want to see a stack trace for each thread.
        // Before https://golang.org/cl/2811 running threads would say
        // "goroutine running on other thread; stack unavailable".
-       out = outbuf.Bytes()
-       n := bytes.Count(out, []byte("main.loop"))
+       out := outbuf.Bytes()
+       n := bytes.Count(out, []byte("main.crashDumpsAllThreadsLoop"))
        if n != 4 {
                t.Errorf("found %d instances of main.loop; expected 4", n)
                t.Logf("%s", out)
        }
 }
 
-const crashDumpsAllThreadsSource = `
-package main
-
-import (
-       "fmt"
-       "os"
-       "runtime"
-       "time"
-)
-
-func main() {
-       const count = 4
-       runtime.GOMAXPROCS(count + 1)
-
-       chans := make([]chan bool, count)
-       for i := range chans {
-               chans[i] = make(chan bool)
-               go loop(i, chans[i])
-       }
-
-       // Wait for all the goroutines to start executing.
-       for _, c := range chans {
-               <-c
-       }
-
-       time.Sleep(time.Millisecond)
-
-       // Tell our parent that all the goroutines are executing.
-       if _, err := os.NewFile(3, "pipe").WriteString("x"); err != nil {
-               fmt.Fprintf(os.Stderr, "write to pipe failed: %v\n", err)
-               os.Exit(2)
-       }
-
-       select {}
-}
-
-func loop(i int, c chan bool) {
-       close(c)
-       for {
-               for j := 0; j < 0x7fffffff; j++ {
-               }
-       }
-}
-`
-
 func TestPanicSystemstack(t *testing.T) {
        // Test that GOTRACEBACK=crash prints both the system and user
        // stack of other threads.
index 5fb02cb46682569596f8189378a777b94badd92b..0cd613a318325dbac49d7146a4f7eff4a2419096 100644 (file)
@@ -45,7 +45,7 @@ func NumCPU() int {
 
 // NumCgoCall returns the number of cgo calls made by the current process.
 func NumCgoCall() int64 {
-       var n int64
+       var n = int64(atomic.Load64(&ncgocall))
        for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
                n += int64(mp.ncgocall)
        }
index b67a3de4f98ef22d75f6db93b8dbbd9a6b1a3406..65f9555f3761c55022fe2a4e8ddc7ebf58e1207e 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd
 // +build aix darwin dragonfly freebsd linux netbsd openbsd
 
 // TODO: test on Windows?
@@ -23,6 +24,9 @@ func TestPanicOnFault(t *testing.T) {
        if runtime.GOOS == "ios" {
                t.Skip("iOS doesn't provide fault addresses")
        }
+       if runtime.GOOS == "netbsd" && runtime.GOARCH == "arm" {
+               t.Skip("netbsd-arm doesn't provide fault address (golang.org/issue/45026)")
+       }
        m, err := syscall.Mmap(-1, 0, 0x1000, syscall.PROT_READ /* Note: no PROT_WRITE */, syscall.MAP_SHARED|syscall.MAP_ANON)
        if err != nil {
                t.Fatalf("can't map anonymous memory: %s", err)
diff --git a/libgo/go/runtime/debug_test.go b/libgo/go/runtime/debug_test.go
deleted file mode 100644 (file)
index 46261bc..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// TODO: This test could be implemented on all (most?) UNIXes if we
-// added syscall.Tgkill more widely.
-
-// We skip all of these tests under race mode because our test thread
-// spends all of its time in the race runtime, which isn't a safe
-// point.
-
-// +build ignore_for_gccgo
-// +build amd64
-// +build linux
-// +build !race
-
-package runtime_test
-
-import (
-       "fmt"
-       "os"
-       "regexp"
-       "runtime"
-       "runtime/debug"
-       "sync/atomic"
-       "syscall"
-       "testing"
-)
-
-func startDebugCallWorker(t *testing.T) (g *runtime.G, after func()) {
-       // This can deadlock if run under a debugger because it
-       // depends on catching SIGTRAP, which is usually swallowed by
-       // a debugger.
-       skipUnderDebugger(t)
-
-       // This can deadlock if there aren't enough threads or if a GC
-       // tries to interrupt an atomic loop (see issue #10958). We
-       // use 8 Ps so there's room for the debug call worker,
-       // something that's trying to preempt the call worker, and the
-       // goroutine that's trying to stop the call worker.
-       ogomaxprocs := runtime.GOMAXPROCS(8)
-       ogcpercent := debug.SetGCPercent(-1)
-
-       // ready is a buffered channel so debugCallWorker won't block
-       // on sending to it. This makes it less likely we'll catch
-       // debugCallWorker while it's in the runtime.
-       ready := make(chan *runtime.G, 1)
-       var stop uint32
-       done := make(chan error)
-       go debugCallWorker(ready, &stop, done)
-       g = <-ready
-       return g, func() {
-               atomic.StoreUint32(&stop, 1)
-               err := <-done
-               if err != nil {
-                       t.Fatal(err)
-               }
-               runtime.GOMAXPROCS(ogomaxprocs)
-               debug.SetGCPercent(ogcpercent)
-       }
-}
-
-func debugCallWorker(ready chan<- *runtime.G, stop *uint32, done chan<- error) {
-       runtime.LockOSThread()
-       defer runtime.UnlockOSThread()
-
-       ready <- runtime.Getg()
-
-       x := 2
-       debugCallWorker2(stop, &x)
-       if x != 1 {
-               done <- fmt.Errorf("want x = 2, got %d; register pointer not adjusted?", x)
-       }
-       close(done)
-}
-
-// Don't inline this function, since we want to test adjusting
-// pointers in the arguments.
-//
-//go:noinline
-func debugCallWorker2(stop *uint32, x *int) {
-       for atomic.LoadUint32(stop) == 0 {
-               // Strongly encourage x to live in a register so we
-               // can test pointer register adjustment.
-               *x++
-       }
-       *x = 1
-}
-
-func debugCallTKill(tid int) error {
-       return syscall.Tgkill(syscall.Getpid(), tid, syscall.SIGTRAP)
-}
-
-// skipUnderDebugger skips the current test when running under a
-// debugger (specifically if this process has a tracer). This is
-// Linux-specific.
-func skipUnderDebugger(t *testing.T) {
-       pid := syscall.Getpid()
-       status, err := os.ReadFile(fmt.Sprintf("/proc/%d/status", pid))
-       if err != nil {
-               t.Logf("couldn't get proc tracer: %s", err)
-               return
-       }
-       re := regexp.MustCompile(`TracerPid:\s+([0-9]+)`)
-       sub := re.FindSubmatch(status)
-       if sub == nil {
-               t.Logf("couldn't find proc tracer PID")
-               return
-       }
-       if string(sub[1]) == "0" {
-               return
-       }
-       t.Skip("test will deadlock under a debugger")
-}
-
-func TestDebugCall(t *testing.T) {
-       g, after := startDebugCallWorker(t)
-       defer after()
-
-       // Inject a call into the debugCallWorker goroutine and test
-       // basic argument and result passing.
-       var args struct {
-               x    int
-               yRet int
-       }
-       fn := func(x int) (yRet int) {
-               return x + 1
-       }
-       args.x = 42
-       if _, err := runtime.InjectDebugCall(g, fn, &args, debugCallTKill, false); err != nil {
-               t.Fatal(err)
-       }
-       if args.yRet != 43 {
-               t.Fatalf("want 43, got %d", args.yRet)
-       }
-}
-
-func TestDebugCallLarge(t *testing.T) {
-       g, after := startDebugCallWorker(t)
-       defer after()
-
-       // Inject a call with a large call frame.
-       const N = 128
-       var args struct {
-               in  [N]int
-               out [N]int
-       }
-       fn := func(in [N]int) (out [N]int) {
-               for i := range in {
-                       out[i] = in[i] + 1
-               }
-               return
-       }
-       var want [N]int
-       for i := range args.in {
-               args.in[i] = i
-               want[i] = i + 1
-       }
-       if _, err := runtime.InjectDebugCall(g, fn, &args, debugCallTKill, false); err != nil {
-               t.Fatal(err)
-       }
-       if want != args.out {
-               t.Fatalf("want %v, got %v", want, args.out)
-       }
-}
-
-func TestDebugCallGC(t *testing.T) {
-       g, after := startDebugCallWorker(t)
-       defer after()
-
-       // Inject a call that performs a GC.
-       if _, err := runtime.InjectDebugCall(g, runtime.GC, nil, debugCallTKill, false); err != nil {
-               t.Fatal(err)
-       }
-}
-
-func TestDebugCallGrowStack(t *testing.T) {
-       g, after := startDebugCallWorker(t)
-       defer after()
-
-       // Inject a call that grows the stack. debugCallWorker checks
-       // for stack pointer breakage.
-       if _, err := runtime.InjectDebugCall(g, func() { growStack(nil) }, nil, debugCallTKill, false); err != nil {
-               t.Fatal(err)
-       }
-}
-
-//go:nosplit
-func debugCallUnsafePointWorker(gpp **runtime.G, ready, stop *uint32) {
-       // The nosplit causes this function to not contain safe-points
-       // except at calls.
-       runtime.LockOSThread()
-       defer runtime.UnlockOSThread()
-
-       *gpp = runtime.Getg()
-
-       for atomic.LoadUint32(stop) == 0 {
-               atomic.StoreUint32(ready, 1)
-       }
-}
-
-func TestDebugCallUnsafePoint(t *testing.T) {
-       skipUnderDebugger(t)
-
-       // This can deadlock if there aren't enough threads or if a GC
-       // tries to interrupt an atomic loop (see issue #10958).
-       defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(8))
-       defer debug.SetGCPercent(debug.SetGCPercent(-1))
-
-       // Test that the runtime refuses call injection at unsafe points.
-       var g *runtime.G
-       var ready, stop uint32
-       defer atomic.StoreUint32(&stop, 1)
-       go debugCallUnsafePointWorker(&g, &ready, &stop)
-       for atomic.LoadUint32(&ready) == 0 {
-               runtime.Gosched()
-       }
-
-       _, err := runtime.InjectDebugCall(g, func() {}, nil, debugCallTKill, true)
-       if msg := "call not at safe point"; err == nil || err.Error() != msg {
-               t.Fatalf("want %q, got %s", msg, err)
-       }
-}
-
-func TestDebugCallPanic(t *testing.T) {
-       skipUnderDebugger(t)
-
-       // This can deadlock if there aren't enough threads.
-       defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(8))
-
-       ready := make(chan *runtime.G)
-       var stop uint32
-       defer atomic.StoreUint32(&stop, 1)
-       go func() {
-               runtime.LockOSThread()
-               defer runtime.UnlockOSThread()
-               ready <- runtime.Getg()
-               for atomic.LoadUint32(&stop) == 0 {
-               }
-       }()
-       g := <-ready
-
-       p, err := runtime.InjectDebugCall(g, func() { panic("test") }, nil, debugCallTKill, false)
-       if err != nil {
-               t.Fatal(err)
-       }
-       if ps, ok := p.(string); !ok || ps != "test" {
-               t.Fatalf("wanted panic %v, got %v", "test", p)
-       }
-}
index bb3e172498e7ec030a45be839f9c4f5a9187df86..dd3815699929411a86170237417b1f4f6b6e0656 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !debuglog
 // +build !debuglog
 
 package runtime
index 3d477e8ef5fb8c2e1b67ba9301135bed15b6613d..2fcdbe70d14428e4f805f27b360a69e062661e90 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build debuglog
 // +build debuglog
 
 package runtime
index 9a40ea19842faf029d6a2502c38c15fedddb1f52..fc961445975867b219812a9f6846790a5dc1996c 100644 (file)
@@ -370,7 +370,7 @@ func g2() {
        defer ap.method2()
        defer ap.method1()
        ff1(ap, 1, 2, 3, 4, 5, 6, 7, 8, 9)
-       // Try to get the stack to be be moved by growing it too large, so
+       // Try to get the stack to be moved by growing it too large, so
        // existing stack-allocated defer becomes invalid.
        rec1(2000)
 }
diff --git a/libgo/go/runtime/defs_windows_arm64.go b/libgo/go/runtime/defs_windows_arm64.go
new file mode 100644 (file)
index 0000000..9ccce46
--- /dev/null
@@ -0,0 +1,83 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+// NOTE(rsc): _CONTEXT_CONTROL is actually 0x400001 and should include PC, SP, and LR.
+// However, empirically, LR doesn't come along on Windows 10
+// unless you also set _CONTEXT_INTEGER (0x400002).
+// Without LR, we skip over the next-to-bottom function in profiles
+// when the bottom function is frameless.
+// So we set both here, to make a working _CONTEXT_CONTROL.
+const _CONTEXT_CONTROL = 0x400003
+
+type neon128 struct {
+       low  uint64
+       high int64
+}
+
+// See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-arm64_nt_context
+type context struct {
+       contextflags uint32
+       cpsr         uint32
+       x            [31]uint64 // fp is x[29], lr is x[30]
+       xsp          uint64
+       pc           uint64
+       v            [32]neon128
+       fpcr         uint32
+       fpsr         uint32
+       bcr          [8]uint32
+       bvr          [8]uint64
+       wcr          [2]uint32
+       wvr          [2]uint64
+}
+
+func (c *context) ip() uintptr { return uintptr(c.pc) }
+func (c *context) sp() uintptr { return uintptr(c.xsp) }
+func (c *context) lr() uintptr { return uintptr(c.x[30]) }
+
+func (c *context) set_ip(x uintptr) { c.pc = uint64(x) }
+func (c *context) set_sp(x uintptr) { c.xsp = uint64(x) }
+func (c *context) set_lr(x uintptr) { c.x[30] = uint64(x) }
+
+func dumpregs(r *context) {
+       print("r0   ", hex(r.x[0]), "\n")
+       print("r1   ", hex(r.x[1]), "\n")
+       print("r2   ", hex(r.x[2]), "\n")
+       print("r3   ", hex(r.x[3]), "\n")
+       print("r4   ", hex(r.x[4]), "\n")
+       print("r5   ", hex(r.x[5]), "\n")
+       print("r6   ", hex(r.x[6]), "\n")
+       print("r7   ", hex(r.x[7]), "\n")
+       print("r8   ", hex(r.x[8]), "\n")
+       print("r9   ", hex(r.x[9]), "\n")
+       print("r10  ", hex(r.x[10]), "\n")
+       print("r11  ", hex(r.x[11]), "\n")
+       print("r12  ", hex(r.x[12]), "\n")
+       print("r13  ", hex(r.x[13]), "\n")
+       print("r14  ", hex(r.x[14]), "\n")
+       print("r15  ", hex(r.x[15]), "\n")
+       print("r16  ", hex(r.x[16]), "\n")
+       print("r17  ", hex(r.x[17]), "\n")
+       print("r18  ", hex(r.x[18]), "\n")
+       print("r19  ", hex(r.x[19]), "\n")
+       print("r20  ", hex(r.x[20]), "\n")
+       print("r21  ", hex(r.x[21]), "\n")
+       print("r22  ", hex(r.x[22]), "\n")
+       print("r23  ", hex(r.x[23]), "\n")
+       print("r24  ", hex(r.x[24]), "\n")
+       print("r25  ", hex(r.x[25]), "\n")
+       print("r26  ", hex(r.x[26]), "\n")
+       print("r27  ", hex(r.x[27]), "\n")
+       print("r28  ", hex(r.x[28]), "\n")
+       print("r29  ", hex(r.x[29]), "\n")
+       print("lr   ", hex(r.x[30]), "\n")
+       print("sp   ", hex(r.xsp), "\n")
+       print("pc   ", hex(r.pc), "\n")
+       print("cpsr ", hex(r.cpsr), "\n")
+}
+
+func stackcheck() {
+       // TODO: not implemented on ARM
+}
index 48b9c4a32e113c4a32edfacd5c8925af0662b608..8893c4a6195f06529e8475b2f3688eae5b13deb4 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows || plan9
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows plan9
 
 package runtime
index 8dac9297509d5f08340428a7104edb310de0c3d6..e7f8dbc13061dd81c502ddd8a9bb4d510045d09e 100644 (file)
@@ -12,12 +12,15 @@ import (
 
 func ExampleFrames() {
        c := func() {
-               // Ask runtime.Callers for up to 10 pcs, including runtime.Callers itself.
+               // Ask runtime.Callers for up to 10 PCs, including runtime.Callers itself.
                pc := make([]uintptr, 10)
                n := runtime.Callers(0, pc)
                if n == 0 {
-                       // No pcs available. Stop now.
-                       // This can happen if the first argument to runtime.Callers is large.
+                       // No PCs available. This can happen if the first argument to
+                       // runtime.Callers is large.
+                       //
+                       // Return now to avoid processing the zero Frame that would
+                       // otherwise be returned by frames.Next below.
                        return
                }
 
@@ -25,9 +28,12 @@ func ExampleFrames() {
                frames := runtime.CallersFrames(pc)
 
                // Loop to get frames.
-               // A fixed number of pcs can expand to an indefinite number of Frames.
+               // A fixed number of PCs can expand to an indefinite number of Frames.
                for {
                        frame, more := frames.Next()
+
+                       // Process this frame.
+                       //
                        // To keep this example's output stable
                        // even if there are changes in the testing package,
                        // stop unwinding when we leave package runtime.
@@ -35,6 +41,8 @@ func ExampleFrames() {
                                break
                        }
                        fmt.Printf("- more:%v | %s\n", more, frame.Function)
+
+                       // Check whether there are more frames to process after this one.
                        if !more {
                                break
                        }
diff --git a/libgo/go/runtime/export_debug_test.go b/libgo/go/runtime/export_debug_test.go
deleted file mode 100644 (file)
index c1cc44f..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore_for_gccgo
-// +build amd64
-// +build linux
-
-package runtime
-
-import (
-       "runtime/internal/sys"
-       "unsafe"
-)
-
-// InjectDebugCall injects a debugger call to fn into g. args must be
-// a pointer to a valid call frame (including arguments and return
-// space) for fn, or nil. tkill must be a function that will send
-// SIGTRAP to thread ID tid. gp must be locked to its OS thread and
-// running.
-//
-// On success, InjectDebugCall returns the panic value of fn or nil.
-// If fn did not panic, its results will be available in args.
-func InjectDebugCall(gp *g, fn, args interface{}, tkill func(tid int) error, returnOnUnsafePoint bool) (interface{}, error) {
-       if gp.lockedm == 0 {
-               return nil, plainError("goroutine not locked to thread")
-       }
-
-       tid := int(gp.lockedm.ptr().procid)
-       if tid == 0 {
-               return nil, plainError("missing tid")
-       }
-
-       f := efaceOf(&fn)
-       if f._type == nil || f._type.kind&kindMask != kindFunc {
-               return nil, plainError("fn must be a function")
-       }
-       fv := (*funcval)(f.data)
-
-       a := efaceOf(&args)
-       if a._type != nil && a._type.kind&kindMask != kindPtr {
-               return nil, plainError("args must be a pointer or nil")
-       }
-       argp := a.data
-       var argSize uintptr
-       if argp != nil {
-               argSize = (*ptrtype)(unsafe.Pointer(a._type)).elem.size
-       }
-
-       h := new(debugCallHandler)
-       h.gp = gp
-       // gp may not be running right now, but we can still get the M
-       // it will run on since it's locked.
-       h.mp = gp.lockedm.ptr()
-       h.fv, h.argp, h.argSize = fv, argp, argSize
-       h.handleF = h.handle // Avoid allocating closure during signal
-
-       defer func() { testSigtrap = nil }()
-       for i := 0; ; i++ {
-               testSigtrap = h.inject
-               noteclear(&h.done)
-               h.err = ""
-
-               if err := tkill(tid); err != nil {
-                       return nil, err
-               }
-               // Wait for completion.
-               notetsleepg(&h.done, -1)
-               if h.err != "" {
-                       switch h.err {
-                       case "call not at safe point":
-                               if returnOnUnsafePoint {
-                                       // This is for TestDebugCallUnsafePoint.
-                                       return nil, h.err
-                               }
-                               fallthrough
-                       case "retry _Grunnable", "executing on Go runtime stack", "call from within the Go runtime":
-                               // These are transient states. Try to get out of them.
-                               if i < 100 {
-                                       usleep(100)
-                                       Gosched()
-                                       continue
-                               }
-                       }
-                       return nil, h.err
-               }
-               return h.panic, nil
-       }
-}
-
-type debugCallHandler struct {
-       gp      *g
-       mp      *m
-       fv      *funcval
-       argp    unsafe.Pointer
-       argSize uintptr
-       panic   interface{}
-
-       handleF func(info *siginfo, ctxt *sigctxt, gp2 *g) bool
-
-       err       plainError
-       done      note
-       savedRegs sigcontext
-       savedFP   fpstate1
-}
-
-func (h *debugCallHandler) inject(info *siginfo, ctxt *sigctxt, gp2 *g) bool {
-       switch h.gp.atomicstatus {
-       case _Grunning:
-               if getg().m != h.mp {
-                       println("trap on wrong M", getg().m, h.mp)
-                       return false
-               }
-               // Push current PC on the stack.
-               rsp := ctxt.rsp() - sys.PtrSize
-               *(*uint64)(unsafe.Pointer(uintptr(rsp))) = ctxt.rip()
-               ctxt.set_rsp(rsp)
-               // Write the argument frame size.
-               *(*uintptr)(unsafe.Pointer(uintptr(rsp - 16))) = h.argSize
-               // Save current registers.
-               h.savedRegs = *ctxt.regs()
-               h.savedFP = *h.savedRegs.fpstate
-               h.savedRegs.fpstate = nil
-               // Set PC to debugCallV1.
-               ctxt.set_rip(uint64(funcPC(debugCallV1)))
-               // Call injected. Switch to the debugCall protocol.
-               testSigtrap = h.handleF
-       case _Grunnable:
-               // Ask InjectDebugCall to pause for a bit and then try
-               // again to interrupt this goroutine.
-               h.err = plainError("retry _Grunnable")
-               notewakeup(&h.done)
-       default:
-               h.err = plainError("goroutine in unexpected state at call inject")
-               notewakeup(&h.done)
-       }
-       // Resume execution.
-       return true
-}
-
-func (h *debugCallHandler) handle(info *siginfo, ctxt *sigctxt, gp2 *g) bool {
-       // Sanity check.
-       if getg().m != h.mp {
-               println("trap on wrong M", getg().m, h.mp)
-               return false
-       }
-       f := findfunc(uintptr(ctxt.rip()))
-       if !(hasPrefix(funcname(f), "runtime.debugCall") || hasPrefix(funcname(f), "debugCall")) {
-               println("trap in unknown function", funcname(f))
-               return false
-       }
-       if *(*byte)(unsafe.Pointer(uintptr(ctxt.rip() - 1))) != 0xcc {
-               println("trap at non-INT3 instruction pc =", hex(ctxt.rip()))
-               return false
-       }
-
-       switch status := ctxt.rax(); status {
-       case 0:
-               // Frame is ready. Copy the arguments to the frame.
-               sp := ctxt.rsp()
-               memmove(unsafe.Pointer(uintptr(sp)), h.argp, h.argSize)
-               // Push return PC.
-               sp -= sys.PtrSize
-               ctxt.set_rsp(sp)
-               *(*uint64)(unsafe.Pointer(uintptr(sp))) = ctxt.rip()
-               // Set PC to call and context register.
-               ctxt.set_rip(uint64(h.fv.fn))
-               ctxt.regs().rcx = uint64(uintptr(unsafe.Pointer(h.fv)))
-       case 1:
-               // Function returned. Copy frame back out.
-               sp := ctxt.rsp()
-               memmove(h.argp, unsafe.Pointer(uintptr(sp)), h.argSize)
-       case 2:
-               // Function panicked. Copy panic out.
-               sp := ctxt.rsp()
-               memmove(unsafe.Pointer(&h.panic), unsafe.Pointer(uintptr(sp)), 2*sys.PtrSize)
-       case 8:
-               // Call isn't safe. Get the reason.
-               sp := ctxt.rsp()
-               reason := *(*string)(unsafe.Pointer(uintptr(sp)))
-               h.err = plainError(reason)
-               // Don't wake h.done. We need to transition to status 16 first.
-       case 16:
-               // Restore all registers except RIP and RSP.
-               rip, rsp := ctxt.rip(), ctxt.rsp()
-               fp := ctxt.regs().fpstate
-               *ctxt.regs() = h.savedRegs
-               ctxt.regs().fpstate = fp
-               *fp = h.savedFP
-               ctxt.set_rip(rip)
-               ctxt.set_rsp(rsp)
-               // Done
-               notewakeup(&h.done)
-       default:
-               h.err = plainError("unexpected debugCallV1 status")
-               notewakeup(&h.done)
-       }
-       // Resume execution.
-       return true
-}
index 000948b78c3f2f534d6cf602eb93cdc48b04b5c3..aa498bb932eb4ff649d7cffbe49342c215288b7c 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 // Export guts for testing.
index 209c6b14a112e485900616f190e4e0107cc69e6d..22ac4b7a05d7f10c7ec39b5e5fe256354887dd8a 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build freebsd hurd linux netbsd openbsd solaris
+//go:build dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
+// +build dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package runtime
 
index 8f66770fb98631b2866ef0aedafc1f0db02b3609..a0c6c0440d8d94447157f28f762bc1587ca7ab09 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build aix darwin dragonfly
+//go:build aix || darwin
+// +build aix darwin
 
 package runtime
 
index 1455c2247d8a295d5b022f0f28655df695014119..5255a708e2270023b4d86b471a171eb859959a89 100644 (file)
@@ -46,6 +46,14 @@ var NetpollGenericInit = netpollGenericInit
 var Memmove = memmove
 var MemclrNoHeapPointers = memclrNoHeapPointers
 
+var LockPartialOrder = lockPartialOrder
+
+type LockRank lockRank
+
+func (l LockRank) String() string {
+       return lockRank(l).String()
+}
+
 const PreemptMSupported = preemptMSupported
 
 type LFNode struct {
@@ -136,35 +144,47 @@ func RunSchedLocalQueueStealTest() {
        }
 }
 
+// Temporary to enable register ABI bringup.
+// TODO(register args): convert back to local variables in RunSchedLocalQueueEmptyTest that
+// get passed to the "go" stmts there.
+var RunSchedLocalQueueEmptyState struct {
+       done  chan bool
+       ready *uint32
+       p     *p
+}
+
 func RunSchedLocalQueueEmptyTest(iters int) {
        // Test that runq is not spuriously reported as empty.
        // Runq emptiness affects scheduling decisions and spurious emptiness
        // can lead to underutilization (both runnable Gs and idle Ps coexist
        // for arbitrary long time).
        done := make(chan bool, 1)
-       _p_ := new(p)
+       RunSchedLocalQueueEmptyState.done = done
+       p := new(p)
+       RunSchedLocalQueueEmptyState.p = p
        gs := make([]g, 2)
        ready := new(uint32)
+       RunSchedLocalQueueEmptyState.ready = ready
        for i := 0; i < iters; i++ {
                *ready = 0
                next0 := (i & 1) == 0
                next1 := (i & 2) == 0
-               runqput(_p_, &gs[0], next0)
-               go func(done chan bool, p *p, ready *uint32, next0, next1 bool) {
-                       for atomic.Xadd(ready, 1); atomic.Load(ready) != 2; {
+               runqput(p, &gs[0], next0)
+               go func() {
+                       for atomic.Xadd(RunSchedLocalQueueEmptyState.ready, 1); atomic.Load(RunSchedLocalQueueEmptyState.ready) != 2; {
                        }
-                       if runqempty(p) {
-                               println("next:", next0, next1)
+                       if runqempty(RunSchedLocalQueueEmptyState.p) {
+                               //println("next:", next0, next1)
                                throw("queue is empty")
                        }
-                       done <- true
-               }(done, _p_, ready, next0, next1)
+                       RunSchedLocalQueueEmptyState.done <- true
+               }()
                for atomic.Xadd(ready, 1); atomic.Load(ready) != 2; {
                }
-               runqput(_p_, &gs[1], next1)
-               runqget(_p_)
+               runqput(p, &gs[1], next1)
+               runqget(p)
                <-done
-               runqget(_p_)
+               runqget(p)
        }
 }
 
@@ -195,8 +215,6 @@ var HashLoad = &hashLoad
 //     return
 //}
 
-type Uintreg sys.Uintreg
-
 var Open = open
 var Close = closefd
 var Read = read
@@ -370,7 +388,7 @@ func ReadMemStatsSlow() (base, slow MemStats) {
                        bySize[i].Mallocs += uint64(m.smallFreeCount[i])
                        smallFree += uint64(m.smallFreeCount[i]) * uint64(class_to_size[i])
                }
-               slow.Frees += memstats.tinyallocs + uint64(m.largeFreeCount)
+               slow.Frees += uint64(m.tinyAllocCount) + uint64(m.largeFreeCount)
                slow.Mallocs += slow.Frees
 
                slow.TotalAlloc = slow.Alloc + uint64(m.largeFree) + smallFree
@@ -393,9 +411,6 @@ func ReadMemStatsSlow() (base, slow MemStats) {
                        slow.HeapReleased += uint64(pg) * pageSize
                }
 
-               // Unused space in the current arena also counts as released space.
-               slow.HeapReleased += uint64(mheap_.curArena.end - mheap_.curArena.base)
-
                getg().m.mallocing--
        })
 
@@ -1127,31 +1142,6 @@ func SemNwait(addr *uint32) uint32 {
        return atomic.Load(&root.nwait)
 }
 
-// MapHashCheck computes the hash of the key k for the map m, twice.
-// Method 1 uses the built-in hasher for the map.
-// Method 2 uses the typehash function (the one used by reflect).
-// Returns the two hash values, which should always be equal.
-func MapHashCheck(m interface{}, k interface{}) (uintptr, uintptr) {
-       // Unpack m.
-       mt := (*maptype)(unsafe.Pointer(efaceOf(&m)._type))
-       mh := (*hmap)(efaceOf(&m).data)
-
-       // Unpack k.
-       kt := efaceOf(&k)._type
-       var p unsafe.Pointer
-       if isDirectIface(kt) {
-               q := efaceOf(&k).data
-               p = unsafe.Pointer(&q)
-       } else {
-               p = efaceOf(&k).data
-       }
-
-       // Compute the hash functions.
-       x := mt.hasher(noescape(p), uintptr(mh.hash0))
-       y := typehash(kt, noescape(p), uintptr(mh.hash0))
-       return x, y
-}
-
 // mspan wrapper for testing.
 //go:notinheap
 type MSpan mspan
@@ -1210,3 +1200,28 @@ func (th *TimeHistogram) Record(duration int64) {
 }
 
 var Pusestackmaps = &usestackmaps
+
+func FinalizerGAsleep() bool {
+       lock(&finlock)
+       result := fingwait
+       unlock(&finlock)
+       return result
+}
+
+// For GCTestIsReachable, it's important that we do this as a call so
+// escape analysis can see through it.
+func GCTestIsReachable(ptrs ...unsafe.Pointer) (mask uint64) {
+       return gcTestIsReachable(ptrs...)
+}
+
+// For GCTestPointerClass, it's important that we do this as a call so
+// escape analysis can see through it.
+//
+// This is nosplit because gcTestPointerClass is.
+//
+//go:nosplit
+func GCTestPointerClass(p unsafe.Pointer) string {
+       return gcTestPointerClass(p)
+}
+
+const Raceenabled = raceenabled
index 801786d60e6e04c8618fbbb878c163c50a6164b5..180af01047adec7a94ca86b7ac0fb96a2d30c44a 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package runtime
index 8d10c8572db252876093e39ec54bb82ad6cda9d2..0d7f35779130398a9044c71236bbbc60557f4586 100644 (file)
@@ -110,8 +110,6 @@ It is a comma-separated list of name=val pairs setting these named variables:
        with a trivial allocator that obtains memory from the operating system and
        never reclaims any memory.
 
-       scavenge: scavenge=1 enables debugging mode of heap scavenger.
-
        scavtrace: setting scavtrace=1 causes the runtime to emit a single line to standard
        error, roughly once per GC cycle, summarizing the amount of work done by the
        scavenger as well as the total amount of memory returned to the operating system
@@ -213,6 +211,8 @@ func Caller(skip int) (pc uintptr, file string, line int, ok bool)
 // program counter adjustment.
 func Callers(skip int, pc []uintptr) int
 
+var defaultGOROOT string // set by cmd/link
+
 // GOROOT returns the root of the Go tree. It uses the
 // GOROOT environment variable, if set at process start,
 // or else the root used during the Go build.
@@ -221,14 +221,24 @@ func GOROOT() string {
        if s != "" {
                return s
        }
-       return sys.DefaultGoroot
+       return defaultGOROOT
 }
 
+// buildVersion is the Go tree's version string at build time.
+//
+// If any GOEXPERIMENTs are set to non-default values, it will include
+// "X:<GOEXPERIMENT>".
+//
+// This is set by the linker.
+//
+// This is accessed by "go version <binary>".
+var buildVersion string
+
 // Version returns the Go tree's version string.
 // It is either the commit hash and date at the time of the build or,
 // when possible, a release tag like "go1.3".
 func Version() string {
-       return sys.TheVersion
+       return buildVersion
 }
 
 // GOOS is the running program's operating system target:
index cde2e14395e9d6c8d4c9d6cacf7525212a167eb5..bb5e1ae6ebf0a8e91ed9d22ee0ea7ae7c17c10b1 100644 (file)
@@ -208,6 +208,126 @@ func TestGcZombieReporting(t *testing.T) {
        }
 }
 
+/*
+
+func TestGCTestMoveStackOnNextCall(t *testing.T) {
+       t.Parallel()
+       var onStack int
+       // GCTestMoveStackOnNextCall can fail in rare cases if there's
+       // a preemption. This won't happen many times in quick
+       // succession, so just retry a few times.
+       for retry := 0; retry < 5; retry++ {
+               runtime.GCTestMoveStackOnNextCall()
+               if moveStackCheck(t, &onStack, uintptr(unsafe.Pointer(&onStack))) {
+                       // Passed.
+                       return
+               }
+       }
+       t.Fatal("stack did not move")
+}
+
+// This must not be inlined because the point is to force a stack
+// growth check and move the stack.
+//
+//go:noinline
+func moveStackCheck(t *testing.T, new *int, old uintptr) bool {
+       // new should have been updated by the stack move;
+       // old should not have.
+
+       // Capture new's value before doing anything that could
+       // further move the stack.
+       new2 := uintptr(unsafe.Pointer(new))
+
+       t.Logf("old stack pointer %x, new stack pointer %x", old, new2)
+       if new2 == old {
+               // Check that we didn't screw up the test's escape analysis.
+               if cls := runtime.GCTestPointerClass(unsafe.Pointer(new)); cls != "stack" {
+                       t.Fatalf("test bug: new (%#x) should be a stack pointer, not %s", new2, cls)
+               }
+               // This was a real failure.
+               return false
+       }
+       return true
+}
+
+func TestGCTestMoveStackRepeatedly(t *testing.T) {
+       // Move the stack repeatedly to make sure we're not doubling
+       // it each time.
+       for i := 0; i < 100; i++ {
+               runtime.GCTestMoveStackOnNextCall()
+               moveStack1(false)
+       }
+}
+
+//go:noinline
+func moveStack1(x bool) {
+       // Make sure this function doesn't get auto-nosplit.
+       if x {
+               println("x")
+       }
+}
+
+*/
+
+func TestGCTestIsReachable(t *testing.T) {
+       var all, half []unsafe.Pointer
+       var want uint64
+       for i := 0; i < 16; i++ {
+               // The tiny allocator muddies things, so we use a
+               // scannable type.
+               p := unsafe.Pointer(new(*int))
+               all = append(all, p)
+               if i%2 == 0 {
+                       half = append(half, p)
+                       want |= 1 << i
+               }
+       }
+
+       got := runtime.GCTestIsReachable(all...)
+       if want != got {
+               // gccgo's conservative GC means that we sometimes
+               // keep data we shouldn't.
+               if runtime.Compiler == "gccgo" {
+                       if ((got ^ want) & want) != 0 {
+                               t.Fatalf("some expected bits not set: want %b, got %b", want, got)
+                       }
+               } else {
+                       t.Fatalf("did not get expected reachable set; want %b, got %b", want, got)
+               }
+       }
+       runtime.KeepAlive(half)
+}
+
+var pointerClassSink *int
+var pointerClassData = 42
+
+func TestGCTestPointerClass(t *testing.T) {
+       if runtime.Compiler == "gccgo" {
+               // gofrontend escape analysis doesn't handle passing
+               // &onStack through a closure.
+               t.Skip("skipping for gofrontend")
+       }
+
+       t.Parallel()
+       check := func(p unsafe.Pointer, want string) {
+               t.Helper()
+               got := runtime.GCTestPointerClass(p)
+               if got != want {
+                       // Convert the pointer to a uintptr to avoid
+                       // escaping it.
+                       t.Errorf("for %#x, want class %s, got %s", uintptr(p), want, got)
+               }
+       }
+       var onStack int
+       var notOnStack int
+       pointerClassSink = &notOnStack
+       check(unsafe.Pointer(&onStack), "stack")
+       check(unsafe.Pointer(&notOnStack), "heap")
+       check(unsafe.Pointer(&pointerClassSink), "bss")
+       check(unsafe.Pointer(&pointerClassData), "data")
+       check(nil, "other")
+}
+
 func BenchmarkSetTypePtr(b *testing.B) {
        benchSetType(b, new(*byte))
 }
index 89efc1cde5c44cb8fbf3dd8d49fd9bd033955c99..58ae38b200daf47416099e87dfbabdd047ef98fc 100644 (file)
@@ -3,10 +3,10 @@
 // license that can be found in the LICENSE file.
 
 // Hashing algorithm inspired by
-//   xxhash: https://code.google.com/p/xxhash/
-// cityhash: https://code.google.com/p/cityhash/
+// wyhash: https://github.com/wangyi-fudan/wyhash/blob/ceb019b530e2c1c14d70b79bfa2bc49de7d95bc1/Modern%20Non-Cryptographic%20Hash%20Function%20and%20Pseudorandom%20Number%20Generator.pdf
 
-// +build 386 arm armbe m68k mips mipsle nios2 ppc riscv s390 sh shbe sparc
+//go:build 386 || arm || mips || mipsle || armbe || m68k || nios2 || ppc || riscv || s390 || sh || shbe || sparc
+// +build 386 arm mips mipsle armbe m68k nios2 ppc riscv s390 sh shbe sparc
 
 package runtime
 
@@ -16,104 +16,54 @@ import "unsafe"
 //
 //go:linkname memhash
 
-const (
-       // Constants for multiplication: four random odd 32-bit numbers.
-       m1 = 3168982561
-       m2 = 3339683297
-       m3 = 832293441
-       m4 = 2336365089
-)
+func memhash32(p unsafe.Pointer, seed uintptr) uintptr {
+       a, b := mix32(uint32(seed), uint32(4^hashkey[0]))
+       t := readUnaligned32(p)
+       a ^= t
+       b ^= t
+       a, b = mix32(a, b)
+       a, b = mix32(a, b)
+       return uintptr(a ^ b)
+}
+
+func memhash64(p unsafe.Pointer, seed uintptr) uintptr {
+       a, b := mix32(uint32(seed), uint32(8^hashkey[0]))
+       a ^= readUnaligned32(p)
+       b ^= readUnaligned32(add(p, 4))
+       a, b = mix32(a, b)
+       a, b = mix32(a, b)
+       return uintptr(a ^ b)
+}
 
 func memhash(p unsafe.Pointer, seed, s uintptr) uintptr {
        if GOARCH == "386" && GOOS != "nacl" && useAeshash {
                return aeshash(p, seed, s)
        }
-       h := uint32(seed + s*hashkey[0])
-tail:
-       switch {
-       case s == 0:
-       case s < 4:
-               h ^= uint32(*(*byte)(p))
-               h ^= uint32(*(*byte)(add(p, s>>1))) << 8
-               h ^= uint32(*(*byte)(add(p, s-1))) << 16
-               h = rotl_15(h*m1) * m2
-       case s == 4:
-               h ^= readUnaligned32(p)
-               h = rotl_15(h*m1) * m2
-       case s <= 8:
-               h ^= readUnaligned32(p)
-               h = rotl_15(h*m1) * m2
-               h ^= readUnaligned32(add(p, s-4))
-               h = rotl_15(h*m1) * m2
-       case s <= 16:
-               h ^= readUnaligned32(p)
-               h = rotl_15(h*m1) * m2
-               h ^= readUnaligned32(add(p, 4))
-               h = rotl_15(h*m1) * m2
-               h ^= readUnaligned32(add(p, s-8))
-               h = rotl_15(h*m1) * m2
-               h ^= readUnaligned32(add(p, s-4))
-               h = rotl_15(h*m1) * m2
-       default:
-               v1 := h
-               v2 := uint32(seed * hashkey[1])
-               v3 := uint32(seed * hashkey[2])
-               v4 := uint32(seed * hashkey[3])
-               for s >= 16 {
-                       v1 ^= readUnaligned32(p)
-                       v1 = rotl_15(v1*m1) * m2
-                       p = add(p, 4)
-                       v2 ^= readUnaligned32(p)
-                       v2 = rotl_15(v2*m2) * m3
-                       p = add(p, 4)
-                       v3 ^= readUnaligned32(p)
-                       v3 = rotl_15(v3*m3) * m4
-                       p = add(p, 4)
-                       v4 ^= readUnaligned32(p)
-                       v4 = rotl_15(v4*m4) * m1
-                       p = add(p, 4)
-                       s -= 16
-               }
-               h = v1 ^ v2 ^ v3 ^ v4
-               goto tail
+       a, b := mix32(uint32(seed), uint32(s^hashkey[0]))
+       if s == 0 {
+               return uintptr(a ^ b)
        }
-       h ^= h >> 17
-       h *= m3
-       h ^= h >> 13
-       h *= m4
-       h ^= h >> 16
-       return uintptr(h)
-}
-
-func memhash32(p unsafe.Pointer, seed uintptr) uintptr {
-       h := uint32(seed + 4*hashkey[0])
-       h ^= readUnaligned32(p)
-       h = rotl_15(h*m1) * m2
-       h ^= h >> 17
-       h *= m3
-       h ^= h >> 13
-       h *= m4
-       h ^= h >> 16
-       return uintptr(h)
-}
-
-func memhash64(p unsafe.Pointer, seed uintptr) uintptr {
-       h := uint32(seed + 8*hashkey[0])
-       h ^= readUnaligned32(p)
-       h = rotl_15(h*m1) * m2
-       h ^= readUnaligned32(add(p, 4))
-       h = rotl_15(h*m1) * m2
-       h ^= h >> 17
-       h *= m3
-       h ^= h >> 13
-       h *= m4
-       h ^= h >> 16
-       return uintptr(h)
+       for ; s > 8; s -= 8 {
+               a ^= readUnaligned32(p)
+               b ^= readUnaligned32(add(p, 4))
+               a, b = mix32(a, b)
+               p = add(p, 8)
+       }
+       if s >= 4 {
+               a ^= readUnaligned32(p)
+               b ^= readUnaligned32(add(p, s-4))
+       } else {
+               t := uint32(*(*byte)(p))
+               t |= uint32(*(*byte)(add(p, s>>1))) << 8
+               t |= uint32(*(*byte)(add(p, s-1))) << 16
+               b ^= t
+       }
+       a, b = mix32(a, b)
+       a, b = mix32(a, b)
+       return uintptr(a ^ b)
 }
 
-// Note: in order to get the compiler to issue rotl instructions, we
-// need to constant fold the shift amount by hand.
-// TODO: convince the compiler to issue rotl instructions after inlining.
-func rotl_15(x uint32) uint32 {
-       return (x << 15) | (x >> (32 - 15))
+func mix32(a, b uint32) (uint32, uint32) {
+       c := uint64(a^uint32(hashkey[1])) * uint64(b^uint32(hashkey[2]))
+       return uint32(c), uint32(c >> 32)
 }
index 704bbe6f62bc9a6a79df8be630f7c3e2ff10a73d..4b32d515c4b455fa815aacd412b1a98a75c6f56b 100644 (file)
 // license that can be found in the LICENSE file.
 
 // Hashing algorithm inspired by
-//   xxhash: https://code.google.com/p/xxhash/
-// cityhash: https://code.google.com/p/cityhash/
+// wyhash: https://github.com/wangyi-fudan/wyhash
 
+//go:build amd64 || arm64 || mips64 || mips64le || ppc64 || ppc64le || riscv64 || s390x || wasm || alpha || amd64p32 || arm64be || ia64 || mips64p32 || mips64p32le || sparc64
 // +build amd64 arm64 mips64 mips64le ppc64 ppc64le riscv64 s390x wasm alpha amd64p32 arm64be ia64 mips64p32 mips64p32le sparc64
 
 package runtime
 
-import "unsafe"
+import (
+       "runtime/internal/math"
+       "unsafe"
+)
 
 // For gccgo, use go:linkname to export compiler-called functions.
 //
 //go:linkname memhash
 
 const (
-       // Constants for multiplication: four random odd 64-bit numbers.
-       m1 = 16877499708836156737
-       m2 = 2820277070424839065
-       m3 = 9497967016996688599
-       m4 = 15839092249703872147
+       m1 = 0xa0761d6478bd642f
+       m2 = 0xe7037ed1a0b428db
+       m3 = 0x8ebc6af09c88c6e3
+       m4 = 0x589965cc75374cc3
+       m5 = 0x1d8e4e27c47d124f
 )
 
 func memhash(p unsafe.Pointer, seed, s uintptr) uintptr {
        if (GOARCH == "amd64" || GOARCH == "arm64") && useAeshash {
                return aeshash(p, seed, s)
        }
-       h := uint64(seed + s*hashkey[0])
-tail:
+       var a, b uintptr
+       seed ^= hashkey[0] ^ m1
        switch {
        case s == 0:
+               return seed
        case s < 4:
-               h ^= uint64(*(*byte)(p))
-               h ^= uint64(*(*byte)(add(p, s>>1))) << 8
-               h ^= uint64(*(*byte)(add(p, s-1))) << 16
-               h = rotl_31(h*m1) * m2
-       case s <= 8:
-               h ^= uint64(readUnaligned32(p))
-               h ^= uint64(readUnaligned32(add(p, s-4))) << 32
-               h = rotl_31(h*m1) * m2
+               a = uintptr(*(*byte)(p))
+               a |= uintptr(*(*byte)(add(p, s>>1))) << 8
+               a |= uintptr(*(*byte)(add(p, s-1))) << 16
+       case s == 4:
+               a = r4(p)
+               b = a
+       case s < 8:
+               a = r4(p)
+               b = r4(add(p, s-4))
+       case s == 8:
+               a = r8(p)
+               b = a
        case s <= 16:
-               h ^= readUnaligned64(p)
-               h = rotl_31(h*m1) * m2
-               h ^= readUnaligned64(add(p, s-8))
-               h = rotl_31(h*m1) * m2
-       case s <= 32:
-               h ^= readUnaligned64(p)
-               h = rotl_31(h*m1) * m2
-               h ^= readUnaligned64(add(p, 8))
-               h = rotl_31(h*m1) * m2
-               h ^= readUnaligned64(add(p, s-16))
-               h = rotl_31(h*m1) * m2
-               h ^= readUnaligned64(add(p, s-8))
-               h = rotl_31(h*m1) * m2
+               a = r8(p)
+               b = r8(add(p, s-8))
        default:
-               v1 := h
-               v2 := uint64(seed * hashkey[1])
-               v3 := uint64(seed * hashkey[2])
-               v4 := uint64(seed * hashkey[3])
-               for s >= 32 {
-                       v1 ^= readUnaligned64(p)
-                       v1 = rotl_31(v1*m1) * m2
-                       p = add(p, 8)
-                       v2 ^= readUnaligned64(p)
-                       v2 = rotl_31(v2*m2) * m3
-                       p = add(p, 8)
-                       v3 ^= readUnaligned64(p)
-                       v3 = rotl_31(v3*m3) * m4
-                       p = add(p, 8)
-                       v4 ^= readUnaligned64(p)
-                       v4 = rotl_31(v4*m4) * m1
-                       p = add(p, 8)
-                       s -= 32
+               l := s
+               if l > 48 {
+                       seed1 := seed
+                       seed2 := seed
+                       for ; l > 48; l -= 48 {
+                               seed = mix(r8(p)^m2, r8(add(p, 8))^seed)
+                               seed1 = mix(r8(add(p, 16))^m3, r8(add(p, 24))^seed1)
+                               seed2 = mix(r8(add(p, 32))^m4, r8(add(p, 40))^seed2)
+                               p = add(p, 48)
+                       }
+                       seed ^= seed1 ^ seed2
+               }
+               for ; l > 16; l -= 16 {
+                       seed = mix(r8(p)^m2, r8(add(p, 8))^seed)
+                       p = add(p, 16)
                }
-               h = v1 ^ v2 ^ v3 ^ v4
-               goto tail
+               a = r8(add(p, l-16))
+               b = r8(add(p, l-8))
        }
 
-       h ^= h >> 29
-       h *= m3
-       h ^= h >> 32
-       return uintptr(h)
+       return mix(m5^s, mix(a^m2, b^seed))
 }
 
 func memhash32(p unsafe.Pointer, seed uintptr) uintptr {
-       h := uint64(seed + 4*hashkey[0])
-       v := uint64(readUnaligned32(p))
-       h ^= v
-       h ^= v << 32
-       h = rotl_31(h*m1) * m2
-       h ^= h >> 29
-       h *= m3
-       h ^= h >> 32
-       return uintptr(h)
+       a := r4(p)
+       return mix(m5^4, mix(a^m2, a^seed^hashkey[0]^m1))
 }
 
 func memhash64(p unsafe.Pointer, seed uintptr) uintptr {
-       h := uint64(seed + 8*hashkey[0])
-       h ^= uint64(readUnaligned32(p)) | uint64(readUnaligned32(add(p, 4)))<<32
-       h = rotl_31(h*m1) * m2
-       h ^= h >> 29
-       h *= m3
-       h ^= h >> 32
-       return uintptr(h)
+       a := r8(p)
+       return mix(m5^8, mix(a^m2, a^seed^hashkey[0]^m1))
+}
+
+func mix(a, b uintptr) uintptr {
+       hi, lo := math.Mul64(uint64(a), uint64(b))
+       return uintptr(hi ^ lo)
+}
+
+func r4(p unsafe.Pointer) uintptr {
+       return uintptr(readUnaligned32(p))
 }
 
-// Note: in order to get the compiler to issue rotl instructions, we
-// need to constant fold the shift amount by hand.
-// TODO: convince the compiler to issue rotl instructions after inlining.
-func rotl_31(x uint64) uint64 {
-       return (x << 31) | (x >> (64 - 31))
+func r8(p unsafe.Pointer) uintptr {
+       return uintptr(readUnaligned64(p))
 }
index 60a86015f64ced83006ad077946e34eae0dd47dd..753b129d82c55533abd6ee486f3fa9d4403ce7b6 100644 (file)
@@ -8,7 +8,6 @@ import (
        "fmt"
        "math"
        "math/rand"
-       "reflect"
        . "runtime"
        "strings"
        "testing"
@@ -49,54 +48,6 @@ func TestMemHash64Equality(t *testing.T) {
        }
 }
 
-func TestCompilerVsRuntimeHash(t *testing.T) {
-       // Test to make sure the compiler's hash function and the runtime's hash function agree.
-       // See issue 37716.
-       for _, m := range []interface{}{
-               map[bool]int{},
-               map[int8]int{},
-               map[uint8]int{},
-               map[int16]int{},
-               map[uint16]int{},
-               map[int32]int{},
-               map[uint32]int{},
-               map[int64]int{},
-               map[uint64]int{},
-               map[int]int{},
-               map[uint]int{},
-               map[uintptr]int{},
-               map[*byte]int{},
-               map[chan int]int{},
-               map[unsafe.Pointer]int{},
-               map[float32]int{},
-               map[float64]int{},
-               map[complex64]int{},
-               map[complex128]int{},
-               map[string]int{},
-               //map[interface{}]int{},
-               //map[interface{F()}]int{},
-               map[[8]uint64]int{},
-               map[[8]string]int{},
-               map[struct{ a, b, c, d int32 }]int{}, // Note: tests AMEM128
-               map[struct{ a, b, _, d int32 }]int{},
-               map[struct {
-                       a, b int32
-                       c    float32
-                       d, e [8]byte
-               }]int{},
-               map[struct {
-                       a int16
-                       b int64
-               }]int{},
-       } {
-               k := reflect.New(reflect.TypeOf(m).Key()).Elem().Interface() // the zero key
-               x, y := MapHashCheck(m, k)
-               if x != y {
-                       t.Errorf("hashes did not match (%x vs %x) for map %T", x, y, m)
-               }
-       }
-}
-
 // Smhasher is a torture test for hash functions.
 // https://code.google.com/p/smhasher/
 // This code is a port of some of the Smhasher tests to Go.
index f3f7382b2428fcc2d4e8a9309199d1438b18fe7c..171acb8697c9201d7afbad444d3e47775122ea2f 100644 (file)
@@ -294,9 +294,10 @@ func dumpgoroutine(gp *g) {
 }
 
 func dumpgs() {
+       assertWorldStopped()
+
        // goroutines & stacks
-       for i := 0; uintptr(i) < allglen; i++ {
-               gp := allgs[i]
+       forEachG(func(gp *g) {
                status := readgstatus(gp) // The world is stopped so gp will not be in a scan state.
                switch status {
                default:
@@ -309,7 +310,7 @@ func dumpgs() {
                        _Gwaiting:
                        dumpgoroutine(gp)
                }
-       }
+       })
 }
 
 func finq_callback(fn *funcval, obj unsafe.Pointer, ft *functype, ot *ptrtype) {
@@ -409,7 +410,7 @@ func dumpparams() {
        dumpint(uint64(arenaStart))
        dumpint(uint64(arenaEnd))
        dumpstr(sys.GOARCH)
-       dumpstr(sys.Goexperiment)
+       dumpstr(buildVersion)
        dumpint(uint64(ncpu))
 }
 
index da4910d341cbcf861059f292eb4576a8e762e75a..0cccbcca16252babeb09438e4041cb30fd8b8d8f 100644 (file)
@@ -81,6 +81,10 @@ type timeHistogram struct {
 }
 
 // record adds the given duration to the distribution.
+//
+// Disallow preemptions and stack growths because this function
+// may run in sensitive locations.
+//go:nosplit
 func (h *timeHistogram) record(duration int64) {
        if duration < 0 {
                atomic.Xadd64(&h.underflow, 1)
index 5385f5dd8689449e4c6ec0e0cb0feae86aa8f6b2..b6bd12d3e8b66d5908b5c2d0da0bfe0d051ff263 100644 (file)
@@ -17,3 +17,24 @@ func MulUintptr(a, b uintptr) (uintptr, bool) {
        overflow := b > MaxUintptr/a
        return a * b, overflow
 }
+
+// Mul64 returns the 128-bit product of x and y: (hi, lo) = x * y
+// with the product bits' upper half returned in hi and the lower
+// half returned in lo.
+// This is a copy from math/bits.Mul64
+// On supported platforms this is an intrinsic lowered by the compiler.
+func Mul64(x, y uint64) (hi, lo uint64) {
+       const mask32 = 1<<32 - 1
+       x0 := x & mask32
+       x1 := x >> 32
+       y0 := y & mask32
+       y1 := y >> 32
+       w0 := x0 * y0
+       t := x1*y0 + w0>>32
+       w1 := t & mask32
+       w2 := t >> 32
+       w1 += x0 * y1
+       hi = x1*y1 + w2 + w1>>32
+       lo = x * y
+       return
+}
diff --git a/libgo/go/runtime/internal/sys/arch.go b/libgo/go/runtime/internal/sys/arch.go
new file mode 100644 (file)
index 0000000..7e09c10
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sys
+
+type ArchFamilyType int
+
+// PtrSize is the size of a pointer in bytes - unsafe.Sizeof(uintptr(0)) but as an ideal constant.
+// It is also the size of the machine's native word size (that is, 4 on 32-bit systems, 8 on 64-bit).
+const PtrSize = 4 << (^uintptr(0) >> 63)
+
+// AIX requires a larger stack for syscalls.
+const StackGuardMultiplier = StackGuardMultiplierDefault*(1-GoosAix) + 2*GoosAix
+
+// ArchFamily is the architecture family (AMD64, ARM, ...)
+const ArchFamily ArchFamilyType = _ArchFamily
+
+// BigEndian reports whether the architecture is big-endian.
+const BigEndian = _BigEndian
+
+// DefaultPhysPageSize is the default physical page size.
+const DefaultPhysPageSize = _DefaultPhysPageSize
+
+// PCQuantum is the minimal unit for a program counter (1 on x86, 4 on most other systems).
+// The various PC tables record PC deltas pre-divided by PCQuantum.
+const PCQuantum = _PCQuantum
+
+// Int64Align is the required alignment for a 64-bit integer (4 on 32-bit systems, 8 on 64-bit).
+const Int64Align = _Int64Align
+
+// MinFrameSize is the size of the system-reserved words at the bottom
+// of a frame (just above the architectural stack pointer).
+// It is zero on x86 and PtrSize on most non-x86 (LR-based) systems.
+// On PowerPC it is larger, to cover three more reserved words:
+// the compiler word, the link editor word, and the TOC save word.
+const MinFrameSize = _MinFrameSize
+
+// StackAlign is the required alignment of the SP register.
+// The stack must be at least word aligned, but some architectures require more.
+const StackAlign = _StackAlign
diff --git a/libgo/go/runtime/internal/sys/stubs.go b/libgo/go/runtime/internal/sys/stubs.go
deleted file mode 100644 (file)
index 5328023..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package sys
-
-// Declarations for runtime services implemented in C or assembly.
-
-const PtrSize = 4 << (^uintptr(0) >> 63)           // unsafe.Sizeof(uintptr(0)) but an ideal const
-const RegSize = 4 << (^Uintreg(0) >> 63)           // unsafe.Sizeof(uintreg(0)) but an ideal const
-const SpAlign = 1*(1-GoarchArm64) + 16*GoarchArm64 // SP alignment: 1 normally, 16 for ARM64
-
-var DefaultGoroot string // set at link time
index b3194dc76685a82970b8b91e9d1cae47124526df..c0eb665dd208dca9befc0fb96122ba44132bae1c 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build 386 amd64p32 arm armbe m68k mips mipsle mips64p32 mips64p32le nios2 ppc riscv s390 sh shbe sparc
+//go:build 386 || arm || mips || mipsle || amd64p32 || armbe || m68k || mips64p32 || mips64p32le || nios2 || ppc || riscv || s390 || sh || shbe || sparc
+// +build 386 arm mips mipsle amd64p32 armbe m68k mips64p32 mips64p32le nios2 ppc riscv s390 sh shbe sparc
 
 package runtime
 
index af9e7d164b93eeec575edd6de54a3ea56388a931..44e6812096def89da737c9481419ab14e516e87f 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build amd64 || arm64 || mips64 || mips64le || ppc64 || ppc64le || riscv64 || s390x || wasm || arm64be || alpha || sparc64 || ia64
 // +build amd64 arm64 mips64 mips64le ppc64 ppc64le riscv64 s390x wasm arm64be alpha sparc64 ia64
 
 package runtime
index 0161955f09faf438f84a8535a4bf09e3e163f261..578bce04149baab781e738fa2779a14ec5d6ec6a 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build libfuzzer
 // +build libfuzzer
 
 package runtime
index 21d7e0dd9432268e6022f027932f8dfc2fb5a881..74f6428e1696435505955614f45a50d34966a4e8 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build dragonfly || freebsd || linux
 // +build dragonfly freebsd linux
 
 package runtime
@@ -249,7 +250,7 @@ func notetsleepg(n *note, ns int64) bool {
        return ok
 }
 
-func beforeIdle(int64) (*g, bool) {
+func beforeIdle(int64, int64) (*g, bool) {
        return nil, false
 }
 
index 14bdc76842cc4749a68d6e7b40ae6d54bf597807..0ca3512baf3c8313542cfe214057ef11772e917c 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build js && wasm
 // +build js,wasm
 
 package runtime
@@ -175,7 +176,12 @@ var idleID int32
 // If an event handler returned, we resume it and it will pause the execution.
 // beforeIdle either returns the specific goroutine to schedule next or
 // indicates with otherReady that some goroutine became ready.
-func beforeIdle(delay int64) (gp *g, otherReady bool) {
+func beforeIdle(now, pollUntil int64) (gp *g, otherReady bool) {
+       delay := int64(-1)
+       if pollUntil != 0 {
+               delay = pollUntil - now
+       }
+
        if delay > 0 {
                clearIdleID()
                if delay < 1e6 {
index fe1738437970db41a9f43723e6d4d71358f623d9..bcd8a86a3bfa28053cd62a9f18808870d11dd448 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || hurd || netbsd || openbsd || plan9 || solaris || windows
 // +build aix darwin hurd netbsd openbsd plan9 solaris windows
 
 package runtime
@@ -308,7 +309,7 @@ func notetsleepg(n *note, ns int64) bool {
        return ok
 }
 
-func beforeIdle(int64) (*g, bool) {
+func beforeIdle(int64, int64) (*g, bool) {
        return nil, false
 }
 
index b3c01ba10456fdc42fc8ae8c7552ef725bdfbb5e..dde9f7c21a7f3aa0f6d1ab5a61128e890e56238e 100644 (file)
@@ -44,7 +44,6 @@ const (
        lockRankPollDesc
        lockRankSched
        lockRankDeadlock
-       lockRankPanic
        lockRankAllg
        lockRankAllp
 
@@ -92,6 +91,7 @@ const (
        // rank, we don't allow any further locks to be acquired other than more
        // hchan locks.
        lockRankHchanLeaf
+       lockRankPanic
 
        // Leaf locks with no dependencies, so these constants are not actually used anywhere.
        // There are other architecture-dependent leaf locks as well.
@@ -123,7 +123,6 @@ var lockNames = []string{
        lockRankPollDesc: "pollDesc",
        lockRankSched:    "sched",
        lockRankDeadlock: "deadlock",
-       lockRankPanic:    "panic",
        lockRankAllg:     "allg",
        lockRankAllp:     "allp",
 
@@ -162,6 +161,7 @@ var lockNames = []string{
 
        lockRankGFree:     "gFree",
        lockRankHchanLeaf: "hchanLeaf",
+       lockRankPanic:     "panic",
 
        lockRankNewmHandoff:   "newmHandoff.lock",
        lockRankDebugPtrmask:  "debugPtrmask.lock",
@@ -202,10 +202,9 @@ var lockPartialOrder [][]lockRank = [][]lockRank{
        lockRankPollDesc:      {},
        lockRankSched:         {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc},
        lockRankDeadlock:      {lockRankDeadlock},
-       lockRankPanic:         {lockRankDeadlock},
-       lockRankAllg:          {lockRankSysmon, lockRankSched, lockRankPanic},
+       lockRankAllg:          {lockRankSysmon, lockRankSched},
        lockRankAllp:          {lockRankSysmon, lockRankSched},
-       lockRankTimers:        {lockRankSysmon, lockRankScavenge, lockRankSched, lockRankAllp, lockRankPollDesc, lockRankTimers},
+       lockRankTimers:        {lockRankSysmon, lockRankScavenge, lockRankPollDesc, lockRankSched, lockRankAllp, lockRankTimers},
        lockRankItab:          {},
        lockRankReflectOffs:   {lockRankItab},
        lockRankHchan:         {lockRankScavenge, lockRankSweep, lockRankHchan},
@@ -214,29 +213,30 @@ var lockPartialOrder [][]lockRank = [][]lockRank{
        lockRankTraceBuf:      {lockRankSysmon, lockRankScavenge},
        lockRankTraceStrings:  {lockRankTraceBuf},
        lockRankMspanSpecial:  {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings},
-       lockRankProf:          {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankHchan},
-       lockRankGcBitsArenas:  {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankHchan},
+       lockRankProf:          {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings},
+       lockRankGcBitsArenas:  {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings},
        lockRankRoot:          {},
-       lockRankTrace:         {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankSched, lockRankHchan, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot, lockRankSweep},
-       lockRankTraceStackTab: {lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankAllg, lockRankTimers, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot, lockRankTrace},
+       lockRankTrace:         {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankHchan, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot},
+       lockRankTraceStackTab: {lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankAllg, lockRankTimers, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot, lockRankTrace},
        lockRankNetpollInit:   {lockRankTimers},
 
        lockRankRwmutexW: {},
        lockRankRwmutexR: {lockRankSysmon, lockRankRwmutexW},
 
-       lockRankSpanSetSpine: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankHchan},
-       lockRankGscan:        {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot, lockRankNotifyList, lockRankProf, lockRankGcBitsArenas, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankSpanSetSpine},
-       lockRankStackpool:    {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankPollDesc, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankRwmutexR, lockRankSpanSetSpine, lockRankGscan},
+       lockRankSpanSetSpine: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings},
+       lockRankGscan:        {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankSpanSetSpine},
+       lockRankStackpool:    {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankRwmutexR, lockRankSpanSetSpine, lockRankGscan},
        lockRankStackLarge:   {lockRankSysmon, lockRankAssistQueue, lockRankSched, lockRankItab, lockRankHchan, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan},
        lockRankDefer:        {},
-       lockRankSudog:        {lockRankNotifyList, lockRankHchan},
-       lockRankWbufSpans:    {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankAllg, lockRankPollDesc, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankRoot, lockRankGscan, lockRankDefer, lockRankSudog},
-       lockRankMheap:        {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankFin, lockRankPollDesc, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankHchan, lockRankMspanSpecial, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankDefer, lockRankSudog, lockRankWbufSpans, lockRankSpanSetSpine},
-       lockRankMheapSpecial: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankHchan},
+       lockRankSudog:        {lockRankHchan, lockRankNotifyList},
+       lockRankWbufSpans:    {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankRoot, lockRankGscan, lockRankDefer, lockRankSudog},
+       lockRankMheap:        {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankDefer, lockRankSudog, lockRankWbufSpans},
+       lockRankMheapSpecial: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings},
        lockRankGlobalAlloc:  {lockRankProf, lockRankSpanSetSpine, lockRankMheap, lockRankMheapSpecial},
 
        lockRankGFree:     {lockRankSched},
        lockRankHchanLeaf: {lockRankGscan, lockRankHchanLeaf},
+       lockRankPanic:     {lockRankDeadlock}, // plus any other lock held on throw.
 
        lockRankNewmHandoff:   {},
        lockRankDebugPtrmask:  {},
index 7dcd8f5fe96296b2b73484cd7accf61ff85d5aab..f3d2c009145766c448a9a71a5ca3d4c0cd1f6c96 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !goexperiment.staticlockranking
 // +build !goexperiment.staticlockranking
 
 package runtime
index 88ac95a0047405b4a744a79286c220249ebe656e..fc8d2dc8d1179fd1813561ff0a6283550b7a0bfe 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build goexperiment.staticlockranking
 // +build goexperiment.staticlockranking
 
 package runtime
@@ -24,19 +25,6 @@ type lockRankStruct struct {
        pad int
 }
 
-// init checks that the partial order in lockPartialOrder fits within the total
-// order determined by the order of the lockRank constants.
-func init() {
-       for rank, list := range lockPartialOrder {
-               for _, entry := range list {
-                       if entry > lockRank(rank) {
-                               println("lockPartial order row", lockRank(rank).String(), "entry", entry.String())
-                               throw("lockPartialOrder table is inconsistent with total lock ranking order")
-                       }
-               }
-       }
-}
-
 func lockInit(l *mutex, rank lockRank) {
        l.rank = rank
 }
@@ -64,12 +52,11 @@ func lockWithRank(l *mutex, rank lockRank) {
                // rank recording for it, since print/println are used when
                // printing out a lock ordering problem below.
                //
-               // paniclk has an ordering problem, since it can be acquired
-               // during a panic with any other locks held (especially if the
-               // panic is because of a directed segv), and yet also allg is
-               // acquired after paniclk in tracebackothers()). This is a genuine
-               // problem, so for now we don't do lock rank recording for paniclk
-               // either.
+               // paniclk is only used for fatal throw/panic. Don't do lock
+               // ranking recording for it, since we throw after reporting a
+               // lock ordering problem. Additionally, paniclk may be taken
+               // after effectively any lock (anywhere we might panic), which
+               // the partial order doesn't cover.
                lock2(l)
                return
        }
@@ -219,7 +206,7 @@ func releaseLockRank(rank lockRank) {
 func lockWithRankMayAcquire(l *mutex, rank lockRank) {
        gp := getg()
        if gp.m.locksHeldLen == 0 {
-               // No possibilty of lock ordering problem if no other locks held
+               // No possibility of lock ordering problem if no other locks held
                return
        }
 
diff --git a/libgo/go/runtime/lockrank_test.go b/libgo/go/runtime/lockrank_test.go
new file mode 100644 (file)
index 0000000..4b2fc0e
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime_test
+
+import (
+       . "runtime"
+       "testing"
+)
+
+// Check that the partial order in lockPartialOrder fits within the total order
+// determined by the order of the lockRank constants.
+func TestLockRankPartialOrder(t *testing.T) {
+       for r, list := range LockPartialOrder {
+               rank := LockRank(r)
+               for _, e := range list {
+                       entry := LockRank(e)
+                       if entry > rank {
+                               t.Errorf("lockPartialOrder row %v entry %v is inconsistent with total lock ranking order", rank, entry)
+                       }
+               }
+       }
+}
+
+// Verify that partial order lists are kept sorted. This is a purely cosemetic
+// check to make manual reviews simpler. It does not affect correctness, unlike
+// the above test.
+func TestLockRankPartialOrderSortedEntries(t *testing.T) {
+       for r, list := range LockPartialOrder {
+               rank := LockRank(r)
+               var prev LockRank
+               for _, e := range list {
+                       entry := LockRank(e)
+                       if entry <= prev {
+                               t.Errorf("Partial order for rank %v out of order: %v <= %v in %v", rank, entry, prev, list)
+                       }
+                       prev = entry
+               }
+       }
+}
index d3d88a243f4628021d0983f4b92aa00ca942c2b4..7005e53a2f32c51a46ba92688b72d5818f99df97 100644 (file)
@@ -237,6 +237,7 @@ const (
        // --------------  ---------  ----------  ----------  -----------
        //       */64-bit         48        64MB           1    4M (32MB)
        // windows/64-bit         48         4MB          64    1M  (8MB)
+       //      ios/arm64         33         4MB           1  2048  (8KB)
        //       */32-bit         32         4MB           1  1024  (4KB)
        //     */mips(le)         31         4MB           1   512  (2KB)
 
@@ -257,7 +258,7 @@ const (
        // logHeapArenaBytes is log_2 of heapArenaBytes. For clarity,
        // prefer using heapArenaBytes where possible (we need the
        // constant to compute some other constants).
-       logHeapArenaBytes = (6+20)*(_64bit*(1-sys.GoosWindows)*(1-sys.GoarchWasm)) + (2+20)*(_64bit*sys.GoosWindows) + (2+20)*(1-_64bit) + (2+20)*sys.GoarchWasm
+       logHeapArenaBytes = (6+20)*(_64bit*(1-sys.GoosWindows)*(1-sys.GoarchWasm)*(1-sys.GoosIos*sys.GoarchArm64)) + (2+20)*(_64bit*sys.GoosWindows) + (2+20)*(1-_64bit) + (2+20)*sys.GoarchWasm + (2+20)*sys.GoosIos*sys.GoarchArm64
 
        // heapArenaBitmapBytes is the size of each heap arena's bitmap.
        heapArenaBitmapBytes = heapArenaBytes / (sys.PtrSize * 8 / 2)
@@ -305,7 +306,7 @@ const (
        // high addresses if viewed as unsigned).
        //
        // On aix/ppc64, this offset allows to keep the heapAddrBits to
-       // 48. Otherwize, it would be 60 in order to handle mmap addresses
+       // 48. Otherwise, it would be 60 in order to handle mmap addresses
        // (in range 0x0a00000000000000 - 0x0afffffffffffff). But in this
        // case, the memory reserved in (s *pageAlloc).init for chunks
        // is causing important slowdowns.
@@ -579,7 +580,7 @@ func mallocinit() {
                const arenaMetaSize = (1 << arenaBits) * unsafe.Sizeof(heapArena{})
                meta := uintptr(sysReserve(nil, arenaMetaSize))
                if meta != 0 {
-                       mheap_.heapArenaAlloc.init(meta, arenaMetaSize)
+                       mheap_.heapArenaAlloc.init(meta, arenaMetaSize, true)
                }
 
                // We want to start the arena low, but if we're linked
@@ -616,7 +617,7 @@ func mallocinit() {
                for _, arenaSize := range &arenaSizes {
                        a, size := sysReserveAligned(unsafe.Pointer(p), arenaSize, heapArenaBytes)
                        if a != nil {
-                               mheap_.arena.init(uintptr(a), size)
+                               mheap_.arena.init(uintptr(a), size, false)
                                p = mheap_.arena.end // For hint below
                                break
                        }
@@ -633,8 +634,8 @@ func mallocinit() {
 // heapArenaBytes. sysAlloc returns nil on failure.
 // There is no corresponding free function.
 //
-// sysAlloc returns a memory region in the Prepared state. This region must
-// be transitioned to Ready before use.
+// sysAlloc returns a memory region in the Reserved state. This region must
+// be transitioned to Prepared and then Ready before use.
 //
 // h must be locked.
 func (h *mheap) sysAlloc(n uintptr) (v unsafe.Pointer, size uintptr) {
@@ -736,9 +737,6 @@ func (h *mheap) sysAlloc(n uintptr) (v unsafe.Pointer, size uintptr) {
                throw("misrounded allocation in sysAlloc")
        }
 
-       // Transition from Reserved to Prepared.
-       sysMap(v, size, &memstats.heap_sys)
-
 mapped:
        // Create arena metadata.
        for ri := arenaIndex(uintptr(v)); ri <= arenaIndex(uintptr(v)+size-1); ri++ {
@@ -947,7 +945,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
                }
 
                if inittrace.active && inittrace.id == getg().goid {
-                       // Init functions are executed sequentially in a single Go routine.
+                       // Init functions are executed sequentially in a single goroutine.
                        inittrace.allocs += 1
                }
        }
@@ -1003,6 +1001,9 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
        var span *mspan
        var x unsafe.Pointer
        noscan := typ == nil || typ.ptrdata == 0
+       // In some cases block zeroing can profitably (for latency reduction purposes)
+       // be delayed till preemption is possible; isZeroed tracks that state.
+       isZeroed := true
        if size <= maxSmallSize {
                if noscan && size < maxTinySize {
                        // Tiny allocator.
@@ -1074,7 +1075,8 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
                        (*[2]uint64)(x)[1] = 0
                        // See if we need to replace the existing tiny block with the new one
                        // based on amount of remaining free space.
-                       if size < c.tinyoffset || c.tiny == 0 {
+                       if !raceenabled && (size < c.tinyoffset || c.tiny == 0) {
+                               // Note: disabled when race detector is on, see comment near end of this function.
                                c.tiny = uintptr(x)
                                c.tinyoffset = size
                        }
@@ -1100,7 +1102,9 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
                }
        } else {
                shouldhelpgc = true
-               span = c.allocLarge(size, needzero, noscan)
+               // For large allocations, keep track of zeroed state so that
+               // bulk zeroing can be happen later in a preemptible context.
+               span, isZeroed = c.allocLarge(size, needzero && !noscan, noscan)
                span.freeindex = 1
                span.allocCount = 1
                x = unsafe.Pointer(span.base())
@@ -1147,30 +1151,34 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
                msanmalloc(x, size)
        }
 
+       if rate := MemProfileRate; rate > 0 {
+               // Note cache c only valid while m acquired; see #47302
+               if rate != 1 && size < c.nextSample {
+                       c.nextSample -= size
+               } else {
+                       profilealloc(mp, x, size)
+               }
+       }
        mp.mallocing = 0
        releasem(mp)
 
+       // Pointerfree data can be zeroed late in a context where preemption can occur.
+       // x will keep the memory alive.
+       if !isZeroed && needzero {
+               memclrNoHeapPointersChunked(size, x) // This is a possible preemption point: see #47302
+       }
+
        if debug.malloc {
                if debug.allocfreetrace != 0 {
                        tracealloc(x, size, typ)
                }
 
                if inittrace.active && inittrace.id == getg().goid {
-                       // Init functions are executed sequentially in a single Go routine.
+                       // Init functions are executed sequentially in a single goroutine.
                        inittrace.bytes += uint64(size)
                }
        }
 
-       if rate := MemProfileRate; rate > 0 {
-               if rate != 1 && size < c.nextSample {
-                       c.nextSample -= size
-               } else {
-                       mp := acquirem()
-                       profilealloc(mp, x, size)
-                       releasem(mp)
-               }
-       }
-
        if assistG != nil {
                // Account for internal fragmentation in the assist
                // debt now that we know it.
@@ -1183,6 +1191,22 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
                }
        }
 
+       if raceenabled && noscan && dataSize < maxTinySize {
+               // Pad tinysize allocations so they are aligned with the end
+               // of the tinyalloc region. This ensures that any arithmetic
+               // that goes off the top end of the object will be detectable
+               // by checkptr (issue 38872).
+               // Note that we disable tinyalloc when raceenabled for this to work.
+               // TODO: This padding is only performed when the race detector
+               // is enabled. It would be nice to enable it if any package
+               // was compiled with checkptr, but there's no easy way to
+               // detect that (especially at compile time).
+               // TODO: enable this padding for all allocations, not just
+               // tinyalloc ones. It's tricky because of pointer maps.
+               // Maybe just all noscan objects?
+               x = add(x, size-dataSize)
+       }
+
        // Check preemption, since unlike gc we don't check on every call.
        if getg().preempt {
                checkPreempt()
@@ -1195,6 +1219,33 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
        return x
 }
 
+// memclrNoHeapPointersChunked repeatedly calls memclrNoHeapPointers
+// on chunks of the buffer to be zeroed, with opportunities for preemption
+// along the way.  memclrNoHeapPointers contains no safepoints and also
+// cannot be preemptively scheduled, so this provides a still-efficient
+// block copy that can also be preempted on a reasonable granularity.
+//
+// Use this with care; if the data being cleared is tagged to contain
+// pointers, this allows the GC to run before it is all cleared.
+func memclrNoHeapPointersChunked(size uintptr, x unsafe.Pointer) {
+       v := uintptr(x)
+       // got this from benchmarking. 128k is too small, 512k is too large.
+       const chunkBytes = 256 * 1024
+       vsize := v + size
+       for voff := v; voff < vsize; voff = voff + chunkBytes {
+               if getg().preempt {
+                       // may hold locks, e.g., profiling
+                       goschedguarded()
+               }
+               // clear min(avail, lump) bytes
+               n := vsize - voff
+               if n > chunkBytes {
+                       n = chunkBytes
+               }
+               memclrNoHeapPointers(unsafe.Pointer(voff), n)
+       }
+}
+
 // implementation of new builtin
 // compiler (both frontend and SSA backend) knows the signature
 // of this function
@@ -1425,15 +1476,19 @@ func inPersistentAlloc(p uintptr) bool {
 }
 
 // linearAlloc is a simple linear allocator that pre-reserves a region
-// of memory and then maps that region into the Ready state as needed. The
-// caller is responsible for locking.
+// of memory and then optionally maps that region into the Ready state
+// as needed.
+//
+// The caller is responsible for locking.
 type linearAlloc struct {
        next   uintptr // next free byte
        mapped uintptr // one byte past end of mapped space
        end    uintptr // end of reserved space
+
+       mapMemory bool // transition memory from Reserved to Ready if true
 }
 
-func (l *linearAlloc) init(base, size uintptr) {
+func (l *linearAlloc) init(base, size uintptr, mapMemory bool) {
        if base+size < base {
                // Chop off the last byte. The runtime isn't prepared
                // to deal with situations where the bounds could overflow.
@@ -1443,6 +1498,7 @@ func (l *linearAlloc) init(base, size uintptr) {
        }
        l.next, l.mapped = base, base
        l.end = base + size
+       l.mapMemory = mapMemory
 }
 
 func (l *linearAlloc) alloc(size, align uintptr, sysStat *sysMemStat) unsafe.Pointer {
@@ -1452,9 +1508,11 @@ func (l *linearAlloc) alloc(size, align uintptr, sysStat *sysMemStat) unsafe.Poi
        }
        l.next = p + size
        if pEnd := alignUp(l.next-1, physPageSize); pEnd > l.mapped {
-               // Transition from Reserved to Prepared to Ready.
-               sysMap(unsafe.Pointer(l.mapped), pEnd-l.mapped, sysStat)
-               sysUsed(unsafe.Pointer(l.mapped), pEnd-l.mapped)
+               if l.mapMemory {
+                       // Transition from Reserved to Prepared to Ready.
+                       sysMap(unsafe.Pointer(l.mapped), pEnd-l.mapped, sysStat)
+                       sysUsed(unsafe.Pointer(l.mapped), pEnd-l.mapped)
+               }
                l.mapped = pEnd
        }
        return unsafe.Pointer(p)
index 24b8740d05d7d45ef17cb09728a04f7f920ee312..7e83255ae45b98c43389f277e2a864ad3ceadabc 100644 (file)
@@ -156,6 +156,9 @@ func TestStringConcatenationAllocs(t *testing.T) {
 }
 
 func TestTinyAlloc(t *testing.T) {
+       if runtime.Raceenabled {
+               t.Skip("tinyalloc suppressed when running in race mode")
+       }
        const N = 16
        var v [N]unsafe.Pointer
        for i := range v {
@@ -184,6 +187,9 @@ type obj12 struct {
 }
 
 func TestTinyAllocIssue37262(t *testing.T) {
+       if runtime.Raceenabled {
+               t.Skip("tinyalloc suppressed when running in race mode")
+       }
        // Try to cause an alignment access fault
        // by atomically accessing the first 64-bit
        // value of a tiny-allocated object.
index 5b9d7102f43395517c1bca39709df36b9a1d7caa..c96d2c71626f7f2ebe188c86867a00ebebcc9202 100644 (file)
@@ -128,7 +128,7 @@ func isEmpty(x uint8) bool {
 
 // A header for a Go map.
 type hmap struct {
-       // Note: the format of the hmap is also encoded in cmd/compile/internal/gc/reflect.go.
+       // Note: the format of the hmap is also encoded in cmd/compile/internal/reflectdata/reflect.go.
        // Make sure this stays in sync with the compiler's definition.
        count     int // # live cells == size of map.  Must be first (used by len() builtin)
        flags     uint8
@@ -174,11 +174,11 @@ type bmap struct {
 }
 
 // A hash iteration structure.
-// If you modify hiter, also change cmd/compile/internal/gc/reflect.go to indicate
+// If you modify hiter, also change cmd/compile/internal/reflectdata/reflect.go to indicate
 // the layout of this structure.
 type hiter struct {
-       key         unsafe.Pointer // Must be in first position.  Write nil to indicate iteration end (see cmd/compile/internal/gc/range.go).
-       elem        unsafe.Pointer // Must be in second position (see cmd/compile/internal/gc/range.go).
+       key         unsafe.Pointer // Must be in first position.  Write nil to indicate iteration end (see cmd/compile/internal/walk/range.go).
+       elem        unsafe.Pointer // Must be in second position (see cmd/compile/internal/walk/range.go).
        t           *maptype
        h           *hmap
        buckets     unsafe.Pointer // bucket ptr at hash_iter initialization time
@@ -495,13 +495,13 @@ func mapaccess2(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, bool)
        }
        hash := t.hasher(key, uintptr(h.hash0))
        m := bucketMask(h.B)
-       b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + (hash&m)*uintptr(t.bucketsize)))
+       b := (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
        if c := h.oldbuckets; c != nil {
                if !h.sameSizeGrow() {
                        // There used to be half as many buckets; mask down one more power of two.
                        m >>= 1
                }
-               oldb := (*bmap)(unsafe.Pointer(uintptr(c) + (hash&m)*uintptr(t.bucketsize)))
+               oldb := (*bmap)(add(c, (hash&m)*uintptr(t.bucketsize)))
                if !evacuated(oldb) {
                        b = oldb
                }
@@ -544,13 +544,13 @@ func mapaccessK(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, unsafe
        }
        hash := t.hasher(key, uintptr(h.hash0))
        m := bucketMask(h.B)
-       b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + (hash&m)*uintptr(t.bucketsize)))
+       b := (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
        if c := h.oldbuckets; c != nil {
                if !h.sameSizeGrow() {
                        // There used to be half as many buckets; mask down one more power of two.
                        m >>= 1
                }
-               oldb := (*bmap)(unsafe.Pointer(uintptr(c) + (hash&m)*uintptr(t.bucketsize)))
+               oldb := (*bmap)(add(c, (hash&m)*uintptr(t.bucketsize)))
                if !evacuated(oldb) {
                        b = oldb
                }
@@ -863,7 +863,7 @@ func mapiterinit(t *maptype, h *hmap, it *hiter) {
        }
 
        if unsafe.Sizeof(hiter{})/sys.PtrSize != 12 {
-               throw("hash_iter size incorrect") // see cmd/compile/internal/gc/reflect.go
+               throw("hash_iter size incorrect") // see cmd/compile/internal/reflectdata/reflect.go
        }
        it.t = t
        it.h = h
index 22059476da52bf45259522133e4575e43e17b1cd..647978b68cfd6a7f3b13600edbd1e72d2f6b53a0 100644 (file)
@@ -262,6 +262,9 @@ bucketloop:
                        // already have a mapping for key. Update it.
                        inserti = i
                        insertb = b
+                       // Overwrite existing key, so it can be garbage collected.
+                       // The size is already guaranteed to be set correctly.
+                       k.str = key.str
                        goto done
                }
                ovf := b.overflow(t)
index 0eb19d6bc38f090a633959cc08231987ef6700b5..72cd9f35a99aaa4d604f97450444cbeeacac4c8b 100644 (file)
@@ -226,16 +226,25 @@ func (s *mspan) isFree(index uintptr) bool {
        return *bytep&mask == 0
 }
 
-func (s *mspan) objIndex(p uintptr) uintptr {
-       byteOffset := p - s.base()
-       if byteOffset == 0 {
-               return 0
-       }
-       if s.baseMask != 0 {
-               // s.baseMask is non-0, elemsize is a power of two, so shift by s.divShift
-               return byteOffset >> s.divShift
+// divideByElemSize returns n/s.elemsize.
+// n must be within [0, s.npages*_PageSize),
+// or may be exactly s.npages*_PageSize
+// if s.elemsize is from sizeclasses.go.
+func (s *mspan) divideByElemSize(n uintptr) uintptr {
+       const doubleCheck = false
+
+       // See explanation in mksizeclasses.go's computeDivMagic.
+       q := uintptr((uint64(n) * uint64(s.divMul)) >> 32)
+
+       if doubleCheck && q != n/s.elemsize {
+               println(n, "/", s.elemsize, "should be", n/s.elemsize, "but got", q)
+               throw("bad magic division")
        }
-       return uintptr(((uint64(byteOffset) >> s.divShift) * uint64(s.divMul)) >> s.divShift2)
+       return q
+}
+
+func (s *mspan) objIndex(p uintptr) uintptr {
+       return s.divideByElemSize(p - s.base())
 }
 
 func markBitsForAddr(p uintptr) markBits {
@@ -324,6 +333,10 @@ func heapBitsForAddr(addr uintptr) (h heapBits) {
        return
 }
 
+// clobberdeadPtr is a special value that is used by the compiler to
+// clobber dead stack slots, when -clobberdead flag is set.
+const clobberdeadPtr = uintptr(0xdeaddead | 0xdeaddead<<((^uintptr(0)>>63)*32))
+
 // badPointer throws bad pointer in heap panic.
 func badPointer(s *mspan, p, refBase, refOff uintptr) {
        // Typically this indicates an incorrect use
@@ -336,13 +349,16 @@ func badPointer(s *mspan, p, refBase, refOff uintptr) {
        // in allocated spans.
        printlock()
        print("runtime: pointer ", hex(p))
-       state := s.state.get()
-       if state != mSpanInUse {
-               print(" to unallocated span")
-       } else {
-               print(" to unused region of span")
+       if s != nil {
+               state := s.state.get()
+               if state != mSpanInUse {
+                       print(" to unallocated span")
+               } else {
+                       print(" to unused region of span")
+               }
+               print(" span.base()=", hex(s.base()), " span.limit=", hex(s.limit), " span.state=", state)
        }
-       print(" span.base()=", hex(s.base()), " span.limit=", hex(s.limit), " span.state=", state, "\n")
+       print("\n")
        if refBase != 0 {
                print("runtime: found in object at *(", hex(refBase), "+", hex(refOff), ")\n")
                gcDumpObject("object", refBase, refOff)
@@ -373,6 +389,12 @@ func findObject(p, refBase, refOff uintptr, forStack bool) (base uintptr, s *msp
        // If s is nil, the virtual address has never been part of the heap.
        // This pointer may be to some mmap'd region, so we allow it.
        if s == nil {
+               if GOARCH == "amd64" && p == clobberdeadPtr && debug.invalidptr != 0 {
+                       // Crash if clobberdeadPtr is seen. Only on AMD64 for now, as
+                       // it is the only platform where compiler's clobberdead mode is
+                       // implemented. On AMD64 clobberdeadPtr cannot be a valid address.
+                       badPointer(s, p, refBase, refOff)
+               }
                return
        }
        // If p is a bad pointer, it may not be in s's bounds.
@@ -402,24 +424,8 @@ func findObject(p, refBase, refOff uintptr, forStack bool) (base uintptr, s *msp
                }
        }
 
-       // If this span holds object of a power of 2 size, just mask off the bits to
-       // the interior of the object. Otherwise use the size to get the base.
-       if s.baseMask != 0 {
-               // optimize for power of 2 sized objects.
-               base = s.base()
-               base = base + (p-base)&uintptr(s.baseMask)
-               objIndex = (base - s.base()) >> s.divShift
-               // base = p & s.baseMask is faster for small spans,
-               // but doesn't work for large spans.
-               // Overall, it's faster to use the more general computation above.
-       } else {
-               base = s.base()
-               if p-base >= s.elemsize {
-                       // n := (p - base) / s.elemsize, using division by multiplication
-                       objIndex = uintptr(p-base) >> s.divShift * uintptr(s.divMul) >> s.divShift2
-                       base += objIndex * s.elemsize
-               }
-       }
+       objIndex = s.objIndex(p)
+       base = s.base() + objIndex*s.elemsize
        return
 }
 
index 32622e6d4cbfdac2b22d4164afcba3e32cb6edd9..531f3be3720437235c3f21090a1147aec7395f1e 100644 (file)
@@ -168,29 +168,29 @@ func (c *mcache) refill(spc spanClass) {
        // mcache. If it gets uncached, we'll adjust this.
        stats := memstats.heapStats.acquire()
        atomic.Xadduintptr(&stats.smallAllocCount[spc.sizeclass()], uintptr(s.nelems)-uintptr(s.allocCount))
-       memstats.heapStats.release()
-
-       // Update heap_live with the same assumption.
-       usedBytes := uintptr(s.allocCount) * s.elemsize
-       atomic.Xadd64(&memstats.heap_live, int64(s.npages*pageSize)-int64(usedBytes))
 
        // Flush tinyAllocs.
        if spc == tinySpanClass {
-               atomic.Xadd64(&memstats.tinyallocs, int64(c.tinyAllocs))
+               atomic.Xadduintptr(&stats.tinyAllocCount, c.tinyAllocs)
                c.tinyAllocs = 0
        }
+       memstats.heapStats.release()
+
+       // Update gcController.heapLive with the same assumption.
+       usedBytes := uintptr(s.allocCount) * s.elemsize
+       atomic.Xadd64(&gcController.heapLive, int64(s.npages*pageSize)-int64(usedBytes))
 
        // While we're here, flush scanAlloc, since we have to call
        // revise anyway.
-       atomic.Xadd64(&memstats.heap_scan, int64(c.scanAlloc))
+       atomic.Xadd64(&gcController.heapScan, int64(c.scanAlloc))
        c.scanAlloc = 0
 
        if trace.enabled {
-               // heap_live changed.
+               // gcController.heapLive changed.
                traceHeapAlloc()
        }
        if gcBlackenEnabled != 0 {
-               // heap_live and heap_scan changed.
+               // gcController.heapLive and heapScan changed.
                gcController.revise()
        }
 
@@ -198,7 +198,10 @@ func (c *mcache) refill(spc spanClass) {
 }
 
 // allocLarge allocates a span for a large object.
-func (c *mcache) allocLarge(size uintptr, needzero bool, noscan bool) *mspan {
+// The boolean result indicates whether the span is known-zeroed.
+// If it did not need to be zeroed, it may not have been zeroed;
+// but if it came directly from the OS, it is already zeroed.
+func (c *mcache) allocLarge(size uintptr, needzero bool, noscan bool) (*mspan, bool) {
        if size+_PageSize < size {
                throw("out of memory")
        }
@@ -213,7 +216,7 @@ func (c *mcache) allocLarge(size uintptr, needzero bool, noscan bool) *mspan {
        deductSweepCredit(npages*_PageSize, npages)
 
        spc := makeSpanClass(0, noscan)
-       s := mheap_.alloc(npages, spc, needzero)
+       s, isZeroed := mheap_.alloc(npages, spc, needzero)
        if s == nil {
                throw("out of memory")
        }
@@ -222,10 +225,10 @@ func (c *mcache) allocLarge(size uintptr, needzero bool, noscan bool) *mspan {
        atomic.Xadduintptr(&stats.largeAllocCount, 1)
        memstats.heapStats.release()
 
-       // Update heap_live and revise pacing if needed.
-       atomic.Xadd64(&memstats.heap_live, int64(npages*pageSize))
+       // Update gcController.heapLive and revise pacing if needed.
+       atomic.Xadd64(&gcController.heapLive, int64(npages*pageSize))
        if trace.enabled {
-               // Trace that a heap alloc occurred because heap_live changed.
+               // Trace that a heap alloc occurred because gcController.heapLive changed.
                traceHeapAlloc()
        }
        if gcBlackenEnabled != 0 {
@@ -237,12 +240,12 @@ func (c *mcache) allocLarge(size uintptr, needzero bool, noscan bool) *mspan {
        mheap_.central[spc].mcentral.fullSwept(mheap_.sweepgen).push(s)
        s.limit = s.base() + size
        heapBitsForAddr(s.base()).initSpan(s)
-       return s
+       return s, isZeroed
 }
 
 func (c *mcache) releaseAll() {
        // Take this opportunity to flush scanAlloc.
-       atomic.Xadd64(&memstats.heap_scan, int64(c.scanAlloc))
+       atomic.Xadd64(&gcController.heapScan, int64(c.scanAlloc))
        c.scanAlloc = 0
 
        sg := mheap_.sweepgen
@@ -255,14 +258,14 @@ func (c *mcache) releaseAll() {
                        atomic.Xadduintptr(&stats.smallAllocCount[spanClass(i).sizeclass()], -n)
                        memstats.heapStats.release()
                        if s.sweepgen != sg+1 {
-                               // refill conservatively counted unallocated slots in heap_live.
+                               // refill conservatively counted unallocated slots in gcController.heapLive.
                                // Undo this.
                                //
                                // If this span was cached before sweep, then
-                               // heap_live was totally recomputed since
+                               // gcController.heapLive was totally recomputed since
                                // caching this span, so we don't do this for
                                // stale spans.
-                               atomic.Xadd64(&memstats.heap_live, -int64(n)*int64(s.elemsize))
+                               atomic.Xadd64(&gcController.heapLive, -int64(n)*int64(s.elemsize))
                        }
                        // Release the span to the mcentral.
                        mheap_.central[i].mcentral.uncacheSpan(s)
@@ -272,10 +275,14 @@ func (c *mcache) releaseAll() {
        // Clear tinyalloc pool.
        c.tiny = 0
        c.tinyoffset = 0
-       atomic.Xadd64(&memstats.tinyallocs, int64(c.tinyAllocs))
+
+       // Flush tinyAllocs.
+       stats := memstats.heapStats.acquire()
+       atomic.Xadduintptr(&stats.tinyAllocCount, c.tinyAllocs)
        c.tinyAllocs = 0
+       memstats.heapStats.release()
 
-       // Updated heap_scan and possible heap_live.
+       // Updated heapScan and possible gcController.heapLive.
        if gcBlackenEnabled != 0 {
                gcController.revise()
        }
index cd20dec5394d346bdd5bd95e895143a4b9af2bf0..6013c94c69808a9d728b9e4d67c9db1fa16dc91f 100644 (file)
@@ -81,8 +81,6 @@ func (c *mcentral) cacheSpan() *mspan {
        spanBytes := uintptr(class_to_allocnpages[c.spanclass.sizeclass()]) * _PageSize
        deductSweepCredit(spanBytes, 0)
 
-       sg := mheap_.sweepgen
-
        traceDone := false
        if trace.enabled {
                traceGCSweepStart()
@@ -104,6 +102,8 @@ func (c *mcentral) cacheSpan() *mspan {
        spanBudget := 100
 
        var s *mspan
+       sl := newSweepLocker()
+       sg := sl.sweepGen
 
        // Try partial swept spans first.
        if s = c.partialSwept(sg).pop(); s != nil {
@@ -116,9 +116,10 @@ func (c *mcentral) cacheSpan() *mspan {
                if s == nil {
                        break
                }
-               if atomic.Load(&s.sweepgen) == sg-2 && atomic.Cas(&s.sweepgen, sg-2, sg-1) {
+               if s, ok := sl.tryAcquire(s); ok {
                        // We got ownership of the span, so let's sweep it and use it.
                        s.sweep(true)
+                       sl.dispose()
                        goto havespan
                }
                // We failed to get ownership of the span, which means it's being or
@@ -135,20 +136,22 @@ func (c *mcentral) cacheSpan() *mspan {
                if s == nil {
                        break
                }
-               if atomic.Load(&s.sweepgen) == sg-2 && atomic.Cas(&s.sweepgen, sg-2, sg-1) {
+               if s, ok := sl.tryAcquire(s); ok {
                        // We got ownership of the span, so let's sweep it.
                        s.sweep(true)
                        // Check if there's any free space.
                        freeIndex := s.nextFreeIndex()
                        if freeIndex != s.nelems {
                                s.freeindex = freeIndex
+                               sl.dispose()
                                goto havespan
                        }
                        // Add it to the swept list, because sweeping didn't give us any free space.
-                       c.fullSwept(sg).push(s)
+                       c.fullSwept(sg).push(s.mspan)
                }
                // See comment for partial unswept spans.
        }
+       sl.dispose()
        if trace.enabled {
                traceGCSweepDone()
                traceDone = true
@@ -211,7 +214,13 @@ func (c *mcentral) uncacheSpan(s *mspan) {
        if stale {
                // It's stale, so just sweep it. Sweeping will put it on
                // the right list.
-               s.sweep(false)
+               //
+               // We don't use a sweepLocker here. Stale cached spans
+               // aren't in the global sweep lists, so mark termination
+               // itself holds up sweep completion until all mcaches
+               // have been swept.
+               ss := sweepLocked{s}
+               ss.sweep(false)
        } else {
                if int(s.nelems)-int(s.allocCount) > 0 {
                        // Put it back on the partial swept list.
@@ -229,14 +238,14 @@ func (c *mcentral) grow() *mspan {
        npages := uintptr(class_to_allocnpages[c.spanclass.sizeclass()])
        size := uintptr(class_to_size[c.spanclass.sizeclass()])
 
-       s := mheap_.alloc(npages, c.spanclass, true)
+       s, _ := mheap_.alloc(npages, c.spanclass, true)
        if s == nil {
                return nil
        }
 
        // Use division by multiplication and shifts to quickly compute:
        // n := (npages << _PageShift) / size
-       n := (npages << _PageShift) >> s.divShift * uintptr(s.divMul) >> s.divShift2
+       n := s.divideByElemSize(npages << _PageShift)
        s.limit = s.base() + size*n
        heapBitsForAddr(s.base()).initSpan(s)
        return s
index e1f1db2dba32dfe53b58bc3de6f9d98cc1a6bfff..45a68e4721514cbe64ddf28997e975ec3e98d567 100644 (file)
@@ -98,6 +98,20 @@ func initMetrics() {
                                }
                        },
                },
+               "/gc/heap/allocs:bytes": {
+                       deps: makeStatDepSet(heapStatsDep),
+                       compute: func(in *statAggregate, out *metricValue) {
+                               out.kind = metricKindUint64
+                               out.scalar = in.heapStats.totalAllocated
+                       },
+               },
+               "/gc/heap/allocs:objects": {
+                       deps: makeStatDepSet(heapStatsDep),
+                       compute: func(in *statAggregate, out *metricValue) {
+                               out.kind = metricKindUint64
+                               out.scalar = in.heapStats.totalAllocs
+                       },
+               },
                "/gc/heap/frees-by-size:bytes": {
                        deps: makeStatDepSet(heapStatsDep),
                        compute: func(in *statAggregate, out *metricValue) {
@@ -110,6 +124,20 @@ func initMetrics() {
                                }
                        },
                },
+               "/gc/heap/frees:bytes": {
+                       deps: makeStatDepSet(heapStatsDep),
+                       compute: func(in *statAggregate, out *metricValue) {
+                               out.kind = metricKindUint64
+                               out.scalar = in.heapStats.totalFreed
+                       },
+               },
+               "/gc/heap/frees:objects": {
+                       deps: makeStatDepSet(heapStatsDep),
+                       compute: func(in *statAggregate, out *metricValue) {
+                               out.kind = metricKindUint64
+                               out.scalar = in.heapStats.totalFrees
+                       },
+               },
                "/gc/heap/goal:bytes": {
                        deps: makeStatDepSet(sysStatsDep),
                        compute: func(in *statAggregate, out *metricValue) {
@@ -124,6 +152,13 @@ func initMetrics() {
                                out.scalar = in.heapStats.numObjects
                        },
                },
+               "/gc/heap/tiny/allocs:objects": {
+                       deps: makeStatDepSet(heapStatsDep),
+                       compute: func(in *statAggregate, out *metricValue) {
+                               out.kind = metricKindUint64
+                               out.scalar = uint64(in.heapStats.tinyAllocCount)
+                       },
+               },
                "/gc/pauses:seconds": {
                        compute: func(_ *statAggregate, out *metricValue) {
                                hist := out.float64HistOrInit(timeHistBuckets)
@@ -245,6 +280,15 @@ func initMetrics() {
                                out.scalar = uint64(gcount())
                        },
                },
+               "/sched/latencies:seconds": {
+                       compute: func(_ *statAggregate, out *metricValue) {
+                               hist := out.float64HistOrInit(timeHistBuckets)
+                               hist.counts[0] = atomic.Load64(&sched.timeToRun.underflow)
+                               for i := range sched.timeToRun.counts {
+                                       hist.counts[i+1] = atomic.Load64(&sched.timeToRun.counts[i])
+                               }
+                       },
+               },
        }
        metricsInit = true
 }
@@ -321,6 +365,22 @@ type heapStatsAggregate struct {
 
        // numObjects is the number of live objects in the heap.
        numObjects uint64
+
+       // totalAllocated is the total bytes of heap objects allocated
+       // over the lifetime of the program.
+       totalAllocated uint64
+
+       // totalFreed is the total bytes of heap objects freed
+       // over the lifetime of the program.
+       totalFreed uint64
+
+       // totalAllocs is the number of heap objects allocated over
+       // the lifetime of the program.
+       totalAllocs uint64
+
+       // totalFrees is the number of heap objects freed over
+       // the lifetime of the program.
+       totalFrees uint64
 }
 
 // compute populates the heapStatsAggregate with values from the runtime.
@@ -328,13 +388,20 @@ func (a *heapStatsAggregate) compute() {
        memstats.heapStats.read(&a.heapStatsDelta)
 
        // Calculate derived stats.
-       a.inObjects = uint64(a.largeAlloc - a.largeFree)
-       a.numObjects = uint64(a.largeAllocCount - a.largeFreeCount)
+       a.totalAllocs = uint64(a.largeAllocCount)
+       a.totalFrees = uint64(a.largeFreeCount)
+       a.totalAllocated = uint64(a.largeAlloc)
+       a.totalFreed = uint64(a.largeFree)
        for i := range a.smallAllocCount {
-               n := uint64(a.smallAllocCount[i] - a.smallFreeCount[i])
-               a.inObjects += n * uint64(class_to_size[i])
-               a.numObjects += n
+               na := uint64(a.smallAllocCount[i])
+               nf := uint64(a.smallFreeCount[i])
+               a.totalAllocs += na
+               a.totalFrees += nf
+               a.totalAllocated += na * uint64(class_to_size[i])
+               a.totalFreed += nf * uint64(class_to_size[i])
        }
+       a.inObjects = a.totalAllocated - a.totalFreed
+       a.numObjects = a.totalAllocs - a.totalFrees
 }
 
 // sysStatsAggregate represents system memory stats obtained
@@ -364,7 +431,7 @@ func (a *sysStatsAggregate) compute() {
        a.buckHashSys = memstats.buckhash_sys.load()
        a.gcMiscSys = memstats.gcMiscSys.load()
        a.otherSys = memstats.other_sys.load()
-       a.heapGoal = atomic.Load64(&memstats.next_gc)
+       a.heapGoal = atomic.Load64(&gcController.heapGoal)
        a.gcCyclesDone = uint64(memstats.numgc)
        a.gcCyclesForced = uint64(memstats.numforcedgc)
 
@@ -481,7 +548,7 @@ func readMetrics(samplesp unsafe.Pointer, len int, cap int) {
 
        // Acquire the metricsSema but with handoff. This operation
        // is expensive enough that queueing up goroutines and handing
-       // off between them will be noticably better-behaved.
+       // off between them will be noticeably better-behaved.
        semacquire1(&metricsSema, true, 0, 0)
 
        // Ensure the map is initialized.
index 117515610436f2a27145a79f589400d8076e14b3..c147cada8944a296d951d7b28299d98db5417692 100644 (file)
@@ -70,17 +70,50 @@ var allDesc = []Description{
                Cumulative:  true,
        },
        {
-               Name:        "/gc/heap/allocs-by-size:bytes",
-               Description: "Distribution of all objects allocated by approximate size.",
-               Kind:        KindFloat64Histogram,
+               Name: "/gc/heap/allocs-by-size:bytes",
+               Description: "Distribution of heap allocations by approximate size. " +
+                       "Note that this does not include tiny objects as defined by " +
+                       "/gc/heap/tiny/allocs:objects, only tiny blocks.",
+               Kind:       KindFloat64Histogram,
+               Cumulative: true,
+       },
+       {
+               Name:        "/gc/heap/allocs:bytes",
+               Description: "Cumulative sum of memory allocated to the heap by the application.",
+               Kind:        KindUint64,
                Cumulative:  true,
        },
        {
-               Name:        "/gc/heap/frees-by-size:bytes",
-               Description: "Distribution of all objects freed by approximate size.",
-               Kind:        KindFloat64Histogram,
+               Name: "/gc/heap/allocs:objects",
+               Description: "Cumulative count of heap allocations triggered by the application. " +
+                       "Note that this does not include tiny objects as defined by " +
+                       "/gc/heap/tiny/allocs:objects, only tiny blocks.",
+               Kind:       KindUint64,
+               Cumulative: true,
+       },
+       {
+               Name: "/gc/heap/frees-by-size:bytes",
+               Description: "Distribution of freed heap allocations by approximate size. " +
+                       "Note that this does not include tiny objects as defined by " +
+                       "/gc/heap/tiny/allocs:objects, only tiny blocks.",
+               Kind:       KindFloat64Histogram,
+               Cumulative: true,
+       },
+       {
+               Name:        "/gc/heap/frees:bytes",
+               Description: "Cumulative sum of heap memory freed by the garbage collector.",
+               Kind:        KindUint64,
                Cumulative:  true,
        },
+       {
+               Name: "/gc/heap/frees:objects",
+               Description: "Cumulative count of heap allocations whose storage was freed " +
+                       "by the garbage collector. " +
+                       "Note that this does not include tiny objects as defined by " +
+                       "/gc/heap/tiny/allocs:objects, only tiny blocks.",
+               Kind:       KindUint64,
+               Cumulative: true,
+       },
        {
                Name:        "/gc/heap/goal:bytes",
                Description: "Heap size target for the end of the GC cycle.",
@@ -91,6 +124,16 @@ var allDesc = []Description{
                Description: "Number of objects, live or unswept, occupying heap memory.",
                Kind:        KindUint64,
        },
+       {
+               Name: "/gc/heap/tiny/allocs:objects",
+               Description: "Count of small allocations that are packed together into blocks. " +
+                       "These allocations are counted separately from other allocations " +
+                       "because each individual allocation is not tracked by the runtime, " +
+                       "only their block. Each block is already accounted for in " +
+                       "allocs-by-size and frees-by-size.",
+               Kind:       KindUint64,
+               Cumulative: true,
+       },
        {
                Name:        "/gc/pauses:seconds",
                Description: "Distribution individual GC-related stop-the-world pause latencies.",
@@ -176,6 +219,11 @@ var allDesc = []Description{
                Description: "Count of live goroutines.",
                Kind:        KindUint64,
        },
+       {
+               Name:        "/sched/latencies:seconds",
+               Description: "Distribution of the time goroutines have spent in the scheduler in a runnable state before actually running.",
+               Kind:        KindFloat64Histogram,
+       },
 }
 
 // All returns a slice of containing metric descriptions for all supported metrics.
index 7f790afc12eeabcdda78f0d01a0d83003155d18a..91ef03072de49b4ac3187c7b13278025a1a0db41 100644 (file)
@@ -61,10 +61,30 @@ Below is the full list of supported metrics, ordered lexicographically.
                Count of all completed GC cycles.
 
        /gc/heap/allocs-by-size:bytes
-               Distribution of all objects allocated by approximate size.
+               Distribution of heap allocations by approximate size.
+               Note that this does not include tiny objects as defined by /gc/heap/tiny/allocs:objects,
+               only tiny blocks.
+
+       /gc/heap/allocs:bytes
+               Cumulative sum of memory allocated to the heap by the application.
+
+       /gc/heap/allocs:objects
+               Cumulative count of heap allocations triggered by the application.
+               Note that this does not include tiny objects as defined by /gc/heap/tiny/allocs:objects,
+               only tiny blocks.
 
        /gc/heap/frees-by-size:bytes
-               Distribution of all objects freed by approximate size.
+               Distribution of freed heap allocations by approximate size.
+               Note that this does not include tiny objects as defined by /gc/heap/tiny/allocs:objects,
+               only tiny blocks.
+
+       /gc/heap/frees:bytes
+               Cumulative sum of heap memory freed by the garbage collector.
+
+       /gc/heap/frees:objects
+               Cumulative count of heap allocations whose storage was freed by the garbage collector.
+               Note that this does not include tiny objects as defined by /gc/heap/tiny/allocs:objects,
+               only tiny blocks.
 
        /gc/heap/goal:bytes
                Heap size target for the end of the GC cycle.
@@ -72,6 +92,13 @@ Below is the full list of supported metrics, ordered lexicographically.
        /gc/heap/objects:objects
                Number of objects, live or unswept, occupying heap memory.
 
+       /gc/heap/tiny/allocs:objects
+               Count of small allocations that are packed together into blocks.
+               These allocations are counted separately from other allocations
+               because each individual allocation is not tracked by the runtime,
+               only their block. Each block is already accounted for in
+               allocs-by-size and frees-by-size.
+
        /gc/pauses:seconds
                Distribution individual GC-related stop-the-world pause latencies.
 
@@ -139,5 +166,9 @@ Below is the full list of supported metrics, ordered lexicographically.
 
        /sched/goroutines:goroutines
                Count of live goroutines.
+
+       /sched/latencies:seconds
+               Distribution of the time goroutines have spent in the scheduler
+               in a runnable state before actually running.
 */
 package metrics
index 8a3cf019bdb474155b6daee86eee14d9cad00b39..5d32ef469caaa9658a1052d6868abd30f1a87870 100644 (file)
@@ -40,6 +40,9 @@ func TestReadMetrics(t *testing.T) {
        }
 
        // Check to make sure the values we read line up with other values we read.
+       var allocsBySize *metrics.Float64Histogram
+       var tinyAllocs uint64
+       var mallocs, frees uint64
        for i := range samples {
                switch name := samples[i].Name; name {
                case "/memory/classes/heap/free:bytes":
@@ -84,6 +87,9 @@ func TestReadMetrics(t *testing.T) {
                                        t.Errorf("histogram counts do not much BySize for class %d: got %d, want %d", i, c, m)
                                }
                        }
+                       allocsBySize = hist
+               case "/gc/heap/allocs:bytes":
+                       checkUint64(t, name, samples[i].Value.Uint64(), mstats.TotalAlloc)
                case "/gc/heap/frees-by-size:bytes":
                        hist := samples[i].Value.Float64Histogram()
                        // Skip size class 0 in BySize, because it's always empty and not represented
@@ -95,9 +101,29 @@ func TestReadMetrics(t *testing.T) {
                                        continue
                                }
                                if c, f := hist.Counts[i], sc.Frees; c != f {
-                                       t.Errorf("histogram counts do not much BySize for class %d: got %d, want %d", i, c, f)
+                                       t.Errorf("histogram counts do not match BySize for class %d: got %d, want %d", i, c, f)
                                }
                        }
+               case "/gc/heap/frees:bytes":
+                       checkUint64(t, name, samples[i].Value.Uint64(), mstats.TotalAlloc-mstats.HeapAlloc)
+               case "/gc/heap/tiny/allocs:objects":
+                       // Currently, MemStats adds tiny alloc count to both Mallocs AND Frees.
+                       // The reason for this is because MemStats couldn't be extended at the time
+                       // but there was a desire to have Mallocs at least be a little more representative,
+                       // while having Mallocs - Frees still represent a live object count.
+                       // Unfortunately, MemStats doesn't actually export a large allocation count,
+                       // so it's impossible to pull this number out directly.
+                       //
+                       // Check tiny allocation count outside of this loop, by using the allocs-by-size
+                       // histogram in order to figure out how many large objects there are.
+                       tinyAllocs = samples[i].Value.Uint64()
+                       // Because the next two metrics tests are checking against Mallocs and Frees,
+                       // we can't check them directly for the same reason: we need to account for tiny
+                       // allocations included in Mallocs and Frees.
+               case "/gc/heap/allocs:objects":
+                       mallocs = samples[i].Value.Uint64()
+               case "/gc/heap/frees:objects":
+                       frees = samples[i].Value.Uint64()
                case "/gc/heap/objects:objects":
                        checkUint64(t, name, samples[i].Value.Uint64(), mstats.HeapObjects)
                case "/gc/heap/goal:bytes":
@@ -110,6 +136,17 @@ func TestReadMetrics(t *testing.T) {
                        checkUint64(t, name, samples[i].Value.Uint64(), uint64(mstats.NumGC))
                }
        }
+
+       // Check tinyAllocs.
+       nonTinyAllocs := uint64(0)
+       for _, c := range allocsBySize.Counts {
+               nonTinyAllocs += c
+       }
+       checkUint64(t, "/gc/heap/tiny/allocs:objects", tinyAllocs, mstats.Mallocs-nonTinyAllocs)
+
+       // Check allocation and free counts.
+       checkUint64(t, "/gc/heap/allocs:objects", mallocs, mstats.Mallocs-tinyAllocs)
+       checkUint64(t, "/gc/heap/frees:objects", frees, mstats.Frees-tinyAllocs)
 }
 
 func TestReadMetricsConsistency(t *testing.T) {
@@ -132,8 +169,10 @@ func TestReadMetricsConsistency(t *testing.T) {
                got, want uint64
        }
        var objects struct {
-               alloc, free *metrics.Float64Histogram
-               total       uint64
+               alloc, free             *metrics.Float64Histogram
+               allocs, frees           uint64
+               allocdBytes, freedBytes uint64
+               total, totalBytes       uint64
        }
        var gc struct {
                numGC  uint64
@@ -159,10 +198,20 @@ func TestReadMetricsConsistency(t *testing.T) {
                switch samples[i].Name {
                case "/memory/classes/total:bytes":
                        totalVirtual.got = samples[i].Value.Uint64()
+               case "/memory/classes/heap/objects:bytes":
+                       objects.totalBytes = samples[i].Value.Uint64()
                case "/gc/heap/objects:objects":
                        objects.total = samples[i].Value.Uint64()
+               case "/gc/heap/allocs:bytes":
+                       objects.allocdBytes = samples[i].Value.Uint64()
+               case "/gc/heap/allocs:objects":
+                       objects.allocs = samples[i].Value.Uint64()
                case "/gc/heap/allocs-by-size:bytes":
                        objects.alloc = samples[i].Value.Float64Histogram()
+               case "/gc/heap/frees:bytes":
+                       objects.freedBytes = samples[i].Value.Uint64()
+               case "/gc/heap/frees:objects":
+                       objects.frees = samples[i].Value.Uint64()
                case "/gc/heap/frees-by-size:bytes":
                        objects.free = samples[i].Value.Float64Histogram()
                case "/gc/cycles:gc-cycles":
@@ -182,6 +231,12 @@ func TestReadMetricsConsistency(t *testing.T) {
        if totalVirtual.got != totalVirtual.want {
                t.Errorf(`"/memory/classes/total:bytes" does not match sum of /memory/classes/**: got %d, want %d`, totalVirtual.got, totalVirtual.want)
        }
+       if got, want := objects.allocs-objects.frees, objects.total; got != want {
+               t.Errorf("mismatch between object alloc/free tallies and total: got %d, want %d", got, want)
+       }
+       if got, want := objects.allocdBytes-objects.freedBytes, objects.totalBytes; got != want {
+               t.Errorf("mismatch between object alloc/free tallies and total: got %d, want %d", got, want)
+       }
        if b, c := len(objects.alloc.Buckets), len(objects.alloc.Counts); b != c+1 {
                t.Errorf("allocs-by-size has wrong bucket or counts length: %d buckets, %d counts", b, c)
        }
@@ -201,17 +256,25 @@ func TestReadMetricsConsistency(t *testing.T) {
                        }
                }
                if !t.Failed() {
-                       got, want := uint64(0), objects.total
+                       var gotAlloc, gotFree uint64
+                       want := objects.total
                        for i := range objects.alloc.Counts {
                                if objects.alloc.Counts[i] < objects.free.Counts[i] {
                                        t.Errorf("found more allocs than frees in object dist bucket %d", i)
                                        continue
                                }
-                               got += objects.alloc.Counts[i] - objects.free.Counts[i]
+                               gotAlloc += objects.alloc.Counts[i]
+                               gotFree += objects.free.Counts[i]
                        }
-                       if got != want {
+                       if got := gotAlloc - gotFree; got != want {
                                t.Errorf("object distribution counts don't match count of live objects: got %d, want %d", got, want)
                        }
+                       if gotAlloc != objects.allocs {
+                               t.Errorf("object distribution counts don't match total allocs: got %d, want %d", gotAlloc, objects.allocs)
+                       }
+                       if gotFree != objects.frees {
+                               t.Errorf("object distribution counts don't match total allocs: got %d, want %d", gotFree, objects.frees)
+                       }
                }
        }
        // The current GC has at least 2 pauses per GC.
index a9f2c1abc34c10aaea5b5762ea0f83dcc74eeb51..efb80120edf3626230d5c67e5c44d457981e31ba 100644 (file)
 // Next GC is after we've allocated an extra amount of memory proportional to
 // the amount already in use. The proportion is controlled by GOGC environment variable
 // (100 by default). If GOGC=100 and we're using 4M, we'll GC again when we get to 8M
-// (this mark is tracked in next_gc variable). This keeps the GC cost in linear
-// proportion to the allocation cost. Adjusting GOGC just changes the linear constant
+// (this mark is tracked in gcController.heapGoal variable). This keeps the GC cost in
+// linear proportion to the allocation cost. Adjusting GOGC just changes the linear constant
 // (and also the amount of extra memory used).
 
 // Oblets
@@ -149,45 +149,16 @@ const (
        sweepMinHeapDistance = 1024 * 1024
 )
 
-// heapminimum is the minimum heap size at which to trigger GC.
-// For small heaps, this overrides the usual GOGC*live set rule.
-//
-// When there is a very small live set but a lot of allocation, simply
-// collecting when the heap reaches GOGC*live results in many GC
-// cycles and high total per-GC overhead. This minimum amortizes this
-// per-GC overhead while keeping the heap reasonably small.
-//
-// During initialization this is set to 4MB*GOGC/100. In the case of
-// GOGC==0, this will set heapminimum to 0, resulting in constant
-// collection even when the heap size is small, which is useful for
-// debugging.
-var heapminimum uint64 = defaultHeapMinimum
-
-// defaultHeapMinimum is the value of heapminimum for GOGC==100.
-const defaultHeapMinimum = 4 << 20
-
-// Initialized from $GOGC.  GOGC=off means no GC.
-var gcpercent int32
-
 func gcinit() {
        if unsafe.Sizeof(workbuf{}) != _WorkbufSize {
                throw("size of Workbuf is suboptimal")
        }
-
        // No sweep on the first cycle.
-       mheap_.sweepdone = 1
+       mheap_.sweepDrained = 1
 
-       // Set a reasonable initial GC trigger.
-       memstats.triggerRatio = 7 / 8.0
-
-       // Fake a heap_marked value so it looks like a trigger at
-       // heapminimum is the appropriate growth from heap_marked.
-       // This will go into computing the initial GC goal.
-       memstats.heap_marked = uint64(float64(heapminimum) / (1 + memstats.triggerRatio))
-
-       // Set gcpercent from the environment. This will also compute
-       // and set the GC trigger and goal.
-       _ = setGCPercent(readgogc())
+       // Initialize GC pacer state.
+       // Use the environment variable GOGC for the initial gcPercent value.
+       gcController.init(readGOGC())
 
        work.startSema = 1
        work.markDoneSema = 1
@@ -196,16 +167,9 @@ func gcinit() {
        lockInit(&work.wbufSpans.lock, lockRankWbufSpans)
 }
 
-func readgogc() int32 {
-       p := gogetenv("GOGC")
-       if p == "off" {
-               return -1
-       }
-       if n, ok := atoi32(p); ok {
-               return n
-       }
-       return 100
-}
+// Temporary in order to enable register ABI work.
+// TODO(register args): convert back to local chan in gcenabled, passed to "go" stmts.
+var gcenable_setup chan int
 
 // gcenable is called after the bulk of the runtime initialization,
 // just before we're about to start letting user code run.
@@ -213,41 +177,17 @@ func readgogc() int32 {
 // scavenger goroutine, and enables GC.
 func gcenable() {
        // Kick off sweeping and scavenging.
-       c := make(chan int, 2)
+       gcenable_setup = make(chan int, 2)
        expectSystemGoroutine()
-       go bgsweep(c)
+       go bgsweep()
        expectSystemGoroutine()
-       go bgscavenge(c)
-       <-c
-       <-c
+       go bgscavenge()
+       <-gcenable_setup
+       <-gcenable_setup
+       gcenable_setup = nil
        memstats.enablegc = true // now that runtime is initialized, GC is okay
 }
 
-//go:linkname setGCPercent runtime_1debug.setGCPercent
-func setGCPercent(in int32) (out int32) {
-       // Run on the system stack since we grab the heap lock.
-       systemstack(func() {
-               lock(&mheap_.lock)
-               out = gcpercent
-               if in < 0 {
-                       in = -1
-               }
-               gcpercent = in
-               heapminimum = defaultHeapMinimum * uint64(gcpercent) / 100
-               // Update pacing in response to gcpercent change.
-               gcSetTriggerRatio(memstats.triggerRatio)
-               unlock(&mheap_.lock)
-       })
-
-       // If we just disabled GC, wait for any concurrent GC mark to
-       // finish so we always return with no GC running.
-       if in < 0 {
-               gcWaitOnMark(atomic.Load(&work.cycles))
-       }
-
-       return out
-}
-
 // Garbage collector phase.
 // Indicates to write barrier and synchronization task to perform.
 var gcphase uint32
@@ -304,9 +244,11 @@ const (
        // gcMarkWorkerFractionalMode indicates that a P is currently
        // running the "fractional" mark worker. The fractional worker
        // is necessary when GOMAXPROCS*gcBackgroundUtilization is not
-       // an integer. The fractional worker should run until it is
-       // preempted and will be scheduled to pick up the fractional
-       // part of GOMAXPROCS*gcBackgroundUtilization.
+       // an integer and using only dedicated workers would result in
+       // utilization too far from the target of gcBackgroundUtilization.
+       // The fractional worker should run until it is preempted and
+       // will be scheduled to pick up the fractional part of
+       // GOMAXPROCS*gcBackgroundUtilization.
        gcMarkWorkerFractionalMode
 
        // gcMarkWorkerIdleMode indicates that a P is running the mark
@@ -325,474 +267,6 @@ var gcMarkWorkerModeStrings = [...]string{
        "GC (idle)",
 }
 
-// gcController implements the GC pacing controller that determines
-// when to trigger concurrent garbage collection and how much marking
-// work to do in mutator assists and background marking.
-//
-// It uses a feedback control algorithm to adjust the memstats.gc_trigger
-// trigger based on the heap growth and GC CPU utilization each cycle.
-// This algorithm optimizes for heap growth to match GOGC and for CPU
-// utilization between assist and background marking to be 25% of
-// GOMAXPROCS. The high-level design of this algorithm is documented
-// at https://golang.org/s/go15gcpacing.
-//
-// All fields of gcController are used only during a single mark
-// cycle.
-var gcController gcControllerState
-
-type gcControllerState struct {
-       // scanWork is the total scan work performed this cycle. This
-       // is updated atomically during the cycle. Updates occur in
-       // bounded batches, since it is both written and read
-       // throughout the cycle. At the end of the cycle, this is how
-       // much of the retained heap is scannable.
-       //
-       // Currently this is the bytes of heap scanned. For most uses,
-       // this is an opaque unit of work, but for estimation the
-       // definition is important.
-       scanWork int64
-
-       // bgScanCredit is the scan work credit accumulated by the
-       // concurrent background scan. This credit is accumulated by
-       // the background scan and stolen by mutator assists. This is
-       // updated atomically. Updates occur in bounded batches, since
-       // it is both written and read throughout the cycle.
-       bgScanCredit int64
-
-       // assistTime is the nanoseconds spent in mutator assists
-       // during this cycle. This is updated atomically. Updates
-       // occur in bounded batches, since it is both written and read
-       // throughout the cycle.
-       assistTime int64
-
-       // dedicatedMarkTime is the nanoseconds spent in dedicated
-       // mark workers during this cycle. This is updated atomically
-       // at the end of the concurrent mark phase.
-       dedicatedMarkTime int64
-
-       // fractionalMarkTime is the nanoseconds spent in the
-       // fractional mark worker during this cycle. This is updated
-       // atomically throughout the cycle and will be up-to-date if
-       // the fractional mark worker is not currently running.
-       fractionalMarkTime int64
-
-       // idleMarkTime is the nanoseconds spent in idle marking
-       // during this cycle. This is updated atomically throughout
-       // the cycle.
-       idleMarkTime int64
-
-       // markStartTime is the absolute start time in nanoseconds
-       // that assists and background mark workers started.
-       markStartTime int64
-
-       // dedicatedMarkWorkersNeeded is the number of dedicated mark
-       // workers that need to be started. This is computed at the
-       // beginning of each cycle and decremented atomically as
-       // dedicated mark workers get started.
-       dedicatedMarkWorkersNeeded int64
-
-       // assistWorkPerByte is the ratio of scan work to allocated
-       // bytes that should be performed by mutator assists. This is
-       // computed at the beginning of each cycle and updated every
-       // time heap_scan is updated.
-       //
-       // Stored as a uint64, but it's actually a float64. Use
-       // float64frombits to get the value.
-       //
-       // Read and written atomically.
-       assistWorkPerByte uint64
-
-       // assistBytesPerWork is 1/assistWorkPerByte.
-       //
-       // Stored as a uint64, but it's actually a float64. Use
-       // float64frombits to get the value.
-       //
-       // Read and written atomically.
-       //
-       // Note that because this is read and written independently
-       // from assistWorkPerByte users may notice a skew between
-       // the two values, and such a state should be safe.
-       assistBytesPerWork uint64
-
-       // fractionalUtilizationGoal is the fraction of wall clock
-       // time that should be spent in the fractional mark worker on
-       // each P that isn't running a dedicated worker.
-       //
-       // For example, if the utilization goal is 25% and there are
-       // no dedicated workers, this will be 0.25. If the goal is
-       // 25%, there is one dedicated worker, and GOMAXPROCS is 5,
-       // this will be 0.05 to make up the missing 5%.
-       //
-       // If this is zero, no fractional workers are needed.
-       fractionalUtilizationGoal float64
-
-       _ cpu.CacheLinePad
-}
-
-// startCycle resets the GC controller's state and computes estimates
-// for a new GC cycle. The caller must hold worldsema and the world
-// must be stopped.
-func (c *gcControllerState) startCycle() {
-       c.scanWork = 0
-       c.bgScanCredit = 0
-       c.assistTime = 0
-       c.dedicatedMarkTime = 0
-       c.fractionalMarkTime = 0
-       c.idleMarkTime = 0
-
-       // Ensure that the heap goal is at least a little larger than
-       // the current live heap size. This may not be the case if GC
-       // start is delayed or if the allocation that pushed heap_live
-       // over gc_trigger is large or if the trigger is really close to
-       // GOGC. Assist is proportional to this distance, so enforce a
-       // minimum distance, even if it means going over the GOGC goal
-       // by a tiny bit.
-       if memstats.next_gc < memstats.heap_live+1024*1024 {
-               memstats.next_gc = memstats.heap_live + 1024*1024
-       }
-
-       // Compute the background mark utilization goal. In general,
-       // this may not come out exactly. We round the number of
-       // dedicated workers so that the utilization is closest to
-       // 25%. For small GOMAXPROCS, this would introduce too much
-       // error, so we add fractional workers in that case.
-       totalUtilizationGoal := float64(gomaxprocs) * gcBackgroundUtilization
-       c.dedicatedMarkWorkersNeeded = int64(totalUtilizationGoal + 0.5)
-       utilError := float64(c.dedicatedMarkWorkersNeeded)/totalUtilizationGoal - 1
-       const maxUtilError = 0.3
-       if utilError < -maxUtilError || utilError > maxUtilError {
-               // Rounding put us more than 30% off our goal. With
-               // gcBackgroundUtilization of 25%, this happens for
-               // GOMAXPROCS<=3 or GOMAXPROCS=6. Enable fractional
-               // workers to compensate.
-               if float64(c.dedicatedMarkWorkersNeeded) > totalUtilizationGoal {
-                       // Too many dedicated workers.
-                       c.dedicatedMarkWorkersNeeded--
-               }
-               c.fractionalUtilizationGoal = (totalUtilizationGoal - float64(c.dedicatedMarkWorkersNeeded)) / float64(gomaxprocs)
-       } else {
-               c.fractionalUtilizationGoal = 0
-       }
-
-       // In STW mode, we just want dedicated workers.
-       if debug.gcstoptheworld > 0 {
-               c.dedicatedMarkWorkersNeeded = int64(gomaxprocs)
-               c.fractionalUtilizationGoal = 0
-       }
-
-       // Clear per-P state
-       for _, p := range allp {
-               p.gcAssistTime = 0
-               p.gcFractionalMarkTime = 0
-       }
-
-       // Compute initial values for controls that are updated
-       // throughout the cycle.
-       c.revise()
-
-       if debug.gcpacertrace > 0 {
-               assistRatio := float64frombits(atomic.Load64(&c.assistWorkPerByte))
-               print("pacer: assist ratio=", assistRatio,
-                       " (scan ", memstats.heap_scan>>20, " MB in ",
-                       work.initialHeapLive>>20, "->",
-                       memstats.next_gc>>20, " MB)",
-                       " workers=", c.dedicatedMarkWorkersNeeded,
-                       "+", c.fractionalUtilizationGoal, "\n")
-       }
-}
-
-// revise updates the assist ratio during the GC cycle to account for
-// improved estimates. This should be called whenever memstats.heap_scan,
-// memstats.heap_live, or memstats.next_gc is updated. It is safe to
-// call concurrently, but it may race with other calls to revise.
-//
-// The result of this race is that the two assist ratio values may not line
-// up or may be stale. In practice this is OK because the assist ratio
-// moves slowly throughout a GC cycle, and the assist ratio is a best-effort
-// heuristic anyway. Furthermore, no part of the heuristic depends on
-// the two assist ratio values being exact reciprocals of one another, since
-// the two values are used to convert values from different sources.
-//
-// The worst case result of this raciness is that we may miss a larger shift
-// in the ratio (say, if we decide to pace more aggressively against the
-// hard heap goal) but even this "hard goal" is best-effort (see #40460).
-// The dedicated GC should ensure we don't exceed the hard goal by too much
-// in the rare case we do exceed it.
-//
-// It should only be called when gcBlackenEnabled != 0 (because this
-// is when assists are enabled and the necessary statistics are
-// available).
-func (c *gcControllerState) revise() {
-       gcpercent := gcpercent
-       if gcpercent < 0 {
-               // If GC is disabled but we're running a forced GC,
-               // act like GOGC is huge for the below calculations.
-               gcpercent = 100000
-       }
-       live := atomic.Load64(&memstats.heap_live)
-       scan := atomic.Load64(&memstats.heap_scan)
-       work := atomic.Loadint64(&c.scanWork)
-
-       // Assume we're under the soft goal. Pace GC to complete at
-       // next_gc assuming the heap is in steady-state.
-       heapGoal := int64(atomic.Load64(&memstats.next_gc))
-
-       // Compute the expected scan work remaining.
-       //
-       // This is estimated based on the expected
-       // steady-state scannable heap. For example, with
-       // GOGC=100, only half of the scannable heap is
-       // expected to be live, so that's what we target.
-       //
-       // (This is a float calculation to avoid overflowing on
-       // 100*heap_scan.)
-       scanWorkExpected := int64(float64(scan) * 100 / float64(100+gcpercent))
-
-       if int64(live) > heapGoal || work > scanWorkExpected {
-               // We're past the soft goal, or we've already done more scan
-               // work than we expected. Pace GC so that in the worst case it
-               // will complete by the hard goal.
-               const maxOvershoot = 1.1
-               heapGoal = int64(float64(heapGoal) * maxOvershoot)
-
-               // Compute the upper bound on the scan work remaining.
-               scanWorkExpected = int64(scan)
-       }
-
-       // Compute the remaining scan work estimate.
-       //
-       // Note that we currently count allocations during GC as both
-       // scannable heap (heap_scan) and scan work completed
-       // (scanWork), so allocation will change this difference
-       // slowly in the soft regime and not at all in the hard
-       // regime.
-       scanWorkRemaining := scanWorkExpected - work
-       if scanWorkRemaining < 1000 {
-               // We set a somewhat arbitrary lower bound on
-               // remaining scan work since if we aim a little high,
-               // we can miss by a little.
-               //
-               // We *do* need to enforce that this is at least 1,
-               // since marking is racy and double-scanning objects
-               // may legitimately make the remaining scan work
-               // negative, even in the hard goal regime.
-               scanWorkRemaining = 1000
-       }
-
-       // Compute the heap distance remaining.
-       heapRemaining := heapGoal - int64(live)
-       if heapRemaining <= 0 {
-               // This shouldn't happen, but if it does, avoid
-               // dividing by zero or setting the assist negative.
-               heapRemaining = 1
-       }
-
-       // Compute the mutator assist ratio so by the time the mutator
-       // allocates the remaining heap bytes up to next_gc, it will
-       // have done (or stolen) the remaining amount of scan work.
-       // Note that the assist ratio values are updated atomically
-       // but not together. This means there may be some degree of
-       // skew between the two values. This is generally OK as the
-       // values shift relatively slowly over the course of a GC
-       // cycle.
-       assistWorkPerByte := float64(scanWorkRemaining) / float64(heapRemaining)
-       assistBytesPerWork := float64(heapRemaining) / float64(scanWorkRemaining)
-       atomic.Store64(&c.assistWorkPerByte, float64bits(assistWorkPerByte))
-       atomic.Store64(&c.assistBytesPerWork, float64bits(assistBytesPerWork))
-}
-
-// endCycle computes the trigger ratio for the next cycle.
-func (c *gcControllerState) endCycle() float64 {
-       if work.userForced {
-               // Forced GC means this cycle didn't start at the
-               // trigger, so where it finished isn't good
-               // information about how to adjust the trigger.
-               // Just leave it where it is.
-               return memstats.triggerRatio
-       }
-
-       // Proportional response gain for the trigger controller. Must
-       // be in [0, 1]. Lower values smooth out transient effects but
-       // take longer to respond to phase changes. Higher values
-       // react to phase changes quickly, but are more affected by
-       // transient changes. Values near 1 may be unstable.
-       const triggerGain = 0.5
-
-       // Compute next cycle trigger ratio. First, this computes the
-       // "error" for this cycle; that is, how far off the trigger
-       // was from what it should have been, accounting for both heap
-       // growth and GC CPU utilization. We compute the actual heap
-       // growth during this cycle and scale that by how far off from
-       // the goal CPU utilization we were (to estimate the heap
-       // growth if we had the desired CPU utilization). The
-       // difference between this estimate and the GOGC-based goal
-       // heap growth is the error.
-       goalGrowthRatio := gcEffectiveGrowthRatio()
-       actualGrowthRatio := float64(memstats.heap_live)/float64(memstats.heap_marked) - 1
-       assistDuration := nanotime() - c.markStartTime
-
-       // Assume background mark hit its utilization goal.
-       utilization := gcBackgroundUtilization
-       // Add assist utilization; avoid divide by zero.
-       if assistDuration > 0 {
-               utilization += float64(c.assistTime) / float64(assistDuration*int64(gomaxprocs))
-       }
-
-       triggerError := goalGrowthRatio - memstats.triggerRatio - utilization/gcGoalUtilization*(actualGrowthRatio-memstats.triggerRatio)
-
-       // Finally, we adjust the trigger for next time by this error,
-       // damped by the proportional gain.
-       triggerRatio := memstats.triggerRatio + triggerGain*triggerError
-
-       if debug.gcpacertrace > 0 {
-               // Print controller state in terms of the design
-               // document.
-               H_m_prev := memstats.heap_marked
-               h_t := memstats.triggerRatio
-               H_T := memstats.gc_trigger
-               h_a := actualGrowthRatio
-               H_a := memstats.heap_live
-               h_g := goalGrowthRatio
-               H_g := int64(float64(H_m_prev) * (1 + h_g))
-               u_a := utilization
-               u_g := gcGoalUtilization
-               W_a := c.scanWork
-               print("pacer: H_m_prev=", H_m_prev,
-                       " h_t=", h_t, " H_T=", H_T,
-                       " h_a=", h_a, " H_a=", H_a,
-                       " h_g=", h_g, " H_g=", H_g,
-                       " u_a=", u_a, " u_g=", u_g,
-                       " W_a=", W_a,
-                       " goalΔ=", goalGrowthRatio-h_t,
-                       " actualΔ=", h_a-h_t,
-                       " u_a/u_g=", u_a/u_g,
-                       "\n")
-       }
-
-       return triggerRatio
-}
-
-// enlistWorker encourages another dedicated mark worker to start on
-// another P if there are spare worker slots. It is used by putfull
-// when more work is made available.
-//
-//go:nowritebarrier
-func (c *gcControllerState) enlistWorker() {
-       // If there are idle Ps, wake one so it will run an idle worker.
-       // NOTE: This is suspected of causing deadlocks. See golang.org/issue/19112.
-       //
-       //      if atomic.Load(&sched.npidle) != 0 && atomic.Load(&sched.nmspinning) == 0 {
-       //              wakep()
-       //              return
-       //      }
-
-       // There are no idle Ps. If we need more dedicated workers,
-       // try to preempt a running P so it will switch to a worker.
-       if c.dedicatedMarkWorkersNeeded <= 0 {
-               return
-       }
-       // Pick a random other P to preempt.
-       if gomaxprocs <= 1 {
-               return
-       }
-       gp := getg()
-       if gp == nil || gp.m == nil || gp.m.p == 0 {
-               return
-       }
-       myID := gp.m.p.ptr().id
-       for tries := 0; tries < 5; tries++ {
-               id := int32(fastrandn(uint32(gomaxprocs - 1)))
-               if id >= myID {
-                       id++
-               }
-               p := allp[id]
-               if p.status != _Prunning {
-                       continue
-               }
-               if preemptone(p) {
-                       return
-               }
-       }
-}
-
-// findRunnableGCWorker returns a background mark worker for _p_ if it
-// should be run. This must only be called when gcBlackenEnabled != 0.
-func (c *gcControllerState) findRunnableGCWorker(_p_ *p) *g {
-       if gcBlackenEnabled == 0 {
-               throw("gcControllerState.findRunnable: blackening not enabled")
-       }
-
-       if !gcMarkWorkAvailable(_p_) {
-               // No work to be done right now. This can happen at
-               // the end of the mark phase when there are still
-               // assists tapering off. Don't bother running a worker
-               // now because it'll just return immediately.
-               return nil
-       }
-
-       // Grab a worker before we commit to running below.
-       node := (*gcBgMarkWorkerNode)(gcBgMarkWorkerPool.pop())
-       if node == nil {
-               // There is at least one worker per P, so normally there are
-               // enough workers to run on all Ps, if necessary. However, once
-               // a worker enters gcMarkDone it may park without rejoining the
-               // pool, thus freeing a P with no corresponding worker.
-               // gcMarkDone never depends on another worker doing work, so it
-               // is safe to simply do nothing here.
-               //
-               // If gcMarkDone bails out without completing the mark phase,
-               // it will always do so with queued global work. Thus, that P
-               // will be immediately eligible to re-run the worker G it was
-               // just using, ensuring work can complete.
-               return nil
-       }
-
-       decIfPositive := func(ptr *int64) bool {
-               for {
-                       v := atomic.Loadint64(ptr)
-                       if v <= 0 {
-                               return false
-                       }
-
-                       // TODO: having atomic.Casint64 would be more pleasant.
-                       if atomic.Cas64((*uint64)(unsafe.Pointer(ptr)), uint64(v), uint64(v-1)) {
-                               return true
-                       }
-               }
-       }
-
-       if decIfPositive(&c.dedicatedMarkWorkersNeeded) {
-               // This P is now dedicated to marking until the end of
-               // the concurrent mark phase.
-               _p_.gcMarkWorkerMode = gcMarkWorkerDedicatedMode
-       } else if c.fractionalUtilizationGoal == 0 {
-               // No need for fractional workers.
-               gcBgMarkWorkerPool.push(&node.node)
-               return nil
-       } else {
-               // Is this P behind on the fractional utilization
-               // goal?
-               //
-               // This should be kept in sync with pollFractionalWorkerExit.
-               delta := nanotime() - gcController.markStartTime
-               if delta > 0 && float64(_p_.gcFractionalMarkTime)/float64(delta) > c.fractionalUtilizationGoal {
-                       // Nope. No need to run a fractional worker.
-                       gcBgMarkWorkerPool.push(&node.node)
-                       return nil
-               }
-               // Run a fractional worker.
-               _p_.gcMarkWorkerMode = gcMarkWorkerFractionalMode
-       }
-
-       // Run the background mark worker.
-       gp := node.gp.ptr()
-       casgstatus(gp, _Gwaiting, _Grunnable)
-       if trace.enabled {
-               traceGoUnpark(gp, 0)
-       }
-       return gp
-}
-
 // pollFractionalWorkerExit reports whether a fractional mark worker
 // should self-preempt. It assumes it is called from the fractional
 // worker.
@@ -811,203 +285,6 @@ func pollFractionalWorkerExit() bool {
        return float64(selfTime)/float64(delta) > 1.2*gcController.fractionalUtilizationGoal
 }
 
-// gcSetTriggerRatio sets the trigger ratio and updates everything
-// derived from it: the absolute trigger, the heap goal, mark pacing,
-// and sweep pacing.
-//
-// This can be called any time. If GC is the in the middle of a
-// concurrent phase, it will adjust the pacing of that phase.
-//
-// This depends on gcpercent, memstats.heap_marked, and
-// memstats.heap_live. These must be up to date.
-//
-// mheap_.lock must be held or the world must be stopped.
-func gcSetTriggerRatio(triggerRatio float64) {
-       assertWorldStoppedOrLockHeld(&mheap_.lock)
-
-       // Compute the next GC goal, which is when the allocated heap
-       // has grown by GOGC/100 over the heap marked by the last
-       // cycle.
-       goal := ^uint64(0)
-       if gcpercent >= 0 {
-               goal = memstats.heap_marked + memstats.heap_marked*uint64(gcpercent)/100
-       }
-
-       // Set the trigger ratio, capped to reasonable bounds.
-       if gcpercent >= 0 {
-               scalingFactor := float64(gcpercent) / 100
-               // Ensure there's always a little margin so that the
-               // mutator assist ratio isn't infinity.
-               maxTriggerRatio := 0.95 * scalingFactor
-               if triggerRatio > maxTriggerRatio {
-                       triggerRatio = maxTriggerRatio
-               }
-
-               // If we let triggerRatio go too low, then if the application
-               // is allocating very rapidly we might end up in a situation
-               // where we're allocating black during a nearly always-on GC.
-               // The result of this is a growing heap and ultimately an
-               // increase in RSS. By capping us at a point >0, we're essentially
-               // saying that we're OK using more CPU during the GC to prevent
-               // this growth in RSS.
-               //
-               // The current constant was chosen empirically: given a sufficiently
-               // fast/scalable allocator with 48 Ps that could drive the trigger ratio
-               // to <0.05, this constant causes applications to retain the same peak
-               // RSS compared to not having this allocator.
-               minTriggerRatio := 0.6 * scalingFactor
-               if triggerRatio < minTriggerRatio {
-                       triggerRatio = minTriggerRatio
-               }
-       } else if triggerRatio < 0 {
-               // gcpercent < 0, so just make sure we're not getting a negative
-               // triggerRatio. This case isn't expected to happen in practice,
-               // and doesn't really matter because if gcpercent < 0 then we won't
-               // ever consume triggerRatio further on in this function, but let's
-               // just be defensive here; the triggerRatio being negative is almost
-               // certainly undesirable.
-               triggerRatio = 0
-       }
-       memstats.triggerRatio = triggerRatio
-
-       // Compute the absolute GC trigger from the trigger ratio.
-       //
-       // We trigger the next GC cycle when the allocated heap has
-       // grown by the trigger ratio over the marked heap size.
-       trigger := ^uint64(0)
-       if gcpercent >= 0 {
-               trigger = uint64(float64(memstats.heap_marked) * (1 + triggerRatio))
-               // Don't trigger below the minimum heap size.
-               minTrigger := heapminimum
-               if !isSweepDone() {
-                       // Concurrent sweep happens in the heap growth
-                       // from heap_live to gc_trigger, so ensure
-                       // that concurrent sweep has some heap growth
-                       // in which to perform sweeping before we
-                       // start the next GC cycle.
-                       sweepMin := atomic.Load64(&memstats.heap_live) + sweepMinHeapDistance
-                       if sweepMin > minTrigger {
-                               minTrigger = sweepMin
-                       }
-               }
-               if trigger < minTrigger {
-                       trigger = minTrigger
-               }
-               if int64(trigger) < 0 {
-                       print("runtime: next_gc=", memstats.next_gc, " heap_marked=", memstats.heap_marked, " heap_live=", memstats.heap_live, " initialHeapLive=", work.initialHeapLive, "triggerRatio=", triggerRatio, " minTrigger=", minTrigger, "\n")
-                       throw("gc_trigger underflow")
-               }
-               if trigger > goal {
-                       // The trigger ratio is always less than GOGC/100, but
-                       // other bounds on the trigger may have raised it.
-                       // Push up the goal, too.
-                       goal = trigger
-               }
-       }
-
-       // Commit to the trigger and goal.
-       memstats.gc_trigger = trigger
-       atomic.Store64(&memstats.next_gc, goal)
-       if trace.enabled {
-               traceNextGC()
-       }
-
-       // Update mark pacing.
-       if gcphase != _GCoff {
-               gcController.revise()
-       }
-
-       // Update sweep pacing.
-       if isSweepDone() {
-               mheap_.sweepPagesPerByte = 0
-       } else {
-               // Concurrent sweep needs to sweep all of the in-use
-               // pages by the time the allocated heap reaches the GC
-               // trigger. Compute the ratio of in-use pages to sweep
-               // per byte allocated, accounting for the fact that
-               // some might already be swept.
-               heapLiveBasis := atomic.Load64(&memstats.heap_live)
-               heapDistance := int64(trigger) - int64(heapLiveBasis)
-               // Add a little margin so rounding errors and
-               // concurrent sweep are less likely to leave pages
-               // unswept when GC starts.
-               heapDistance -= 1024 * 1024
-               if heapDistance < _PageSize {
-                       // Avoid setting the sweep ratio extremely high
-                       heapDistance = _PageSize
-               }
-               pagesSwept := atomic.Load64(&mheap_.pagesSwept)
-               pagesInUse := atomic.Load64(&mheap_.pagesInUse)
-               sweepDistancePages := int64(pagesInUse) - int64(pagesSwept)
-               if sweepDistancePages <= 0 {
-                       mheap_.sweepPagesPerByte = 0
-               } else {
-                       mheap_.sweepPagesPerByte = float64(sweepDistancePages) / float64(heapDistance)
-                       mheap_.sweepHeapLiveBasis = heapLiveBasis
-                       // Write pagesSweptBasis last, since this
-                       // signals concurrent sweeps to recompute
-                       // their debt.
-                       atomic.Store64(&mheap_.pagesSweptBasis, pagesSwept)
-               }
-       }
-
-       gcPaceScavenger()
-}
-
-// gcEffectiveGrowthRatio returns the current effective heap growth
-// ratio (GOGC/100) based on heap_marked from the previous GC and
-// next_gc for the current GC.
-//
-// This may differ from gcpercent/100 because of various upper and
-// lower bounds on gcpercent. For example, if the heap is smaller than
-// heapminimum, this can be higher than gcpercent/100.
-//
-// mheap_.lock must be held or the world must be stopped.
-func gcEffectiveGrowthRatio() float64 {
-       assertWorldStoppedOrLockHeld(&mheap_.lock)
-
-       egogc := float64(atomic.Load64(&memstats.next_gc)-memstats.heap_marked) / float64(memstats.heap_marked)
-       if egogc < 0 {
-               // Shouldn't happen, but just in case.
-               egogc = 0
-       }
-       return egogc
-}
-
-// gcGoalUtilization is the goal CPU utilization for
-// marking as a fraction of GOMAXPROCS.
-const gcGoalUtilization = 0.30
-
-// gcBackgroundUtilization is the fixed CPU utilization for background
-// marking. It must be <= gcGoalUtilization. The difference between
-// gcGoalUtilization and gcBackgroundUtilization will be made up by
-// mark assists. The scheduler will aim to use within 50% of this
-// goal.
-//
-// Setting this to < gcGoalUtilization avoids saturating the trigger
-// feedback controller when there are no assists, which allows it to
-// better control CPU and heap growth. However, the larger the gap,
-// the more mutator assists are expected to happen, which impact
-// mutator latency.
-const gcBackgroundUtilization = 0.25
-
-// gcCreditSlack is the amount of scan work credit that can
-// accumulate locally before updating gcController.scanWork and,
-// optionally, gcController.bgScanCredit. Lower values give a more
-// accurate assist ratio and make it more likely that assists will
-// successfully steal background credit. Higher values reduce memory
-// contention.
-const gcCreditSlack = 2000
-
-// gcAssistTimeSlack is the nanoseconds of mutator assist time that
-// can accumulate on a P before updating gcController.assistTime.
-const gcAssistTimeSlack = 5000
-
-// gcOverAssistWork determines how many extra units of scan work a GC
-// assist does when an assist happens. This amortizes the cost of an
-// assist by pre-paying for this many bytes of future allocations.
-const gcOverAssistWork = 64 << 10
-
 var work struct {
        full  lfstack          // lock-free list of full blocks workbuf
        empty lfstack          // lock-free list of empty blocks workbuf
@@ -1050,9 +327,11 @@ var work struct {
        nwait  uint32
 
        // Number of roots of various root types. Set by gcMarkRootPrepare.
-       nFlushCacheRoots                    int
        nDataRoots, nSpanRoots, nStackRoots int
 
+       // Base indexes of each root type. Set by gcMarkRootPrepare.
+       baseData, baseSpans, baseStacks, baseEnd uint32
+
        // Each type of GC state transition is protected by a lock.
        // Since multiple threads can simultaneously detect the state
        // transition condition, any thread that detects a transition
@@ -1086,7 +365,7 @@ var work struct {
        // program started if debug.gctrace > 0.
        totaltime int64
 
-       // initialHeapLive is the value of memstats.heap_live at the
+       // initialHeapLive is the value of gcController.heapLive at the
        // beginning of this GC cycle.
        initialHeapLive uint64
 
@@ -1183,7 +462,7 @@ func GC() {
        // First, wait for sweeping to finish. (We know there are no
        // more spans on the sweep queue, but we may be concurrently
        // sweeping spans, so we have to wait.)
-       for atomic.Load(&work.cycles) == n+1 && atomic.Load(&mheap_.sweepers) != 0 {
+       for atomic.Load(&work.cycles) == n+1 && !isSweepDone() {
                Gosched()
        }
 
@@ -1267,13 +546,13 @@ func (t gcTrigger) test() bool {
        }
        switch t.kind {
        case gcTriggerHeap:
-               // Non-atomic access to heap_live for performance. If
+               // Non-atomic access to gcController.heapLive for performance. If
                // we are going to trigger on this, this thread just
-               // atomically wrote heap_live anyway and we'll see our
+               // atomically wrote gcController.heapLive anyway and we'll see our
                // own write.
-               return memstats.heap_live >= memstats.gc_trigger
+               return gcController.heapLive >= gcController.trigger
        case gcTriggerTime:
-               if gcpercent < 0 {
+               if gcController.gcPercent < 0 {
                        return false
                }
                lastgc := int64(atomic.Load64(&memstats.last_gc_nanotime))
@@ -1367,7 +646,7 @@ func gcStart(trigger gcTrigger) {
                // so it can't be more than ncpu, even if GOMAXPROCS is.
                work.stwprocs = ncpu
        }
-       work.heap0 = atomic.Load64(&memstats.heap_live)
+       work.heap0 = atomic.Load64(&gcController.heapLive)
        work.pauseNS = 0
        work.mode = mode
 
@@ -1390,7 +669,7 @@ func gcStart(trigger gcTrigger) {
        work.cycles++
 
        gcController.startCycle()
-       work.heapGoal = memstats.next_gc
+       work.heapGoal = gcController.heapGoal
 
        // In STW mode, disable scheduling of user Gs. This may also
        // disable scheduling of this goroutine, so it may block as
@@ -1619,7 +898,7 @@ top:
        // endCycle depends on all gcWork cache stats being flushed.
        // The termination algorithm above ensured that up to
        // allocations since the ragged barrier.
-       nextTriggerRatio := gcController.endCycle()
+       nextTriggerRatio := gcController.endCycle(work.userForced)
 
        // Perform mark termination. This will restart the world.
        gcMarkTermination(nextTriggerRatio)
@@ -1631,7 +910,7 @@ func gcMarkTermination(nextTriggerRatio float64) {
        // Start marktermination (write barrier remains enabled for now).
        setGCPhase(_GCmarktermination)
 
-       work.heap1 = memstats.heap_live
+       work.heap1 = gcController.heapLive
        startTime := nanotime()
 
        mp := acquirem()
@@ -1693,12 +972,12 @@ func gcMarkTermination(nextTriggerRatio float64) {
                throw("gc done but gcphase != _GCoff")
        }
 
-       // Record next_gc and heap_inuse for scavenger.
-       memstats.last_next_gc = memstats.next_gc
+       // Record heapGoal and heap_inuse for scavenger.
+       gcController.lastHeapGoal = gcController.heapGoal
        memstats.last_heap_inuse = memstats.heap_inuse
 
        // Update GC trigger and pacing for the next cycle.
-       gcSetTriggerRatio(nextTriggerRatio)
+       gcController.commit(nextTriggerRatio)
 
        // Update timing memstats
        now := nanotime()
@@ -1745,6 +1024,13 @@ func gcMarkTermination(nextTriggerRatio float64) {
        // so events don't leak into the wrong cycle.
        mProf_NextCycle()
 
+       // There may be stale spans in mcaches that need to be swept.
+       // Those aren't tracked in any sweep lists, so we need to
+       // count them against sweep completion until we ensure all
+       // those spans have been forced out.
+       sl := newSweepLocker()
+       sl.blockCompletion()
+
        systemstack(func() { startTheWorldWithSema(true) })
 
        // Flush the heap profile so we can start a new cycle next GC.
@@ -1765,6 +1051,9 @@ func gcMarkTermination(nextTriggerRatio float64) {
                        _p_.mcache.prepareForSweep()
                })
        })
+       // Now that we've swept stale spans in mcaches, they don't
+       // count against unswept spans.
+       sl.dispose()
 
        // Print gctrace before dropping worldsema. As soon as we drop
        // worldsema another cycle could start and smash the stats
@@ -1986,15 +1275,11 @@ func gcBgMarkWorker() {
                                        // everything out of the run
                                        // queue so it can run
                                        // somewhere else.
-                                       lock(&sched.lock)
-                                       for {
-                                               gp, _ := runqget(pp)
-                                               if gp == nil {
-                                                       break
-                                               }
-                                               globrunqput(gp)
+                                       if drainQ, n := runqdrain(pp); n > 0 {
+                                               lock(&sched.lock)
+                                               globrunqputbatch(&drainQ, int32(n))
+                                               unlock(&sched.lock)
                                        }
-                                       unlock(&sched.lock)
                                }
                                // Go back to draining, this time
                                // without preemption.
@@ -2068,7 +1353,7 @@ func gcMarkWorkAvailable(p *p) bool {
 // gcMark runs the mark (or, for concurrent GC, mark termination)
 // All gcWork caches must be empty.
 // STW is in effect at this point.
-func gcMark(start_time int64) {
+func gcMark(startTime int64) {
        if debug.allocfreetrace > 0 {
                tracegc()
        }
@@ -2076,7 +1361,7 @@ func gcMark(start_time int64) {
        if gcphase != _GCmarktermination {
                throw("in gcMark expecting to see gcphase as _GCmarktermination")
        }
-       work.tstart = start_time
+       work.tstart = startTime
 
        // Check that there's no marking work remaining.
        if work.full != 0 || work.markrootNext < work.markrootJobs {
@@ -2138,25 +1423,25 @@ func gcMark(start_time int64) {
        }
 
        // Update the marked heap stat.
-       memstats.heap_marked = work.bytesMarked
+       gcController.heapMarked = work.bytesMarked
 
        // Flush scanAlloc from each mcache since we're about to modify
-       // heap_scan directly. If we were to flush this later, then scanAlloc
+       // heapScan directly. If we were to flush this later, then scanAlloc
        // might have incorrect information.
        for _, p := range allp {
                c := p.mcache
                if c == nil {
                        continue
                }
-               memstats.heap_scan += uint64(c.scanAlloc)
+               gcController.heapScan += uint64(c.scanAlloc)
                c.scanAlloc = 0
        }
 
        // Update other GC heap size stats. This must happen after
        // cachestats (which flushes local statistics to these) and
-       // flushallmcaches (which modifies heap_live).
-       memstats.heap_live = work.bytesMarked
-       memstats.heap_scan = uint64(gcController.scanWork)
+       // flushallmcaches (which modifies gcController.heapLive).
+       gcController.heapLive = work.bytesMarked
+       gcController.heapScan = uint64(gcController.scanWork)
 
        if trace.enabled {
                traceHeapAlloc()
@@ -2178,7 +1463,7 @@ func gcSweep(mode gcMode) {
 
        lock(&mheap_.lock)
        mheap_.sweepgen += 2
-       mheap_.sweepdone = 0
+       mheap_.sweepDrained = 0
        mheap_.pagesSwept = 0
        mheap_.sweepArenas = mheap_.allArenas
        mheap_.reclaimIndex = 0
@@ -2229,14 +1514,12 @@ func gcSweep(mode gcMode) {
 //
 //go:systemstack
 func gcResetMarkState() {
-       // This may be called during a concurrent phase, so make sure
+       // This may be called during a concurrent phase, so lock to make sure
        // allgs doesn't change.
-       lock(&allglock)
-       for _, gp := range allgs {
+       forEachG(func(gp *g) {
                gp.gcscandone = false // set to true in gcphasework
                gp.gcAssistBytes = 0
-       }
-       unlock(&allglock)
+       })
 
        // Clear page marks. This is just 1MB per 64GB of heap, so the
        // time here is pretty trivial.
@@ -2251,7 +1534,7 @@ func gcResetMarkState() {
        }
 
        work.bytesMarked = 0
-       work.initialHeapLive = atomic.Load64(&memstats.heap_live)
+       work.initialHeapLive = atomic.Load64(&gcController.heapLive)
 }
 
 // Hooks for other packages
@@ -2334,3 +1617,95 @@ func fmtNSAsMS(buf []byte, ns uint64) []byte {
        }
        return itoaDiv(buf, x, dec)
 }
+
+// Helpers for testing GC.
+
+// gcTestIsReachable performs a GC and returns a bit set where bit i
+// is set if ptrs[i] is reachable.
+func gcTestIsReachable(ptrs ...unsafe.Pointer) (mask uint64) {
+       // This takes the pointers as unsafe.Pointers in order to keep
+       // them live long enough for us to attach specials. After
+       // that, we drop our references to them.
+
+       if len(ptrs) > 64 {
+               panic("too many pointers for uint64 mask")
+       }
+
+       // Block GC while we attach specials and drop our references
+       // to ptrs. Otherwise, if a GC is in progress, it could mark
+       // them reachable via this function before we have a chance to
+       // drop them.
+       semacquire(&gcsema)
+
+       // Create reachability specials for ptrs.
+       specials := make([]*specialReachable, len(ptrs))
+       for i, p := range ptrs {
+               lock(&mheap_.speciallock)
+               s := (*specialReachable)(mheap_.specialReachableAlloc.alloc())
+               unlock(&mheap_.speciallock)
+               s.special.kind = _KindSpecialReachable
+               if !addspecial(p, &s.special) {
+                       throw("already have a reachable special (duplicate pointer?)")
+               }
+               specials[i] = s
+               // Make sure we don't retain ptrs.
+               ptrs[i] = nil
+       }
+
+       semrelease(&gcsema)
+
+       // Force a full GC and sweep.
+       GC()
+
+       // Process specials.
+       for i, s := range specials {
+               if !s.done {
+                       printlock()
+                       println("runtime: object", i, "was not swept")
+                       throw("IsReachable failed")
+               }
+               if s.reachable {
+                       mask |= 1 << i
+               }
+               lock(&mheap_.speciallock)
+               mheap_.specialReachableAlloc.free(unsafe.Pointer(s))
+               unlock(&mheap_.speciallock)
+       }
+
+       return mask
+}
+
+// onCurrentStack reports whether the argument is on the current stack.
+// It is implemented in C.
+func onCurrentStack(uintptr) bool
+
+// getBSS returns the start of the BSS section.
+// It is implemented in C.
+func getBSS() uintptr
+
+// gcTestPointerClass returns the category of what p points to, one of:
+// "heap", "stack", "data", "bss", "other". This is useful for checking
+// that a test is doing what it's intended to do.
+//
+// This is nosplit simply to avoid extra pointer shuffling that may
+// complicate a test.
+//
+//go:nosplit
+func gcTestPointerClass(p unsafe.Pointer) string {
+       p2 := uintptr(noescape(p))
+       if onCurrentStack(p2) {
+               return "stack"
+       }
+       if base, _, _ := findObject(p2, 0, 0, false); base != 0 {
+               return "heap"
+       }
+       bss := getBSS()
+       if p2 >= getText() && p2 < bss {
+               return "data"
+       }
+       if p2 >= bss && p2 < getEnd() {
+               return "bss"
+       }
+       KeepAlive(p)
+       return "other"
+}
index e5581255bb9acb0c6f00ccf0795b06623c4a05b4..f6e1a14b5e9f45bf39ba829b8ecf862d83a0b0ed 100644 (file)
@@ -56,8 +56,6 @@ const (
 func gcMarkRootPrepare() {
        assertWorldStopped()
 
-       work.nFlushCacheRoots = 0
-
        work.nDataRoots = 0
 
        // Only scan globals once per cycle; preferably concurrently.
@@ -91,7 +89,13 @@ func gcMarkRootPrepare() {
        work.nStackRoots = int(atomic.Loaduintptr(&allglen))
 
        work.markrootNext = 0
-       work.markrootJobs = uint32(fixedRootCount + work.nFlushCacheRoots + work.nDataRoots + work.nSpanRoots + work.nStackRoots)
+       work.markrootJobs = uint32(fixedRootCount + work.nDataRoots + work.nSpanRoots + work.nStackRoots)
+
+       // Calculate base indexes of each root type
+       work.baseData = uint32(fixedRootCount)
+       work.baseSpans = work.baseData + uint32(work.nDataRoots)
+       work.baseStacks = work.baseSpans + uint32(work.nSpanRoots)
+       work.baseEnd = work.baseStacks + uint32(work.nStackRoots)
 }
 
 // gcMarkRootCheck checks that all roots have been scanned. It is
@@ -102,23 +106,26 @@ func gcMarkRootCheck() {
                throw("left over markroot jobs")
        }
 
-       lock(&allglock)
        // Check that stacks have been scanned.
-       var gp *g
-       for i := 0; i < work.nStackRoots; i++ {
-               gp = allgs[i]
+       //
+       // We only check the first nStackRoots Gs that we should have scanned.
+       // Since we don't care about newer Gs (see comment in
+       // gcMarkRootPrepare), no locking is required.
+       i := 0
+       forEachGRace(func(gp *g) {
+               if i >= work.nStackRoots {
+                       return
+               }
+
                if !gp.gcscandone {
-                       goto fail
+                       println("gp", gp, "goid", gp.goid,
+                               "status", readgstatus(gp),
+                               "gcscandone", gp.gcscandone)
+                       throw("scan missed a g")
                }
-       }
-       unlock(&allglock)
-       return
-
-fail:
-       println("gp", gp, "goid", gp.goid,
-               "status", readgstatus(gp),
-               "gcscandone", gp.gcscandone)
-       throw("scan missed a g")
+
+               i++
+       })
 }
 
 // ptrmask for an allocation containing a single pointer.
@@ -132,22 +139,11 @@ var oneptrmask = [...]uint8{1}
 //
 //go:nowritebarrier
 func markroot(gcw *gcWork, i uint32) {
-       // TODO(austin): This is a bit ridiculous. Compute and store
-       // the bases in gcMarkRootPrepare instead of the counts.
-       baseFlushCache := uint32(fixedRootCount)
-       baseData := baseFlushCache + uint32(work.nFlushCacheRoots)
-       baseSpans := baseData + uint32(work.nDataRoots)
-       baseStacks := baseSpans + uint32(work.nSpanRoots)
-       end := baseStacks + uint32(work.nStackRoots)
-
        // Note: if you add a case here, please also update heapdump.go:dumproots.
        switch {
-       case baseFlushCache <= i && i < baseData:
-               flushmcache(int(i - baseFlushCache))
-
-       case baseData <= i && i < baseSpans:
+       case work.baseData <= i && i < work.baseSpans:
                roots := gcRoots
-               c := baseData
+               c := work.baseData
                for roots != nil {
                        if i == c {
                                markrootBlock(roots, gcw)
@@ -166,15 +162,18 @@ func markroot(gcw *gcWork, i uint32) {
        case i == fixedRootFreeGStacks:
                // FIXME: We don't do this for gccgo.
 
-       case baseSpans <= i && i < baseStacks:
+       case work.baseSpans <= i && i < work.baseStacks:
                // mark mspan.specials
-               markrootSpans(gcw, int(i-baseSpans))
+               markrootSpans(gcw, int(i-work.baseSpans))
 
        default:
                // the rest is scanning goroutine stacks
                var gp *g
-               if baseStacks <= i && i < end {
-                       gp = allgs[i-baseStacks]
+               if work.baseStacks <= i && i < work.baseEnd {
+                       // N.B. Atomic read of allglen in gcMarkRootPrepare
+                       // acts as a barrier to ensure that allgs must be large
+                       // enough to contain all relevant Gs.
+                       gp = allgs[i-work.baseStacks]
                } else {
                        throw("markroot: bad index")
                }
@@ -1051,12 +1050,7 @@ func scanobject(b uintptr, gcw *gcWork) {
        }
 
        var i uintptr
-       for i = 0; i < n; i += sys.PtrSize {
-               // Find bits for this word.
-               if i != 0 {
-                       // Avoid needless hbits.next() on last iteration.
-                       hbits = hbits.next()
-               }
+       for i = 0; i < n; i, hbits = i+sys.PtrSize, hbits.next() {
                // Load bits once. See CL 22712 and issue 16973 for discussion.
                bits := hbits.bits()
                if bits&bitScan == 0 {
diff --git a/libgo/go/runtime/mgcpacer.go b/libgo/go/runtime/mgcpacer.go
new file mode 100644 (file)
index 0000000..8a66920
--- /dev/null
@@ -0,0 +1,848 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import (
+       "internal/cpu"
+       "runtime/internal/atomic"
+       "unsafe"
+)
+
+const (
+       // gcGoalUtilization is the goal CPU utilization for
+       // marking as a fraction of GOMAXPROCS.
+       gcGoalUtilization = 0.30
+
+       // gcBackgroundUtilization is the fixed CPU utilization for background
+       // marking. It must be <= gcGoalUtilization. The difference between
+       // gcGoalUtilization and gcBackgroundUtilization will be made up by
+       // mark assists. The scheduler will aim to use within 50% of this
+       // goal.
+       //
+       // Setting this to < gcGoalUtilization avoids saturating the trigger
+       // feedback controller when there are no assists, which allows it to
+       // better control CPU and heap growth. However, the larger the gap,
+       // the more mutator assists are expected to happen, which impact
+       // mutator latency.
+       gcBackgroundUtilization = 0.25
+
+       // gcCreditSlack is the amount of scan work credit that can
+       // accumulate locally before updating gcController.scanWork and,
+       // optionally, gcController.bgScanCredit. Lower values give a more
+       // accurate assist ratio and make it more likely that assists will
+       // successfully steal background credit. Higher values reduce memory
+       // contention.
+       gcCreditSlack = 2000
+
+       // gcAssistTimeSlack is the nanoseconds of mutator assist time that
+       // can accumulate on a P before updating gcController.assistTime.
+       gcAssistTimeSlack = 5000
+
+       // gcOverAssistWork determines how many extra units of scan work a GC
+       // assist does when an assist happens. This amortizes the cost of an
+       // assist by pre-paying for this many bytes of future allocations.
+       gcOverAssistWork = 64 << 10
+
+       // defaultHeapMinimum is the value of heapMinimum for GOGC==100.
+       defaultHeapMinimum = 4 << 20
+)
+
+func init() {
+       if offset := unsafe.Offsetof(gcController.heapLive); offset%8 != 0 {
+               println(offset)
+               throw("gcController.heapLive not aligned to 8 bytes")
+       }
+}
+
+// gcController implements the GC pacing controller that determines
+// when to trigger concurrent garbage collection and how much marking
+// work to do in mutator assists and background marking.
+//
+// It uses a feedback control algorithm to adjust the gcController.trigger
+// trigger based on the heap growth and GC CPU utilization each cycle.
+// This algorithm optimizes for heap growth to match GOGC and for CPU
+// utilization between assist and background marking to be 25% of
+// GOMAXPROCS. The high-level design of this algorithm is documented
+// at https://golang.org/s/go15gcpacing.
+//
+// All fields of gcController are used only during a single mark
+// cycle.
+var gcController gcControllerState
+
+type gcControllerState struct {
+       // Initialized from $GOGC. GOGC=off means no GC.
+       gcPercent int32
+
+       _ uint32 // padding so following 64-bit values are 8-byte aligned
+
+       // heapMinimum is the minimum heap size at which to trigger GC.
+       // For small heaps, this overrides the usual GOGC*live set rule.
+       //
+       // When there is a very small live set but a lot of allocation, simply
+       // collecting when the heap reaches GOGC*live results in many GC
+       // cycles and high total per-GC overhead. This minimum amortizes this
+       // per-GC overhead while keeping the heap reasonably small.
+       //
+       // During initialization this is set to 4MB*GOGC/100. In the case of
+       // GOGC==0, this will set heapMinimum to 0, resulting in constant
+       // collection even when the heap size is small, which is useful for
+       // debugging.
+       heapMinimum uint64
+
+       // triggerRatio is the heap growth ratio that triggers marking.
+       //
+       // E.g., if this is 0.6, then GC should start when the live
+       // heap has reached 1.6 times the heap size marked by the
+       // previous cycle. This should be ≤ GOGC/100 so the trigger
+       // heap size is less than the goal heap size. This is set
+       // during mark termination for the next cycle's trigger.
+       //
+       // Protected by mheap_.lock or a STW.
+       triggerRatio float64
+
+       // trigger is the heap size that triggers marking.
+       //
+       // When heapLive ≥ trigger, the mark phase will start.
+       // This is also the heap size by which proportional sweeping
+       // must be complete.
+       //
+       // This is computed from triggerRatio during mark termination
+       // for the next cycle's trigger.
+       //
+       // Protected by mheap_.lock or a STW.
+       trigger uint64
+
+       // heapGoal is the goal heapLive for when next GC ends.
+       // Set to ^uint64(0) if disabled.
+       //
+       // Read and written atomically, unless the world is stopped.
+       heapGoal uint64
+
+       // lastHeapGoal is the value of heapGoal for the previous GC.
+       // Note that this is distinct from the last value heapGoal had,
+       // because it could change if e.g. gcPercent changes.
+       //
+       // Read and written with the world stopped or with mheap_.lock held.
+       lastHeapGoal uint64
+
+       // heapLive is the number of bytes considered live by the GC.
+       // That is: retained by the most recent GC plus allocated
+       // since then. heapLive ≤ memstats.heapAlloc, since heapAlloc includes
+       // unmarked objects that have not yet been swept (and hence goes up as we
+       // allocate and down as we sweep) while heapLive excludes these
+       // objects (and hence only goes up between GCs).
+       //
+       // This is updated atomically without locking. To reduce
+       // contention, this is updated only when obtaining a span from
+       // an mcentral and at this point it counts all of the
+       // unallocated slots in that span (which will be allocated
+       // before that mcache obtains another span from that
+       // mcentral). Hence, it slightly overestimates the "true" live
+       // heap size. It's better to overestimate than to
+       // underestimate because 1) this triggers the GC earlier than
+       // necessary rather than potentially too late and 2) this
+       // leads to a conservative GC rate rather than a GC rate that
+       // is potentially too low.
+       //
+       // Reads should likewise be atomic (or during STW).
+       //
+       // Whenever this is updated, call traceHeapAlloc() and
+       // this gcControllerState's revise() method.
+       heapLive uint64
+
+       // heapScan is the number of bytes of "scannable" heap. This
+       // is the live heap (as counted by heapLive), but omitting
+       // no-scan objects and no-scan tails of objects.
+       //
+       // Whenever this is updated, call this gcControllerState's
+       // revise() method.
+       //
+       // Read and written atomically or with the world stopped.
+       heapScan uint64
+
+       // heapMarked is the number of bytes marked by the previous
+       // GC. After mark termination, heapLive == heapMarked, but
+       // unlike heapLive, heapMarked does not change until the
+       // next mark termination.
+       heapMarked uint64
+
+       // scanWork is the total scan work performed this cycle. This
+       // is updated atomically during the cycle. Updates occur in
+       // bounded batches, since it is both written and read
+       // throughout the cycle. At the end of the cycle, this is how
+       // much of the retained heap is scannable.
+       //
+       // Currently this is the bytes of heap scanned. For most uses,
+       // this is an opaque unit of work, but for estimation the
+       // definition is important.
+       scanWork int64
+
+       // bgScanCredit is the scan work credit accumulated by the
+       // concurrent background scan. This credit is accumulated by
+       // the background scan and stolen by mutator assists. This is
+       // updated atomically. Updates occur in bounded batches, since
+       // it is both written and read throughout the cycle.
+       bgScanCredit int64
+
+       // assistTime is the nanoseconds spent in mutator assists
+       // during this cycle. This is updated atomically. Updates
+       // occur in bounded batches, since it is both written and read
+       // throughout the cycle.
+       assistTime int64
+
+       // dedicatedMarkTime is the nanoseconds spent in dedicated
+       // mark workers during this cycle. This is updated atomically
+       // at the end of the concurrent mark phase.
+       dedicatedMarkTime int64
+
+       // fractionalMarkTime is the nanoseconds spent in the
+       // fractional mark worker during this cycle. This is updated
+       // atomically throughout the cycle and will be up-to-date if
+       // the fractional mark worker is not currently running.
+       fractionalMarkTime int64
+
+       // idleMarkTime is the nanoseconds spent in idle marking
+       // during this cycle. This is updated atomically throughout
+       // the cycle.
+       idleMarkTime int64
+
+       // markStartTime is the absolute start time in nanoseconds
+       // that assists and background mark workers started.
+       markStartTime int64
+
+       // dedicatedMarkWorkersNeeded is the number of dedicated mark
+       // workers that need to be started. This is computed at the
+       // beginning of each cycle and decremented atomically as
+       // dedicated mark workers get started.
+       dedicatedMarkWorkersNeeded int64
+
+       // assistWorkPerByte is the ratio of scan work to allocated
+       // bytes that should be performed by mutator assists. This is
+       // computed at the beginning of each cycle and updated every
+       // time heapScan is updated.
+       //
+       // Stored as a uint64, but it's actually a float64. Use
+       // float64frombits to get the value.
+       //
+       // Read and written atomically.
+       assistWorkPerByte uint64
+
+       // assistBytesPerWork is 1/assistWorkPerByte.
+       //
+       // Stored as a uint64, but it's actually a float64. Use
+       // float64frombits to get the value.
+       //
+       // Read and written atomically.
+       //
+       // Note that because this is read and written independently
+       // from assistWorkPerByte users may notice a skew between
+       // the two values, and such a state should be safe.
+       assistBytesPerWork uint64
+
+       // fractionalUtilizationGoal is the fraction of wall clock
+       // time that should be spent in the fractional mark worker on
+       // each P that isn't running a dedicated worker.
+       //
+       // For example, if the utilization goal is 25% and there are
+       // no dedicated workers, this will be 0.25. If the goal is
+       // 25%, there is one dedicated worker, and GOMAXPROCS is 5,
+       // this will be 0.05 to make up the missing 5%.
+       //
+       // If this is zero, no fractional workers are needed.
+       fractionalUtilizationGoal float64
+
+       _ cpu.CacheLinePad
+}
+
+func (c *gcControllerState) init(gcPercent int32) {
+       c.heapMinimum = defaultHeapMinimum
+
+       // Set a reasonable initial GC trigger.
+       c.triggerRatio = 7 / 8.0
+
+       // Fake a heapMarked value so it looks like a trigger at
+       // heapMinimum is the appropriate growth from heapMarked.
+       // This will go into computing the initial GC goal.
+       c.heapMarked = uint64(float64(c.heapMinimum) / (1 + c.triggerRatio))
+
+       // This will also compute and set the GC trigger and goal.
+       c.setGCPercent(gcPercent)
+}
+
+// startCycle resets the GC controller's state and computes estimates
+// for a new GC cycle. The caller must hold worldsema and the world
+// must be stopped.
+func (c *gcControllerState) startCycle() {
+       c.scanWork = 0
+       c.bgScanCredit = 0
+       c.assistTime = 0
+       c.dedicatedMarkTime = 0
+       c.fractionalMarkTime = 0
+       c.idleMarkTime = 0
+
+       // Ensure that the heap goal is at least a little larger than
+       // the current live heap size. This may not be the case if GC
+       // start is delayed or if the allocation that pushed gcController.heapLive
+       // over trigger is large or if the trigger is really close to
+       // GOGC. Assist is proportional to this distance, so enforce a
+       // minimum distance, even if it means going over the GOGC goal
+       // by a tiny bit.
+       if c.heapGoal < c.heapLive+1024*1024 {
+               c.heapGoal = c.heapLive + 1024*1024
+       }
+
+       // Compute the background mark utilization goal. In general,
+       // this may not come out exactly. We round the number of
+       // dedicated workers so that the utilization is closest to
+       // 25%. For small GOMAXPROCS, this would introduce too much
+       // error, so we add fractional workers in that case.
+       totalUtilizationGoal := float64(gomaxprocs) * gcBackgroundUtilization
+       c.dedicatedMarkWorkersNeeded = int64(totalUtilizationGoal + 0.5)
+       utilError := float64(c.dedicatedMarkWorkersNeeded)/totalUtilizationGoal - 1
+       const maxUtilError = 0.3
+       if utilError < -maxUtilError || utilError > maxUtilError {
+               // Rounding put us more than 30% off our goal. With
+               // gcBackgroundUtilization of 25%, this happens for
+               // GOMAXPROCS<=3 or GOMAXPROCS=6. Enable fractional
+               // workers to compensate.
+               if float64(c.dedicatedMarkWorkersNeeded) > totalUtilizationGoal {
+                       // Too many dedicated workers.
+                       c.dedicatedMarkWorkersNeeded--
+               }
+               c.fractionalUtilizationGoal = (totalUtilizationGoal - float64(c.dedicatedMarkWorkersNeeded)) / float64(gomaxprocs)
+       } else {
+               c.fractionalUtilizationGoal = 0
+       }
+
+       // In STW mode, we just want dedicated workers.
+       if debug.gcstoptheworld > 0 {
+               c.dedicatedMarkWorkersNeeded = int64(gomaxprocs)
+               c.fractionalUtilizationGoal = 0
+       }
+
+       // Clear per-P state
+       for _, p := range allp {
+               p.gcAssistTime = 0
+               p.gcFractionalMarkTime = 0
+       }
+
+       // Compute initial values for controls that are updated
+       // throughout the cycle.
+       c.revise()
+
+       if debug.gcpacertrace > 0 {
+               assistRatio := float64frombits(atomic.Load64(&c.assistWorkPerByte))
+               print("pacer: assist ratio=", assistRatio,
+                       " (scan ", gcController.heapScan>>20, " MB in ",
+                       work.initialHeapLive>>20, "->",
+                       c.heapGoal>>20, " MB)",
+                       " workers=", c.dedicatedMarkWorkersNeeded,
+                       "+", c.fractionalUtilizationGoal, "\n")
+       }
+}
+
+// revise updates the assist ratio during the GC cycle to account for
+// improved estimates. This should be called whenever gcController.heapScan,
+// gcController.heapLive, or gcController.heapGoal is updated. It is safe to
+// call concurrently, but it may race with other calls to revise.
+//
+// The result of this race is that the two assist ratio values may not line
+// up or may be stale. In practice this is OK because the assist ratio
+// moves slowly throughout a GC cycle, and the assist ratio is a best-effort
+// heuristic anyway. Furthermore, no part of the heuristic depends on
+// the two assist ratio values being exact reciprocals of one another, since
+// the two values are used to convert values from different sources.
+//
+// The worst case result of this raciness is that we may miss a larger shift
+// in the ratio (say, if we decide to pace more aggressively against the
+// hard heap goal) but even this "hard goal" is best-effort (see #40460).
+// The dedicated GC should ensure we don't exceed the hard goal by too much
+// in the rare case we do exceed it.
+//
+// It should only be called when gcBlackenEnabled != 0 (because this
+// is when assists are enabled and the necessary statistics are
+// available).
+func (c *gcControllerState) revise() {
+       gcPercent := c.gcPercent
+       if gcPercent < 0 {
+               // If GC is disabled but we're running a forced GC,
+               // act like GOGC is huge for the below calculations.
+               gcPercent = 100000
+       }
+       live := atomic.Load64(&c.heapLive)
+       scan := atomic.Load64(&c.heapScan)
+       work := atomic.Loadint64(&c.scanWork)
+
+       // Assume we're under the soft goal. Pace GC to complete at
+       // heapGoal assuming the heap is in steady-state.
+       heapGoal := int64(atomic.Load64(&c.heapGoal))
+
+       // Compute the expected scan work remaining.
+       //
+       // This is estimated based on the expected
+       // steady-state scannable heap. For example, with
+       // GOGC=100, only half of the scannable heap is
+       // expected to be live, so that's what we target.
+       //
+       // (This is a float calculation to avoid overflowing on
+       // 100*heapScan.)
+       scanWorkExpected := int64(float64(scan) * 100 / float64(100+gcPercent))
+
+       if int64(live) > heapGoal || work > scanWorkExpected {
+               // We're past the soft goal, or we've already done more scan
+               // work than we expected. Pace GC so that in the worst case it
+               // will complete by the hard goal.
+               const maxOvershoot = 1.1
+               heapGoal = int64(float64(heapGoal) * maxOvershoot)
+
+               // Compute the upper bound on the scan work remaining.
+               scanWorkExpected = int64(scan)
+       }
+
+       // Compute the remaining scan work estimate.
+       //
+       // Note that we currently count allocations during GC as both
+       // scannable heap (heapScan) and scan work completed
+       // (scanWork), so allocation will change this difference
+       // slowly in the soft regime and not at all in the hard
+       // regime.
+       scanWorkRemaining := scanWorkExpected - work
+       if scanWorkRemaining < 1000 {
+               // We set a somewhat arbitrary lower bound on
+               // remaining scan work since if we aim a little high,
+               // we can miss by a little.
+               //
+               // We *do* need to enforce that this is at least 1,
+               // since marking is racy and double-scanning objects
+               // may legitimately make the remaining scan work
+               // negative, even in the hard goal regime.
+               scanWorkRemaining = 1000
+       }
+
+       // Compute the heap distance remaining.
+       heapRemaining := heapGoal - int64(live)
+       if heapRemaining <= 0 {
+               // This shouldn't happen, but if it does, avoid
+               // dividing by zero or setting the assist negative.
+               heapRemaining = 1
+       }
+
+       // Compute the mutator assist ratio so by the time the mutator
+       // allocates the remaining heap bytes up to heapGoal, it will
+       // have done (or stolen) the remaining amount of scan work.
+       // Note that the assist ratio values are updated atomically
+       // but not together. This means there may be some degree of
+       // skew between the two values. This is generally OK as the
+       // values shift relatively slowly over the course of a GC
+       // cycle.
+       assistWorkPerByte := float64(scanWorkRemaining) / float64(heapRemaining)
+       assistBytesPerWork := float64(heapRemaining) / float64(scanWorkRemaining)
+       atomic.Store64(&c.assistWorkPerByte, float64bits(assistWorkPerByte))
+       atomic.Store64(&c.assistBytesPerWork, float64bits(assistBytesPerWork))
+}
+
+// endCycle computes the trigger ratio for the next cycle.
+// userForced indicates whether the current GC cycle was forced
+// by the application.
+func (c *gcControllerState) endCycle(userForced bool) float64 {
+       if userForced {
+               // Forced GC means this cycle didn't start at the
+               // trigger, so where it finished isn't good
+               // information about how to adjust the trigger.
+               // Just leave it where it is.
+               return c.triggerRatio
+       }
+
+       // Proportional response gain for the trigger controller. Must
+       // be in [0, 1]. Lower values smooth out transient effects but
+       // take longer to respond to phase changes. Higher values
+       // react to phase changes quickly, but are more affected by
+       // transient changes. Values near 1 may be unstable.
+       const triggerGain = 0.5
+
+       // Compute next cycle trigger ratio. First, this computes the
+       // "error" for this cycle; that is, how far off the trigger
+       // was from what it should have been, accounting for both heap
+       // growth and GC CPU utilization. We compute the actual heap
+       // growth during this cycle and scale that by how far off from
+       // the goal CPU utilization we were (to estimate the heap
+       // growth if we had the desired CPU utilization). The
+       // difference between this estimate and the GOGC-based goal
+       // heap growth is the error.
+       goalGrowthRatio := c.effectiveGrowthRatio()
+       actualGrowthRatio := float64(c.heapLive)/float64(c.heapMarked) - 1
+       assistDuration := nanotime() - c.markStartTime
+
+       // Assume background mark hit its utilization goal.
+       utilization := gcBackgroundUtilization
+       // Add assist utilization; avoid divide by zero.
+       if assistDuration > 0 {
+               utilization += float64(c.assistTime) / float64(assistDuration*int64(gomaxprocs))
+       }
+
+       triggerError := goalGrowthRatio - c.triggerRatio - utilization/gcGoalUtilization*(actualGrowthRatio-c.triggerRatio)
+
+       // Finally, we adjust the trigger for next time by this error,
+       // damped by the proportional gain.
+       triggerRatio := c.triggerRatio + triggerGain*triggerError
+
+       if debug.gcpacertrace > 0 {
+               // Print controller state in terms of the design
+               // document.
+               H_m_prev := c.heapMarked
+               h_t := c.triggerRatio
+               H_T := c.trigger
+               h_a := actualGrowthRatio
+               H_a := c.heapLive
+               h_g := goalGrowthRatio
+               H_g := int64(float64(H_m_prev) * (1 + h_g))
+               u_a := utilization
+               u_g := gcGoalUtilization
+               W_a := c.scanWork
+               print("pacer: H_m_prev=", H_m_prev,
+                       " h_t=", h_t, " H_T=", H_T,
+                       " h_a=", h_a, " H_a=", H_a,
+                       " h_g=", h_g, " H_g=", H_g,
+                       " u_a=", u_a, " u_g=", u_g,
+                       " W_a=", W_a,
+                       " goalΔ=", goalGrowthRatio-h_t,
+                       " actualΔ=", h_a-h_t,
+                       " u_a/u_g=", u_a/u_g,
+                       "\n")
+       }
+
+       return triggerRatio
+}
+
+// enlistWorker encourages another dedicated mark worker to start on
+// another P if there are spare worker slots. It is used by putfull
+// when more work is made available.
+//
+//go:nowritebarrier
+func (c *gcControllerState) enlistWorker() {
+       // If there are idle Ps, wake one so it will run an idle worker.
+       // NOTE: This is suspected of causing deadlocks. See golang.org/issue/19112.
+       //
+       //      if atomic.Load(&sched.npidle) != 0 && atomic.Load(&sched.nmspinning) == 0 {
+       //              wakep()
+       //              return
+       //      }
+
+       // There are no idle Ps. If we need more dedicated workers,
+       // try to preempt a running P so it will switch to a worker.
+       if c.dedicatedMarkWorkersNeeded <= 0 {
+               return
+       }
+       // Pick a random other P to preempt.
+       if gomaxprocs <= 1 {
+               return
+       }
+       gp := getg()
+       if gp == nil || gp.m == nil || gp.m.p == 0 {
+               return
+       }
+       myID := gp.m.p.ptr().id
+       for tries := 0; tries < 5; tries++ {
+               id := int32(fastrandn(uint32(gomaxprocs - 1)))
+               if id >= myID {
+                       id++
+               }
+               p := allp[id]
+               if p.status != _Prunning {
+                       continue
+               }
+               if preemptone(p) {
+                       return
+               }
+       }
+}
+
+// findRunnableGCWorker returns a background mark worker for _p_ if it
+// should be run. This must only be called when gcBlackenEnabled != 0.
+func (c *gcControllerState) findRunnableGCWorker(_p_ *p) *g {
+       if gcBlackenEnabled == 0 {
+               throw("gcControllerState.findRunnable: blackening not enabled")
+       }
+
+       if !gcMarkWorkAvailable(_p_) {
+               // No work to be done right now. This can happen at
+               // the end of the mark phase when there are still
+               // assists tapering off. Don't bother running a worker
+               // now because it'll just return immediately.
+               return nil
+       }
+
+       // Grab a worker before we commit to running below.
+       node := (*gcBgMarkWorkerNode)(gcBgMarkWorkerPool.pop())
+       if node == nil {
+               // There is at least one worker per P, so normally there are
+               // enough workers to run on all Ps, if necessary. However, once
+               // a worker enters gcMarkDone it may park without rejoining the
+               // pool, thus freeing a P with no corresponding worker.
+               // gcMarkDone never depends on another worker doing work, so it
+               // is safe to simply do nothing here.
+               //
+               // If gcMarkDone bails out without completing the mark phase,
+               // it will always do so with queued global work. Thus, that P
+               // will be immediately eligible to re-run the worker G it was
+               // just using, ensuring work can complete.
+               return nil
+       }
+
+       decIfPositive := func(ptr *int64) bool {
+               for {
+                       v := atomic.Loadint64(ptr)
+                       if v <= 0 {
+                               return false
+                       }
+
+                       if atomic.Casint64(ptr, v, v-1) {
+                               return true
+                       }
+               }
+       }
+
+       if decIfPositive(&c.dedicatedMarkWorkersNeeded) {
+               // This P is now dedicated to marking until the end of
+               // the concurrent mark phase.
+               _p_.gcMarkWorkerMode = gcMarkWorkerDedicatedMode
+       } else if c.fractionalUtilizationGoal == 0 {
+               // No need for fractional workers.
+               gcBgMarkWorkerPool.push(&node.node)
+               return nil
+       } else {
+               // Is this P behind on the fractional utilization
+               // goal?
+               //
+               // This should be kept in sync with pollFractionalWorkerExit.
+               delta := nanotime() - c.markStartTime
+               if delta > 0 && float64(_p_.gcFractionalMarkTime)/float64(delta) > c.fractionalUtilizationGoal {
+                       // Nope. No need to run a fractional worker.
+                       gcBgMarkWorkerPool.push(&node.node)
+                       return nil
+               }
+               // Run a fractional worker.
+               _p_.gcMarkWorkerMode = gcMarkWorkerFractionalMode
+       }
+
+       // Run the background mark worker.
+       gp := node.gp.ptr()
+       casgstatus(gp, _Gwaiting, _Grunnable)
+       if trace.enabled {
+               traceGoUnpark(gp, 0)
+       }
+       return gp
+}
+
+// commit sets the trigger ratio and updates everything
+// derived from it: the absolute trigger, the heap goal, mark pacing,
+// and sweep pacing.
+//
+// This can be called any time. If GC is the in the middle of a
+// concurrent phase, it will adjust the pacing of that phase.
+//
+// This depends on gcPercent, gcController.heapMarked, and
+// gcController.heapLive. These must be up to date.
+//
+// mheap_.lock must be held or the world must be stopped.
+func (c *gcControllerState) commit(triggerRatio float64) {
+       assertWorldStoppedOrLockHeld(&mheap_.lock)
+
+       // Compute the next GC goal, which is when the allocated heap
+       // has grown by GOGC/100 over the heap marked by the last
+       // cycle.
+       goal := ^uint64(0)
+       if c.gcPercent >= 0 {
+               goal = c.heapMarked + c.heapMarked*uint64(c.gcPercent)/100
+       }
+
+       // Set the trigger ratio, capped to reasonable bounds.
+       if c.gcPercent >= 0 {
+               scalingFactor := float64(c.gcPercent) / 100
+               // Ensure there's always a little margin so that the
+               // mutator assist ratio isn't infinity.
+               maxTriggerRatio := 0.95 * scalingFactor
+               if triggerRatio > maxTriggerRatio {
+                       triggerRatio = maxTriggerRatio
+               }
+
+               // If we let triggerRatio go too low, then if the application
+               // is allocating very rapidly we might end up in a situation
+               // where we're allocating black during a nearly always-on GC.
+               // The result of this is a growing heap and ultimately an
+               // increase in RSS. By capping us at a point >0, we're essentially
+               // saying that we're OK using more CPU during the GC to prevent
+               // this growth in RSS.
+               //
+               // The current constant was chosen empirically: given a sufficiently
+               // fast/scalable allocator with 48 Ps that could drive the trigger ratio
+               // to <0.05, this constant causes applications to retain the same peak
+               // RSS compared to not having this allocator.
+               minTriggerRatio := 0.6 * scalingFactor
+               if triggerRatio < minTriggerRatio {
+                       triggerRatio = minTriggerRatio
+               }
+       } else if triggerRatio < 0 {
+               // gcPercent < 0, so just make sure we're not getting a negative
+               // triggerRatio. This case isn't expected to happen in practice,
+               // and doesn't really matter because if gcPercent < 0 then we won't
+               // ever consume triggerRatio further on in this function, but let's
+               // just be defensive here; the triggerRatio being negative is almost
+               // certainly undesirable.
+               triggerRatio = 0
+       }
+       c.triggerRatio = triggerRatio
+
+       // Compute the absolute GC trigger from the trigger ratio.
+       //
+       // We trigger the next GC cycle when the allocated heap has
+       // grown by the trigger ratio over the marked heap size.
+       trigger := ^uint64(0)
+       if c.gcPercent >= 0 {
+               trigger = uint64(float64(c.heapMarked) * (1 + triggerRatio))
+               // Don't trigger below the minimum heap size.
+               minTrigger := c.heapMinimum
+               if !isSweepDone() {
+                       // Concurrent sweep happens in the heap growth
+                       // from gcController.heapLive to trigger, so ensure
+                       // that concurrent sweep has some heap growth
+                       // in which to perform sweeping before we
+                       // start the next GC cycle.
+                       sweepMin := atomic.Load64(&c.heapLive) + sweepMinHeapDistance
+                       if sweepMin > minTrigger {
+                               minTrigger = sweepMin
+                       }
+               }
+               if trigger < minTrigger {
+                       trigger = minTrigger
+               }
+               if int64(trigger) < 0 {
+                       print("runtime: heapGoal=", c.heapGoal, " heapMarked=", c.heapMarked, " gcController.heapLive=", c.heapLive, " initialHeapLive=", work.initialHeapLive, "triggerRatio=", triggerRatio, " minTrigger=", minTrigger, "\n")
+                       throw("trigger underflow")
+               }
+               if trigger > goal {
+                       // The trigger ratio is always less than GOGC/100, but
+                       // other bounds on the trigger may have raised it.
+                       // Push up the goal, too.
+                       goal = trigger
+               }
+       }
+
+       // Commit to the trigger and goal.
+       c.trigger = trigger
+       atomic.Store64(&c.heapGoal, goal)
+       if trace.enabled {
+               traceHeapGoal()
+       }
+
+       // Update mark pacing.
+       if gcphase != _GCoff {
+               c.revise()
+       }
+
+       // Update sweep pacing.
+       if isSweepDone() {
+               mheap_.sweepPagesPerByte = 0
+       } else {
+               // Concurrent sweep needs to sweep all of the in-use
+               // pages by the time the allocated heap reaches the GC
+               // trigger. Compute the ratio of in-use pages to sweep
+               // per byte allocated, accounting for the fact that
+               // some might already be swept.
+               heapLiveBasis := atomic.Load64(&c.heapLive)
+               heapDistance := int64(trigger) - int64(heapLiveBasis)
+               // Add a little margin so rounding errors and
+               // concurrent sweep are less likely to leave pages
+               // unswept when GC starts.
+               heapDistance -= 1024 * 1024
+               if heapDistance < _PageSize {
+                       // Avoid setting the sweep ratio extremely high
+                       heapDistance = _PageSize
+               }
+               pagesSwept := atomic.Load64(&mheap_.pagesSwept)
+               pagesInUse := atomic.Load64(&mheap_.pagesInUse)
+               sweepDistancePages := int64(pagesInUse) - int64(pagesSwept)
+               if sweepDistancePages <= 0 {
+                       mheap_.sweepPagesPerByte = 0
+               } else {
+                       mheap_.sweepPagesPerByte = float64(sweepDistancePages) / float64(heapDistance)
+                       mheap_.sweepHeapLiveBasis = heapLiveBasis
+                       // Write pagesSweptBasis last, since this
+                       // signals concurrent sweeps to recompute
+                       // their debt.
+                       atomic.Store64(&mheap_.pagesSweptBasis, pagesSwept)
+               }
+       }
+
+       gcPaceScavenger()
+}
+
+// effectiveGrowthRatio returns the current effective heap growth
+// ratio (GOGC/100) based on heapMarked from the previous GC and
+// heapGoal for the current GC.
+//
+// This may differ from gcPercent/100 because of various upper and
+// lower bounds on gcPercent. For example, if the heap is smaller than
+// heapMinimum, this can be higher than gcPercent/100.
+//
+// mheap_.lock must be held or the world must be stopped.
+func (c *gcControllerState) effectiveGrowthRatio() float64 {
+       assertWorldStoppedOrLockHeld(&mheap_.lock)
+
+       egogc := float64(atomic.Load64(&c.heapGoal)-c.heapMarked) / float64(c.heapMarked)
+       if egogc < 0 {
+               // Shouldn't happen, but just in case.
+               egogc = 0
+       }
+       return egogc
+}
+
+// setGCPercent updates gcPercent and all related pacer state.
+// Returns the old value of gcPercent.
+//
+// The world must be stopped, or mheap_.lock must be held.
+func (c *gcControllerState) setGCPercent(in int32) int32 {
+       assertWorldStoppedOrLockHeld(&mheap_.lock)
+
+       out := c.gcPercent
+       if in < 0 {
+               in = -1
+       }
+       c.gcPercent = in
+       c.heapMinimum = defaultHeapMinimum * uint64(c.gcPercent) / 100
+       // Update pacing in response to gcPercent change.
+       c.commit(c.triggerRatio)
+
+       return out
+}
+
+//go:linkname setGCPercent runtime_1debug.setGCPercent
+func setGCPercent(in int32) (out int32) {
+       // Run on the system stack since we grab the heap lock.
+       systemstack(func() {
+               lock(&mheap_.lock)
+               out = gcController.setGCPercent(in)
+               unlock(&mheap_.lock)
+       })
+
+       // If we just disabled GC, wait for any concurrent GC mark to
+       // finish so we always return with no GC running.
+       if in < 0 {
+               gcWaitOnMark(atomic.Load(&work.cycles))
+       }
+
+       return out
+}
+
+func readGOGC() int32 {
+       p := gogetenv("GOGC")
+       if p == "off" {
+               return -1
+       }
+       if n, ok := atoi32(p); ok {
+               return n
+       }
+       return 100
+}
index da5be70344a2c48cbb736ffba0c09b932c3525bb..3fa1c4604d76080c311a3c1a7c95f2e1fbca26ea 100644 (file)
 // application down to a goal.
 //
 // That goal is defined as:
-//   (retainExtraPercent+100) / 100 * (next_gc / last_next_gc) * last_heap_inuse
+//   (retainExtraPercent+100) / 100 * (heapGoal / lastHeapGoal) * last_heap_inuse
 //
 // Essentially, we wish to have the application's RSS track the heap goal, but
 // the heap goal is defined in terms of bytes of objects, rather than pages like
 // RSS. As a result, we need to take into account for fragmentation internal to
-// spans. next_gc / last_next_gc defines the ratio between the current heap goal
+// spans. heapGoal / lastHeapGoal defines the ratio between the current heap goal
 // and the last heap goal, which tells us by how much the heap is growing and
 // shrinking. We estimate what the heap will grow to in terms of pages by taking
 // this ratio and multiplying it by heap_inuse at the end of the last GC, which
@@ -118,12 +118,12 @@ func gcPaceScavenger() {
        // We never scavenge before the 2nd GC cycle anyway (we don't have enough
        // information about the heap yet) so this is fine, and avoids a fault
        // or garbage data later.
-       if memstats.last_next_gc == 0 {
+       if gcController.lastHeapGoal == 0 {
                mheap_.scavengeGoal = ^uint64(0)
                return
        }
        // Compute our scavenging goal.
-       goalRatio := float64(atomic.Load64(&memstats.next_gc)) / float64(memstats.last_next_gc)
+       goalRatio := float64(atomic.Load64(&gcController.heapGoal)) / float64(gcController.lastHeapGoal)
        retainedGoal := uint64(float64(memstats.last_heap_inuse) * goalRatio)
        // Add retainExtraPercent overhead to retainedGoal. This calculation
        // looks strange but the purpose is to arrive at an integer division
@@ -207,7 +207,7 @@ func wakeScavenger() {
                // Ready the goroutine by injecting it. We use injectglist instead
                // of ready or goready in order to allow us to run this function
                // without a P. injectglist also avoids placing the goroutine in
-               // the current P's runnext slot, which is desireable to prevent
+               // the current P's runnext slot, which is desirable to prevent
                // the scavenger from interfering with user goroutine scheduling
                // too much.
                var list gList
@@ -249,7 +249,7 @@ func scavengeSleep(ns int64) int64 {
 // The background scavenger maintains the RSS of the application below
 // the line described by the proportional scavenging statistics in
 // the mheap struct.
-func bgscavenge(c chan int) {
+func bgscavenge() {
        setSystemGoroutine()
 
        scavenge.g = getg()
@@ -263,7 +263,7 @@ func bgscavenge(c chan int) {
                wakeScavenger()
        }
 
-       c <- 1
+       gcenable_setup <- 1
        goparkunlock(&scavenge.lock, waitReasonGCScavengeWait, traceEvGoBlock, 1)
 
        // Exponentially-weighted moving average of the fraction of time this
@@ -374,7 +374,7 @@ func bgscavenge(c chan int) {
                // Due to OS-related anomalies we may "sleep" for an inordinate amount
                // of time. Let's avoid letting the ratio get out of hand by bounding
                // the sleep time we use in our EWMA.
-               const minFraction = 1 / 1000
+               const minFraction = 1.0 / 1000.0
                if fraction < minFraction {
                        fraction = minFraction
                }
index 250343077ff84737ac31d5d7b56108903d13cf66..3b12a2e1e631524e4ea267025214f34966fa42a0 100644 (file)
@@ -152,12 +152,6 @@ func TestPallocDataFindScavengeCandidate(t *testing.T) {
                        max:   PallocChunkPages,
                        want:  BitRange{0, uint(m)},
                }
-               tests["StartFree"+suffix] = test{
-                       alloc: []BitRange{{uint(m), PallocChunkPages - uint(m)}},
-                       min:   m,
-                       max:   PallocChunkPages,
-                       want:  BitRange{0, uint(m)},
-               }
                tests["EndFree"+suffix] = test{
                        alloc: []BitRange{{0, PallocChunkPages - uint(m)}},
                        min:   m,
index b2a5a8670b85ce5292e6f3eaa2988519330c05c6..746e7f0a9f7d9f26d99fa73cb5d633f02fbc7979 100644 (file)
@@ -153,7 +153,7 @@ func finishsweep_m() {
        nextMarkBitArenaEpoch()
 }
 
-func bgsweep(c chan int) {
+func bgsweep() {
        setSystemGoroutine()
 
        sweep.g = getg()
@@ -161,7 +161,7 @@ func bgsweep(c chan int) {
        lockInit(&sweep.lock, lockRankSweep)
        lock(&sweep.lock)
        sweep.parked = true
-       c <- 1
+       gcenable_setup <- 1
        goparkunlock(&sweep.lock, waitReasonGCSweepWait, traceEvGoBlock, 1)
 
        for {
@@ -178,6 +178,10 @@ func bgsweep(c chan int) {
                        // gosweepone returning ^0 above
                        // and the lock being acquired.
                        unlock(&sweep.lock)
+
+                       // We need a preemption point for gofrontend.
+                       Gosched()
+
                        continue
                }
                sweep.parked = true
@@ -185,66 +189,133 @@ func bgsweep(c chan int) {
        }
 }
 
+// sweepLocker acquires sweep ownership of spans and blocks sweep
+// completion.
+type sweepLocker struct {
+       // sweepGen is the sweep generation of the heap.
+       sweepGen uint32
+       // blocking indicates that this tracker is blocking sweep
+       // completion, usually as a result of acquiring sweep
+       // ownership of at least one span.
+       blocking bool
+}
+
+// sweepLocked represents sweep ownership of a span.
+type sweepLocked struct {
+       *mspan
+}
+
+func newSweepLocker() sweepLocker {
+       return sweepLocker{
+               sweepGen: mheap_.sweepgen,
+       }
+}
+
+// tryAcquire attempts to acquire sweep ownership of span s. If it
+// successfully acquires ownership, it blocks sweep completion.
+func (l *sweepLocker) tryAcquire(s *mspan) (sweepLocked, bool) {
+       // Check before attempting to CAS.
+       if atomic.Load(&s.sweepgen) != l.sweepGen-2 {
+               return sweepLocked{}, false
+       }
+       // Add ourselves to sweepers before potentially taking
+       // ownership.
+       l.blockCompletion()
+       // Attempt to acquire sweep ownership of s.
+       if !atomic.Cas(&s.sweepgen, l.sweepGen-2, l.sweepGen-1) {
+               return sweepLocked{}, false
+       }
+       return sweepLocked{s}, true
+}
+
+// blockCompletion blocks sweep completion without acquiring any
+// specific spans.
+func (l *sweepLocker) blockCompletion() {
+       if !l.blocking {
+               atomic.Xadd(&mheap_.sweepers, +1)
+               l.blocking = true
+       }
+}
+
+func (l *sweepLocker) dispose() {
+       if !l.blocking {
+               return
+       }
+       // Decrement the number of active sweepers and if this is the
+       // last one, mark sweep as complete.
+       l.blocking = false
+       if atomic.Xadd(&mheap_.sweepers, -1) == 0 && atomic.Load(&mheap_.sweepDrained) != 0 {
+               l.sweepIsDone()
+       }
+}
+
+func (l *sweepLocker) sweepIsDone() {
+       if debug.gcpacertrace > 0 {
+               print("pacer: sweep done at heap size ", gcController.heapLive>>20, "MB; allocated ", (gcController.heapLive-mheap_.sweepHeapLiveBasis)>>20, "MB during sweep; swept ", mheap_.pagesSwept, " pages at ", mheap_.sweepPagesPerByte, " pages/byte\n")
+       }
+}
+
 // sweepone sweeps some unswept heap span and returns the number of pages returned
 // to the heap, or ^uintptr(0) if there was nothing to sweep.
 func sweepone() uintptr {
        _g_ := getg()
-       sweepRatio := mheap_.sweepPagesPerByte // For debugging
 
        // increment locks to ensure that the goroutine is not preempted
        // in the middle of sweep thus leaving the span in an inconsistent state for next GC
        _g_.m.locks++
-       if atomic.Load(&mheap_.sweepdone) != 0 {
+       if atomic.Load(&mheap_.sweepDrained) != 0 {
                _g_.m.locks--
                return ^uintptr(0)
        }
-       atomic.Xadd(&mheap_.sweepers, +1)
+       // TODO(austin): sweepone is almost always called in a loop;
+       // lift the sweepLocker into its callers.
+       sl := newSweepLocker()
 
        // Find a span to sweep.
-       var s *mspan
-       sg := mheap_.sweepgen
+       npages := ^uintptr(0)
+       var noMoreWork bool
        for {
-               s = mheap_.nextSpanForSweep()
+               s := mheap_.nextSpanForSweep()
                if s == nil {
-                       atomic.Store(&mheap_.sweepdone, 1)
+                       noMoreWork = atomic.Cas(&mheap_.sweepDrained, 0, 1)
                        break
                }
                if state := s.state.get(); state != mSpanInUse {
                        // This can happen if direct sweeping already
                        // swept this span, but in that case the sweep
                        // generation should always be up-to-date.
-                       if !(s.sweepgen == sg || s.sweepgen == sg+3) {
-                               print("runtime: bad span s.state=", state, " s.sweepgen=", s.sweepgen, " sweepgen=", sg, "\n")
+                       if !(s.sweepgen == sl.sweepGen || s.sweepgen == sl.sweepGen+3) {
+                               print("runtime: bad span s.state=", state, " s.sweepgen=", s.sweepgen, " sweepgen=", sl.sweepGen, "\n")
                                throw("non in-use span in unswept list")
                        }
                        continue
                }
-               if s.sweepgen == sg-2 && atomic.Cas(&s.sweepgen, sg-2, sg-1) {
+               if s, ok := sl.tryAcquire(s); ok {
+                       // Sweep the span we found.
+                       npages = s.npages
+                       if s.sweep(false) {
+                               // Whole span was freed. Count it toward the
+                               // page reclaimer credit since these pages can
+                               // now be used for span allocation.
+                               atomic.Xadduintptr(&mheap_.reclaimCredit, npages)
+                       } else {
+                               // Span is still in-use, so this returned no
+                               // pages to the heap and the span needs to
+                               // move to the swept in-use list.
+                               npages = 0
+                       }
                        break
                }
        }
 
-       // Sweep the span we found.
-       npages := ^uintptr(0)
-       if s != nil {
-               npages = s.npages
-               if s.sweep(false) {
-                       // Whole span was freed. Count it toward the
-                       // page reclaimer credit since these pages can
-                       // now be used for span allocation.
-                       atomic.Xadduintptr(&mheap_.reclaimCredit, npages)
-               } else {
-                       // Span is still in-use, so this returned no
-                       // pages to the heap and the span needs to
-                       // move to the swept in-use list.
-                       npages = 0
-               }
-       }
+       sl.dispose()
 
-       // Decrement the number of active sweepers and if this is the
-       // last one print trace information.
-       if atomic.Xadd(&mheap_.sweepers, -1) == 0 && atomic.Load(&mheap_.sweepdone) != 0 {
-               // Since the sweeper is done, move the scavenge gen forward (signalling
+       if noMoreWork {
+               // The sweep list is empty. There may still be
+               // concurrent sweeps running, but we're at least very
+               // close to done sweeping.
+
+               // Move the scavenge gen forward (signalling
                // that there's new work to do) and wake the scavenger.
                //
                // The scavenger is signaled by the last sweeper because once
@@ -264,23 +335,23 @@ func sweepone() uintptr {
                // for us to wake the scavenger directly via wakeScavenger, since
                // it could allocate. Ask sysmon to do it for us instead.
                readyForScavenger()
-
-               if debug.gcpacertrace > 0 {
-                       print("pacer: sweep done at heap size ", memstats.heap_live>>20, "MB; allocated ", (memstats.heap_live-mheap_.sweepHeapLiveBasis)>>20, "MB during sweep; swept ", mheap_.pagesSwept, " pages at ", sweepRatio, " pages/byte\n")
-               }
        }
+
        _g_.m.locks--
        return npages
 }
 
-// isSweepDone reports whether all spans are swept or currently being swept.
+// isSweepDone reports whether all spans are swept.
 //
 // Note that this condition may transition from false to true at any
 // time as the sweeper runs. It may transition from true to false if a
 // GC runs; to prevent that the caller must be non-preemptible or must
 // somehow block GC progress.
 func isSweepDone() bool {
-       return mheap_.sweepdone != 0
+       // Check that all spans have at least begun sweeping and there
+       // are no active sweepers. If both are true, then all spans
+       // have finished sweeping.
+       return atomic.Load(&mheap_.sweepDrained) != 0 && atomic.Load(&mheap_.sweepers) == 0
 }
 
 // Returns only when span s has been swept.
@@ -294,20 +365,19 @@ func (s *mspan) ensureSwept() {
                throw("mspan.ensureSwept: m is not locked")
        }
 
-       sg := mheap_.sweepgen
-       spangen := atomic.Load(&s.sweepgen)
-       if spangen == sg || spangen == sg+3 {
-               return
-       }
+       sl := newSweepLocker()
        // The caller must be sure that the span is a mSpanInUse span.
-       if atomic.Cas(&s.sweepgen, sg-2, sg-1) {
+       if s, ok := sl.tryAcquire(s); ok {
                s.sweep(false)
+               sl.dispose()
                return
        }
+       sl.dispose()
+
        // unfortunate condition, and we don't have efficient means to wait
        for {
                spangen := atomic.Load(&s.sweepgen)
-               if spangen == sg || spangen == sg+3 {
+               if spangen == sl.sweepGen || spangen == sl.sweepGen+3 {
                        break
                }
                osyield()
@@ -319,13 +389,21 @@ func (s *mspan) ensureSwept() {
 // Returns true if the span was returned to heap.
 // If preserve=true, don't return it to heap nor relink in mcentral lists;
 // caller takes care of it.
-func (s *mspan) sweep(preserve bool) bool {
+func (sl *sweepLocked) sweep(preserve bool) bool {
        // It's critical that we enter this function with preemption disabled,
        // GC must not start while we are in the middle of this function.
        _g_ := getg()
        if _g_.m.locks == 0 && _g_.m.mallocing == 0 && _g_ != _g_.m.g0 {
                throw("mspan.sweep: m is not locked")
        }
+
+       s := sl.mspan
+       if !preserve {
+               // We'll release ownership of this span. Nil it out to
+               // prevent the caller from accidentally using it.
+               sl.mspan = nil
+       }
+
        sweepgen := mheap_.sweepgen
        if state := s.state.get(); state != mSpanInUse || s.sweepgen != sweepgen-1 {
                print("mspan.sweep: state=", state, " sweepgen=", s.sweepgen, " mheap.sweepgen=", sweepgen, "\n")
@@ -358,11 +436,10 @@ func (s *mspan) sweep(preserve bool) bool {
        //    If such object is not marked, we need to queue all finalizers at once.
        // Both 1 and 2 are possible at the same time.
        hadSpecials := s.specials != nil
-       specialp := &s.specials
-       special := *specialp
-       for special != nil {
+       siter := newSpecialsIter(s)
+       for siter.valid() {
                // A finalizer can be set for an inner byte of an object, find object beginning.
-               objIndex := uintptr(special.offset) / size
+               objIndex := uintptr(siter.s.offset) / size
                p := s.base() + objIndex*size
                mbits := s.markBitsForIndex(objIndex)
                if !mbits.isMarked() {
@@ -370,7 +447,7 @@ func (s *mspan) sweep(preserve bool) bool {
                        // Pass 1: see if it has at least one finalizer.
                        hasFin := false
                        endOffset := p - s.base() + size
-                       for tmp := special; tmp != nil && uintptr(tmp.offset) < endOffset; tmp = tmp.next {
+                       for tmp := siter.s; tmp != nil && uintptr(tmp.offset) < endOffset; tmp = tmp.next {
                                if tmp.kind == _KindSpecialFinalizer {
                                        // Stop freeing of object if it has a finalizer.
                                        mbits.setMarkedNonAtomic()
@@ -379,27 +456,31 @@ func (s *mspan) sweep(preserve bool) bool {
                                }
                        }
                        // Pass 2: queue all finalizers _or_ handle profile record.
-                       for special != nil && uintptr(special.offset) < endOffset {
+                       for siter.valid() && uintptr(siter.s.offset) < endOffset {
                                // Find the exact byte for which the special was setup
                                // (as opposed to object beginning).
+                               special := siter.s
                                p := s.base() + uintptr(special.offset)
                                if special.kind == _KindSpecialFinalizer || !hasFin {
-                                       // Splice out special record.
-                                       y := special
-                                       special = special.next
-                                       *specialp = special
-                                       freespecial(y, unsafe.Pointer(p), size)
+                                       siter.unlinkAndNext()
+                                       freeSpecial(special, unsafe.Pointer(p), size)
                                } else {
-                                       // This is profile record, but the object has finalizers (so kept alive).
-                                       // Keep special record.
-                                       specialp = &special.next
-                                       special = *specialp
+                                       // The object has finalizers, so we're keeping it alive.
+                                       // All other specials only apply when an object is freed,
+                                       // so just keep the special record.
+                                       siter.next()
                                }
                        }
                } else {
-                       // object is still live: keep special record
-                       specialp = &special.next
-                       special = *specialp
+                       // object is still live
+                       if siter.s.kind == _KindSpecialReachable {
+                               special := siter.unlinkAndNext()
+                               (*specialReachable)(unsafe.Pointer(special)).reachable = true
+                               freeSpecial(special, unsafe.Pointer(p), size)
+                       } else {
+                               // keep special record
+                               siter.next()
+                       }
                }
        }
        if hadSpecials && s.specials == nil {
@@ -647,7 +728,7 @@ retry:
        sweptBasis := atomic.Load64(&mheap_.pagesSweptBasis)
 
        // Fix debt if necessary.
-       newHeapLive := uintptr(atomic.Load64(&memstats.heap_live)-mheap_.sweepHeapLiveBasis) + spanBytes
+       newHeapLive := uintptr(atomic.Load64(&gcController.heapLive)-mheap_.sweepHeapLiveBasis) + spanBytes
        pagesTarget := int64(mheap_.sweepPagesPerByte*float64(newHeapLive)) - int64(callerSweepPages)
        for pagesTarget > int64(atomic.Load64(&mheap_.pagesSwept)-sweptBasis) {
                if sweepone() == ^uintptr(0) {
index b3a068661ebec0caf0bd40465c63945c6b18c9cb..667c7afa97197ddd3d190fafaf928385595447dd 100644 (file)
@@ -398,7 +398,7 @@ func getempty() *workbuf {
 }
 
 // putempty puts a workbuf onto the work.empty list.
-// Upon entry this go routine owns b. The lfstack.push relinquishes ownership.
+// Upon entry this goroutine owns b. The lfstack.push relinquishes ownership.
 //go:nowritebarrier
 func putempty(b *workbuf) {
        b.checkempty()
index 77f39870c276d1ec392156fdc8aa1215ab8667f0..8e346c8ead7280dc4fbe99c5b815cb140e938343 100644 (file)
@@ -62,11 +62,12 @@ const (
 type mheap struct {
        // lock must only be acquired on the system stack, otherwise a g
        // could self-deadlock if its stack grows with the lock held.
-       lock      mutex
-       pages     pageAlloc // page allocation data structure
-       sweepgen  uint32    // sweep generation, see comment in mspan; written during STW
-       sweepdone uint32    // all spans are swept
-       sweepers  uint32    // number of active sweepone calls
+       lock  mutex
+       pages pageAlloc // page allocation data structure
+
+       sweepgen     uint32 // sweep generation, see comment in mspan; written during STW
+       sweepDrained uint32 // all spans are swept or are being swept
+       sweepers     uint32 // number of active sweepone calls
 
        // allspans is a slice of all mspans ever created. Each mspan
        // appears exactly once.
@@ -85,14 +86,14 @@ type mheap struct {
 
        // Proportional sweep
        //
-       // These parameters represent a linear function from heap_live
+       // These parameters represent a linear function from gcController.heapLive
        // to page sweep count. The proportional sweep system works to
        // stay in the black by keeping the current page sweep count
-       // above this line at the current heap_live.
+       // above this line at the current gcController.heapLive.
        //
        // The line has slope sweepPagesPerByte and passes through a
        // basis point at (sweepHeapLiveBasis, pagesSweptBasis). At
-       // any given time, the system is at (memstats.heap_live,
+       // any given time, the system is at (gcController.heapLive,
        // pagesSwept) in this space.
        //
        // It's important that the line pass through a point we
@@ -104,7 +105,7 @@ type mheap struct {
        pagesInUse         uint64  // pages of spans in stats mSpanInUse; updated atomically
        pagesSwept         uint64  // pages swept this cycle; updated atomically
        pagesSweptBasis    uint64  // pagesSwept to use as the origin of the sweep ratio; updated atomically
-       sweepHeapLiveBasis uint64  // value of heap_live to use as the origin of sweep ratio; written with lock, read without
+       sweepHeapLiveBasis uint64  // value of gcController.heapLive to use as the origin of sweep ratio; written with lock, read without
        sweepPagesPerByte  float64 // proportional sweep ratio; written with lock, read without
        // TODO(austin): pagesInUse should be a uintptr, but the 386
        // compiler can't 8-byte align fields.
@@ -212,6 +213,7 @@ type mheap struct {
        cachealloc            fixalloc // allocator for mcache*
        specialfinalizeralloc fixalloc // allocator for specialfinalizer*
        specialprofilealloc   fixalloc // allocator for specialprofile*
+       specialReachableAlloc fixalloc // allocator for specialReachable
        speciallock           mutex    // lock for special record allocators.
        arenaHintAlloc        fixalloc // allocator for arenaHints
 
@@ -451,14 +453,11 @@ type mspan struct {
        // h->sweepgen is incremented by 2 after every GC
 
        sweepgen    uint32
-       divMul      uint16        // for divide by elemsize - divMagic.mul
-       baseMask    uint16        // if non-0, elemsize is a power of 2, & this will get object allocation base
+       divMul      uint32        // for divide by elemsize
        allocCount  uint16        // number of allocated objects
        spanclass   spanClass     // size class and noscan (uint8)
        state       mSpanStateBox // mSpanInUse etc; accessed atomically (get/set methods)
        needzero    uint8         // needs to be zeroed before allocation
-       divShift    uint8         // for divide by elemsize - divMagic.shift
-       divShift2   uint8         // for divide by elemsize - divMagic.shift2
        elemsize    uintptr       // computed from sizeclass or from npages
        limit       uintptr       // end of data in span
        speciallock mutex         // guards specials list
@@ -706,6 +705,7 @@ func (h *mheap) init() {
        h.cachealloc.init(unsafe.Sizeof(mcache{}), nil, nil, &memstats.mcache_sys)
        h.specialfinalizeralloc.init(unsafe.Sizeof(specialfinalizer{}), nil, nil, &memstats.other_sys)
        h.specialprofilealloc.init(unsafe.Sizeof(specialprofile{}), nil, nil, &memstats.other_sys)
+       h.specialReachableAlloc.init(unsafe.Sizeof(specialReachable{}), nil, nil, &memstats.other_sys)
        h.arenaHintAlloc.init(unsafe.Sizeof(arenaHint{}), nil, nil, &memstats.other_sys)
 
        // Don't zero mspan allocations. Background sweeping can
@@ -818,7 +818,7 @@ func (h *mheap) reclaimChunk(arenas []arenaIdx, pageIdx, n uintptr) uintptr {
 
        n0 := n
        var nFreed uintptr
-       sg := h.sweepgen
+       sl := newSweepLocker()
        for n > 0 {
                ai := arenas[pageIdx/pagesPerArena]
                ha := h.arenas[ai.l1()][ai.l2()]
@@ -843,7 +843,7 @@ func (h *mheap) reclaimChunk(arenas []arenaIdx, pageIdx, n uintptr) uintptr {
                        for j := uint(0); j < 8; j++ {
                                if inUseUnmarked&(1<<j) != 0 {
                                        s := ha.spans[arenaPage+uint(i)*8+j]
-                                       if atomic.Load(&s.sweepgen) == sg-2 && atomic.Cas(&s.sweepgen, sg-2, sg-1) {
+                                       if s, ok := sl.tryAcquire(s); ok {
                                                npages := s.npages
                                                unlock(&h.lock)
                                                if s.sweep(false) {
@@ -864,6 +864,7 @@ func (h *mheap) reclaimChunk(arenas []arenaIdx, pageIdx, n uintptr) uintptr {
                pageIdx += uintptr(len(inUse) * 8)
                n -= uintptr(len(inUse) * 8)
        }
+       sl.dispose()
        if trace.enabled {
                unlock(&h.lock)
                // Account for pages scanned but not reclaimed.
@@ -896,7 +897,9 @@ func (s spanAllocType) manual() bool {
 // spanclass indicates the span's size class and scannability.
 //
 // If needzero is true, the memory for the returned span will be zeroed.
-func (h *mheap) alloc(npages uintptr, spanclass spanClass, needzero bool) *mspan {
+// The boolean returned indicates whether the returned span contains zeroes,
+// either because this was requested, or because it was already zeroed.
+func (h *mheap) alloc(npages uintptr, spanclass spanClass, needzero bool) (*mspan, bool) {
        // Don't do any operations that lock the heap on the G stack.
        // It might trigger stack growth, and the stack growth code needs
        // to be able to allocate heap.
@@ -904,19 +907,22 @@ func (h *mheap) alloc(npages uintptr, spanclass spanClass, needzero bool) *mspan
        systemstack(func() {
                // To prevent excessive heap growth, before allocating n pages
                // we need to sweep and reclaim at least n pages.
-               if h.sweepdone == 0 {
+               if !isSweepDone() {
                        h.reclaim(npages)
                }
                s = h.allocSpan(npages, spanAllocHeap, spanclass)
        })
 
-       if s != nil {
-               if needzero && s.needzero != 0 {
-                       memclrNoHeapPointers(unsafe.Pointer(s.base()), s.npages<<_PageShift)
-               }
-               s.needzero = 0
+       if s == nil {
+               return nil, false
        }
-       return s
+       isZeroed := s.needzero == 0
+       if needzero && !isZeroed {
+               memclrNoHeapPointers(unsafe.Pointer(s.base()), s.npages<<_PageShift)
+               isZeroed = true
+       }
+       s.needzero = 0
+       return s, isZeroed
 }
 
 // allocManual allocates a manually-managed span of npage pages.
@@ -1224,20 +1230,11 @@ HaveSpan:
                if sizeclass := spanclass.sizeclass(); sizeclass == 0 {
                        s.elemsize = nbytes
                        s.nelems = 1
-
-                       s.divShift = 0
                        s.divMul = 0
-                       s.divShift2 = 0
-                       s.baseMask = 0
                } else {
                        s.elemsize = uintptr(class_to_size[sizeclass])
                        s.nelems = nbytes / s.elemsize
-
-                       m := &class_to_divmagic[sizeclass]
-                       s.divShift = m.shift
-                       s.divMul = m.mul
-                       s.divShift2 = m.shift2
-                       s.baseMask = m.baseMask
+                       s.divMul = class_to_divmagic[sizeclass]
                }
 
                // Initialize mark and allocation structures.
@@ -1332,6 +1329,10 @@ func (h *mheap) grow(npage uintptr) bool {
        assertLockHeld(&h.lock)
 
        // We must grow the heap in whole palloc chunks.
+       // We call sysMap below but note that because we
+       // round up to pallocChunkPages which is on the order
+       // of MiB (generally >= to the huge page size) we
+       // won't be calling it too much.
        ask := alignUp(npage, pallocChunkPages) * pageSize
 
        totalGrowth := uintptr(0)
@@ -1358,6 +1359,17 @@ func (h *mheap) grow(npage uintptr) bool {
                        // remains of the current space and switch to
                        // the new space. This should be rare.
                        if size := h.curArena.end - h.curArena.base; size != 0 {
+                               // Transition this space from Reserved to Prepared and mark it
+                               // as released since we'll be able to start using it after updating
+                               // the page allocator and releasing the lock at any time.
+                               sysMap(unsafe.Pointer(h.curArena.base), size, &memstats.heap_sys)
+                               // Update stats.
+                               atomic.Xadd64(&memstats.heap_released, int64(size))
+                               stats := memstats.heapStats.acquire()
+                               atomic.Xaddint64(&stats.released, int64(size))
+                               memstats.heapStats.release()
+                               // Update the page allocator's structures to make this
+                               // space ready for allocation.
                                h.pages.grow(h.curArena.base, size)
                                totalGrowth += size
                        }
@@ -1366,17 +1378,6 @@ func (h *mheap) grow(npage uintptr) bool {
                        h.curArena.end = uintptr(av) + asize
                }
 
-               // The memory just allocated counts as both released
-               // and idle, even though it's not yet backed by spans.
-               //
-               // The allocation is always aligned to the heap arena
-               // size which is always > physPageSize, so its safe to
-               // just add directly to heap_released.
-               atomic.Xadd64(&memstats.heap_released, int64(asize))
-               stats := memstats.heapStats.acquire()
-               atomic.Xaddint64(&stats.released, int64(asize))
-               memstats.heapStats.release()
-
                // Recalculate nBase.
                // We know this won't overflow, because sysAlloc returned
                // a valid region starting at h.curArena.base which is at
@@ -1387,6 +1388,23 @@ func (h *mheap) grow(npage uintptr) bool {
        // Grow into the current arena.
        v := h.curArena.base
        h.curArena.base = nBase
+
+       // Transition the space we're going to use from Reserved to Prepared.
+       sysMap(unsafe.Pointer(v), nBase-v, &memstats.heap_sys)
+
+       // The memory just allocated counts as both released
+       // and idle, even though it's not yet backed by spans.
+       //
+       // The allocation is always aligned to the heap arena
+       // size which is always > physPageSize, so its safe to
+       // just add directly to heap_released.
+       atomic.Xadd64(&memstats.heap_released, int64(nBase-v))
+       stats := memstats.heapStats.acquire()
+       atomic.Xaddint64(&stats.released, int64(nBase-v))
+       memstats.heapStats.release()
+
+       // Update the page allocator's structures to make this
+       // space ready for allocation.
        h.pages.grow(v, nBase-v)
        totalGrowth += nBase - v
 
@@ -1640,6 +1658,9 @@ func (list *mSpanList) takeAll(other *mSpanList) {
 const (
        _KindSpecialFinalizer = 1
        _KindSpecialProfile   = 2
+       // _KindSpecialReachable is a special used for tracking
+       // reachability during testing.
+       _KindSpecialReachable = 3
        // Note: The finalizer special must be first because if we're freeing
        // an object, a finalizer special will cause the freeing operation
        // to abort, and we want to keep the other special records around
@@ -1843,9 +1864,45 @@ func setprofilebucket(p unsafe.Pointer, b *bucket) {
        }
 }
 
-// Do whatever cleanup needs to be done to deallocate s. It has
-// already been unlinked from the mspan specials list.
-func freespecial(s *special, p unsafe.Pointer, size uintptr) {
+// specialReachable tracks whether an object is reachable on the next
+// GC cycle. This is used by testing.
+type specialReachable struct {
+       special   special
+       done      bool
+       reachable bool
+}
+
+// specialsIter helps iterate over specials lists.
+type specialsIter struct {
+       pprev **special
+       s     *special
+}
+
+func newSpecialsIter(span *mspan) specialsIter {
+       return specialsIter{&span.specials, span.specials}
+}
+
+func (i *specialsIter) valid() bool {
+       return i.s != nil
+}
+
+func (i *specialsIter) next() {
+       i.pprev = &i.s.next
+       i.s = *i.pprev
+}
+
+// unlinkAndNext removes the current special from the list and moves
+// the iterator to the next special. It returns the unlinked special.
+func (i *specialsIter) unlinkAndNext() *special {
+       cur := i.s
+       i.s = cur.next
+       *i.pprev = i.s
+       return cur
+}
+
+// freeSpecial performs any cleanup on special s and deallocates it.
+// s must already be unlinked from the specials list.
+func freeSpecial(s *special, p unsafe.Pointer, size uintptr) {
        switch s.kind {
        case _KindSpecialFinalizer:
                sf := (*specialfinalizer)(unsafe.Pointer(s))
@@ -1859,6 +1916,10 @@ func freespecial(s *special, p unsafe.Pointer, size uintptr) {
                lock(&mheap_.speciallock)
                mheap_.specialprofilealloc.free(unsafe.Pointer(sp))
                unlock(&mheap_.speciallock)
+       case _KindSpecialReachable:
+               sp := (*specialReachable)(unsafe.Pointer(s))
+               sp.done = true
+               // The creator frees these.
        default:
                throw("bad special kind")
                panic("not reached")
index d65029239484cc085748622048f15607202a1254..8d78a3923a094be383eaebbbce64d519c579c45a 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 // fastlog2Table contains log2 approximations for 5 binary digits.
index 8644973a0cc60db8ad0a526cfa787f80a483edad..f82df93442226426850e854187e7bcc52a1d4bb0 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 // mkpreempt generates the asyncPreempt functions for each
@@ -123,6 +124,7 @@ func header(arch string) {
        fmt.Fprintf(out, "// Code generated by mkpreempt.go; DO NOT EDIT.\n\n")
        if beLe[arch] {
                base := arch[:len(arch)-1]
+               fmt.Fprintf(out, "//go:build %s || %sle\n", base, base)
                fmt.Fprintf(out, "// +build %s %sle\n\n", base, base)
        }
        fmt.Fprintf(out, "#include \"go_asm.h\"\n")
@@ -230,12 +232,16 @@ func genAMD64() {
                if reg == "SP" || reg == "BP" {
                        continue
                }
-               if strings.HasPrefix(reg, "X") {
-                       l.add("MOVUPS", reg, 16)
-               } else {
+               if !strings.HasPrefix(reg, "X") {
                        l.add("MOVQ", reg, 8)
                }
        }
+       lSSE := layout{stack: l.stack, sp: "SP"}
+       for _, reg := range regNamesAMD64 {
+               if strings.HasPrefix(reg, "X") {
+                       lSSE.add("MOVUPS", reg, 16)
+               }
+       }
 
        // TODO: MXCSR register?
 
@@ -244,10 +250,12 @@ func genAMD64() {
        p("// Save flags before clobbering them")
        p("PUSHFQ")
        p("// obj doesn't understand ADD/SUB on SP, but does understand ADJSP")
-       p("ADJSP $%d", l.stack)
+       p("ADJSP $%d", lSSE.stack)
        p("// But vet doesn't know ADJSP, so suppress vet stack checking")
        p("NOP SP")
 
+       l.save()
+
        // Apparently, the signal handling code path in darwin kernel leaves
        // the upper bits of Y registers in a dirty state, which causes
        // many SSE operations (128-bit and narrower) become much slower.
@@ -259,10 +267,11 @@ func genAMD64() {
        p("VZEROUPPER")
        p("#endif")
 
-       l.save()
+       lSSE.save()
        p("CALL ·asyncPreempt2(SB)")
+       lSSE.restore()
        l.restore()
-       p("ADJSP $%d", -l.stack)
+       p("ADJSP $%d", -lSSE.stack)
        p("POPFQ")
        p("POPQ BP")
        p("RET")
index b92d1fed5f834ae23a60b3138c840dca2b8831b9..b1b10e9e0230a9976968a4b7cf84a9ee2d746eda 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 // Generate tables for small malloc size classes.
@@ -36,6 +37,8 @@ import (
        "go/format"
        "io"
        "log"
+       "math"
+       "math/bits"
        "os"
 )
 
@@ -86,11 +89,6 @@ const (
 type class struct {
        size   int // max size
        npages int // number of pages
-
-       mul    int
-       shift  uint
-       shift2 uint
-       mask   int
 }
 
 func powerOfTwo(x int) bool {
@@ -167,9 +165,9 @@ func makeClasses() []class {
        return classes
 }
 
-// computeDivMagic computes some magic constants to implement
-// the division required to compute object number from span offset.
-// n / c.size is implemented as n >> c.shift * c.mul >> c.shift2
+// computeDivMagic checks that the division required to compute object
+// index from span offset can be computed using 32-bit multiplication.
+// n / c.size is implemented as (n * (^uint32(0)/uint32(c.size) + 1)) >> 32
 // for all 0 <= n <= c.npages * pageSize
 func computeDivMagic(c *class) {
        // divisor
@@ -181,68 +179,67 @@ func computeDivMagic(c *class) {
        // maximum input value for which the formula needs to work.
        max := c.npages * pageSize
 
+       // As reported in [1], if n and d are unsigned N-bit integers, we
+       // can compute n / d as ⌊n * c / 2^F⌋, where c is ⌈2^F / d⌉ and F is
+       // computed with:
+       //
+       //      Algorithm 2: Algorithm to select the number of fractional bits
+       //      and the scaled approximate reciprocal in the case of unsigned
+       //      integers.
+       //
+       //      if d is a power of two then
+       //              Let F ← log₂(d) and c = 1.
+       //      else
+       //              Let F ← N + L where L is the smallest integer
+       //              such that d ≤ (2^(N+L) mod d) + 2^L.
+       //      end if
+       //
+       // [1] "Faster Remainder by Direct Computation: Applications to
+       // Compilers and Software Libraries" Daniel Lemire, Owen Kaser,
+       // Nathan Kurz arXiv:1902.01961
+       //
+       // To minimize the risk of introducing errors, we implement the
+       // algorithm exactly as stated, rather than trying to adapt it to
+       // fit typical Go idioms.
+       N := bits.Len(uint(max))
+       var F int
        if powerOfTwo(d) {
-               // If the size is a power of two, heapBitsForObject can divide even faster by masking.
-               // Compute this mask.
-               if max >= 1<<16 {
-                       panic("max too big for power of two size")
+               F = int(math.Log2(float64(d)))
+               if d != 1<<F {
+                       panic("imprecise log2")
                }
-               c.mask = 1<<16 - d
-       }
-
-       // Compute pre-shift by factoring power of 2 out of d.
-       for d%2 == 0 {
-               c.shift++
-               d >>= 1
-               max >>= 1
-       }
-
-       // Find the smallest k that works.
-       // A small k allows us to fit the math required into 32 bits
-       // so we can use 32-bit multiplies and shifts on 32-bit platforms.
-nextk:
-       for k := uint(0); ; k++ {
-               mul := (int(1)<<k + d - 1) / d //  ⌈2^k / d⌉
-
-               // Test to see if mul works.
-               for n := 0; n <= max; n++ {
-                       if n*mul>>k != n/d {
-                               continue nextk
+       } else {
+               for L := 0; ; L++ {
+                       if d <= ((1<<(N+L))%d)+(1<<L) {
+                               F = N + L
+                               break
                        }
                }
-               if mul >= 1<<16 {
-                       panic("mul too big")
-               }
-               if uint64(mul)*uint64(max) >= 1<<32 {
-                       panic("mul*max too big")
-               }
-               c.mul = mul
-               c.shift2 = k
-               break
        }
 
-       // double-check.
+       // Also, noted in the paper, F is the smallest number of fractional
+       // bits required. We use 32 bits, because it works for all size
+       // classes and is fast on all CPU architectures that we support.
+       if F > 32 {
+               fmt.Printf("d=%d max=%d N=%d F=%d\n", c.size, max, N, F)
+               panic("size class requires more than 32 bits of precision")
+       }
+
+       // Brute force double-check with the exact computation that will be
+       // done by the runtime.
+       m := ^uint32(0)/uint32(c.size) + 1
        for n := 0; n <= max; n++ {
-               if n*c.mul>>c.shift2 != n/d {
-                       fmt.Printf("d=%d max=%d mul=%d shift2=%d n=%d\n", d, max, c.mul, c.shift2, n)
-                       panic("bad multiply magic")
-               }
-               // Also check the exact computations that will be done by the runtime,
-               // for both 32 and 64 bit operations.
-               if uint32(n)*uint32(c.mul)>>uint8(c.shift2) != uint32(n/d) {
-                       fmt.Printf("d=%d max=%d mul=%d shift2=%d n=%d\n", d, max, c.mul, c.shift2, n)
+               if uint32((uint64(n)*uint64(m))>>32) != uint32(n/c.size) {
+                       fmt.Printf("d=%d max=%d m=%d n=%d\n", d, max, m, n)
                        panic("bad 32-bit multiply magic")
                }
-               if uint64(n)*uint64(c.mul)>>uint8(c.shift2) != uint64(n/d) {
-                       fmt.Printf("d=%d max=%d mul=%d shift2=%d n=%d\n", d, max, c.mul, c.shift2, n)
-                       panic("bad 64-bit multiply magic")
-               }
        }
 }
 
 func printComment(w io.Writer, classes []class) {
-       fmt.Fprintf(w, "// %-5s  %-9s  %-10s  %-7s  %-10s  %-9s\n", "class", "bytes/obj", "bytes/span", "objects", "tail waste", "max waste")
+       fmt.Fprintf(w, "// %-5s  %-9s  %-10s  %-7s  %-10s  %-9s  %-9s\n", "class", "bytes/obj", "bytes/span", "objects", "tail waste", "max waste", "min align")
        prevSize := 0
+       var minAligns [pageShift + 1]int
        for i, c := range classes {
                if i == 0 {
                        continue
@@ -251,8 +248,32 @@ func printComment(w io.Writer, classes []class) {
                objects := spanSize / c.size
                tailWaste := spanSize - c.size*(spanSize/c.size)
                maxWaste := float64((c.size-prevSize-1)*objects+tailWaste) / float64(spanSize)
+               alignBits := bits.TrailingZeros(uint(c.size))
+               if alignBits > pageShift {
+                       // object alignment is capped at page alignment
+                       alignBits = pageShift
+               }
+               for i := range minAligns {
+                       if i > alignBits {
+                               minAligns[i] = 0
+                       } else if minAligns[i] == 0 {
+                               minAligns[i] = c.size
+                       }
+               }
                prevSize = c.size
-               fmt.Fprintf(w, "// %5d  %9d  %10d  %7d  %10d  %8.2f%%\n", i, c.size, spanSize, objects, tailWaste, 100*maxWaste)
+               fmt.Fprintf(w, "// %5d  %9d  %10d  %7d  %10d  %8.2f%%  %9d\n", i, c.size, spanSize, objects, tailWaste, 100*maxWaste, 1<<alignBits)
+       }
+       fmt.Fprintf(w, "\n")
+
+       fmt.Fprintf(w, "// %-9s  %-4s  %-12s\n", "alignment", "bits", "min obj size")
+       for bits, size := range minAligns {
+               if size == 0 {
+                       break
+               }
+               if bits+1 < len(minAligns) && size == minAligns[bits+1] {
+                       continue
+               }
+               fmt.Fprintf(w, "// %9d  %4d  %12d\n", 1<<bits, bits, size)
        }
        fmt.Fprintf(w, "\n")
 }
@@ -279,15 +300,13 @@ func printClasses(w io.Writer, classes []class) {
        }
        fmt.Fprintln(w, "}")
 
-       fmt.Fprintln(w, "type divMagic struct {")
-       fmt.Fprintln(w, "  shift uint8")
-       fmt.Fprintln(w, "  shift2 uint8")
-       fmt.Fprintln(w, "  mul uint16")
-       fmt.Fprintln(w, "  baseMask uint16")
-       fmt.Fprintln(w, "}")
-       fmt.Fprint(w, "var class_to_divmagic = [_NumSizeClasses]divMagic {")
+       fmt.Fprint(w, "var class_to_divmagic = [_NumSizeClasses]uint32 {")
        for _, c := range classes {
-               fmt.Fprintf(w, "{%d,%d,%d,%d},", c.shift, c.shift2, c.mul, c.mask)
+               if c.size == 0 {
+                       fmt.Fprintf(w, "0,")
+                       continue
+               }
+               fmt.Fprintf(w, "^uint32(0)/%d+1,", c.size)
        }
        fmt.Fprintln(w, "}")
 
index dac1f39969090f2d65d73c6f80152806d939a6ab..071f1fc27499cf9f9c043c80c2049f10b1e0c568 100644 (file)
@@ -395,6 +395,9 @@ func (p *pageAlloc) grow(base, size uintptr) {
                        // Store it atomically to avoid races with readers which
                        // don't acquire the heap lock.
                        r := sysAlloc(unsafe.Sizeof(*p.chunks[0]), p.sysStat)
+                       if r == nil {
+                               throw("pageAlloc: out of memory")
+                       }
                        atomic.StorepNoWB(unsafe.Pointer(&p.chunks[c.l1()]), r)
                }
                p.chunkOf(c).scavenged.setRange(0, pallocChunkPages)
index e721c3848ea2c5588506c1016a17b7c1cee66ae0..07415461701b91eae761bf2a225ccb2a7eec4cbd 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build 386 || arm || mips || mipsle || wasm || (ios && arm64) || amd64p32 || armbe || m68k || mips64p32 || mips64p32le || nios2 || ppc || riscv || s390 || sh || shbe || sparc
 // +build 386 arm mips mipsle wasm ios,arm64 amd64p32 armbe m68k mips64p32 mips64p32le nios2 ppc riscv s390 sh shbe sparc
 
 // wasm is a treated as a 32-bit architecture for the purposes of the page
index 4d4257a8c0a1887ad2cf5ee7f00d90340a6439d5..729a4eb9b798f0baa9eebe3350c544b392c9713d 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build amd64 || (!ios && arm64) || mips64 || mips64le || ppc64 || ppc64le || riscv64 || s390x || arm64be || alpha || sparc64 || ia64
 // +build amd64 !ios,arm64 mips64 mips64le ppc64 ppc64le riscv64 s390x arm64be alpha sparc64 ia64
 
 // See mpagealloc_32bit.go for why ios/arm64 is excluded here.
index afacf8fa70f50f388cee156e421e86b239e94c53..9b115973ee345637ee92f2f2c567df9cdc77b475 100644 (file)
@@ -12,6 +12,10 @@ import (
        "unsafe"
 )
 
+// For gofrontend, use go:linkname for blockevent so that
+// runtime/pprof/pprof_test can call it.
+//go:linkname blockevent
+
 // NOTE(rsc): Everything here could use cas if contention became an issue.
 var proflock mutex
 
@@ -138,7 +142,7 @@ func (a *memRecordCycle) add(b *memRecordCycle) {
 // A blockRecord is the bucket data for a bucket of type blockProfile,
 // which is used in blocking and mutex profiles.
 type blockRecord struct {
-       count  int64
+       count  float64
        cycles int64
 }
 
@@ -431,20 +435,23 @@ func blockevent(cycles int64, skip int) {
        if cycles <= 0 {
                cycles = 1
        }
-       if blocksampled(cycles) {
-               saveblockevent(cycles, skip+1, blockProfile)
+
+       rate := int64(atomic.Load64(&blockprofilerate))
+       if blocksampled(cycles, rate) {
+               saveblockevent(cycles, rate, skip+1, blockProfile)
        }
 }
 
-func blocksampled(cycles int64) bool {
-       rate := int64(atomic.Load64(&blockprofilerate))
+// blocksampled returns true for all events where cycles >= rate. Shorter
+// events have a cycles/rate random chance of returning true.
+func blocksampled(cycles, rate int64) bool {
        if rate <= 0 || (rate > cycles && int64(fastrand())%rate > cycles) {
                return false
        }
        return true
 }
 
-func saveblockevent(cycles int64, skip int, which bucketType) {
+func saveblockevent(cycles, rate int64, skip int, which bucketType) {
        gp := getg()
        var nstk int
        var stk [maxStack]uintptr
@@ -457,8 +464,15 @@ func saveblockevent(cycles int64, skip int, which bucketType) {
        }
        lock(&proflock)
        b := stkbucket(which, 0, skip, stk[:nstk], true)
-       b.bp().count++
-       b.bp().cycles += cycles
+
+       if which == blockProfile && cycles < rate {
+               // Remove sampling bias, see discussion on http://golang.org/cl/299991.
+               b.bp().count += float64(rate) / float64(cycles)
+               b.bp().cycles += rate
+       } else {
+               b.bp().count++
+               b.bp().cycles += cycles
+       }
        unlock(&proflock)
 }
 
@@ -489,7 +503,7 @@ func mutexevent(cycles int64, skip int) {
        // TODO(pjw): measure impact of always calling fastrand vs using something
        // like malloc.go:nextSample()
        if rate > 0 && int64(fastrand())%rate == 0 {
-               saveblockevent(cycles, skip+1, mutexProfile)
+               saveblockevent(cycles, rate, skip+1, mutexProfile)
        }
 }
 
@@ -525,7 +539,22 @@ func (r *StackRecord) Stack() []uintptr {
 // memory profiling rate should do so just once, as early as
 // possible in the execution of the program (for example,
 // at the beginning of main).
-var MemProfileRate int = 512 * 1024
+var MemProfileRate int = defaultMemProfileRate(512 * 1024)
+
+// defaultMemProfileRate returns 0 if disableMemoryProfiling is set.
+// It exists primarily for the godoc rendering of MemProfileRate
+// above.
+func defaultMemProfileRate(v int) int {
+       if disableMemoryProfiling {
+               return 0
+       }
+       return v
+}
+
+// disableMemoryProfiling is set by the linker if runtime.MemProfile
+// is not used and the link type guarantees nobody else could use it
+// elsewhere.
+var disableMemoryProfiling bool
 
 // A MemProfileRecord describes the live objects allocated
 // by a particular call sequence (stack trace).
@@ -722,9 +751,8 @@ func fixupBucket(b *bucket) {
                rawrecord := b.mp()
                cb.mp().active.add(&rawrecord.active)
        case blockProfile, mutexProfile:
-               bpcount := b.bp().count
-               cb.bp().count += bpcount
-               cb.bp().cycles += bpcount
+               cb.bp().count += b.bp().count
+               cb.bp().cycles += b.bp().cycles
        }
 }
 
@@ -866,7 +894,12 @@ func harvestBlockMutexProfile(buckets *bucket, p []BlockProfileRecord) (n int, o
                for b := sbuckets; b != nil; b = b.allnext {
                        bp := b.bp()
                        r := &p[0]
-                       r.Count = bp.count
+                       r.Count = int64(bp.count)
+                       // Prevent callers from having to worry about division by zero errors.
+                       // See discussion on http://golang.org/cl/299991.
+                       if r.Count == 0 {
+                               r.Count = 1
+                       }
                        r.Cycles = bp.cycles
                        i := 0
                        var pc uintptr
@@ -962,12 +995,13 @@ func goroutineProfileWithLabels(p []StackRecord, labels []unsafe.Pointer) (n int
 
        stopTheWorld("profile")
 
+       // World is stopped, no locking required.
        n = 1
-       for _, gp1 := range allgs {
+       forEachGRace(func(gp1 *g) {
                if isOK(gp1) {
                        n++
                }
-       }
+       })
 
        if n <= len(p) {
                ok = true
@@ -984,21 +1018,23 @@ func goroutineProfileWithLabels(p []StackRecord, labels []unsafe.Pointer) (n int
                }
 
                // Save other goroutines.
-               for _, gp1 := range allgs {
+               forEachGRace(func(gp1 *g) {
                        if isOK(gp1) {
-                               if len(r) == 0 {
-                                       // Should be impossible, but better to return a
-                                       // truncated profile than to crash the entire process.
-                                       break
-                               }
-                               saveg(gp1, &r[0])
-                               if labels != nil {
-                                       lbl[0] = gp1.labels
-                                       lbl = lbl[1:]
-                               }
-                               r = r[1:]
+                               return
                        }
-               }
+
+                       if len(r) == 0 {
+                               // Should be impossible, but better to return a
+                               // truncated profile than to crash the entire process.
+                               return
+                       }
+                       saveg(gp1, &r[0])
+                       if labels != nil {
+                               lbl[0] = gp1.labels
+                               lbl = lbl[1:]
+                       }
+                       r = r[1:]
+               })
        }
 
        startTheWorld()
index 374d13f30b516978a1154ea7e932f55a9d1af492..b1096a6750e5d249dc132c92acf755ed7fe7fcce 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !msan
 // +build !msan
 
 // Dummy MSan support API, used when not built with -msan.
index 488e5d1eba1dffc9236bea2bafceab770342df96..535b78a1cf6c151d8bb9c1ee85363548eb082c01 100644 (file)
@@ -8,6 +8,7 @@ package runtime
 
 import (
        "runtime/internal/atomic"
+       "runtime/internal/sys"
        "unsafe"
 )
 
@@ -62,12 +63,6 @@ type mstats struct {
 
        // Statistics about the garbage collector.
 
-       // next_gc is the goal heap_live for when next GC ends.
-       // Set to ^uint64(0) if disabled.
-       //
-       // Read and written atomically, unless the world is stopped.
-       next_gc uint64
-
        // Protected by mheap or stopping the world during GC.
        last_gc_unix    uint64 // last gc (in unix time)
        pause_total_ns  uint64
@@ -92,69 +87,8 @@ type mstats struct {
        _ [1 - _NumSizeClasses%2]uint32
 
        last_gc_nanotime uint64 // last gc (monotonic time)
-       tinyallocs       uint64 // number of tiny allocations that didn't cause actual allocation; not exported to go directly
-       last_next_gc     uint64 // next_gc for the previous GC
        last_heap_inuse  uint64 // heap_inuse at mark termination of the previous GC
 
-       // triggerRatio is the heap growth ratio that triggers marking.
-       //
-       // E.g., if this is 0.6, then GC should start when the live
-       // heap has reached 1.6 times the heap size marked by the
-       // previous cycle. This should be ≤ GOGC/100 so the trigger
-       // heap size is less than the goal heap size. This is set
-       // during mark termination for the next cycle's trigger.
-       triggerRatio float64
-
-       // gc_trigger is the heap size that triggers marking.
-       //
-       // When heap_live ≥ gc_trigger, the mark phase will start.
-       // This is also the heap size by which proportional sweeping
-       // must be complete.
-       //
-       // This is computed from triggerRatio during mark termination
-       // for the next cycle's trigger.
-       gc_trigger uint64
-
-       // heap_live is the number of bytes considered live by the GC.
-       // That is: retained by the most recent GC plus allocated
-       // since then. heap_live <= alloc, since alloc includes unmarked
-       // objects that have not yet been swept (and hence goes up as we
-       // allocate and down as we sweep) while heap_live excludes these
-       // objects (and hence only goes up between GCs).
-       //
-       // This is updated atomically without locking. To reduce
-       // contention, this is updated only when obtaining a span from
-       // an mcentral and at this point it counts all of the
-       // unallocated slots in that span (which will be allocated
-       // before that mcache obtains another span from that
-       // mcentral). Hence, it slightly overestimates the "true" live
-       // heap size. It's better to overestimate than to
-       // underestimate because 1) this triggers the GC earlier than
-       // necessary rather than potentially too late and 2) this
-       // leads to a conservative GC rate rather than a GC rate that
-       // is potentially too low.
-       //
-       // Reads should likewise be atomic (or during STW).
-       //
-       // Whenever this is updated, call traceHeapAlloc() and
-       // gcController.revise().
-       heap_live uint64
-
-       // heap_scan is the number of bytes of "scannable" heap. This
-       // is the live heap (as counted by heap_live), but omitting
-       // no-scan objects and no-scan tails of objects.
-       //
-       // Whenever this is updated, call gcController.revise().
-       //
-       // Read and written atomically or with the world stopped.
-       heap_scan uint64
-
-       // heap_marked is the number of bytes marked by the previous
-       // GC. After mark termination, heap_live == heap_marked, but
-       // unlike heap_live, heap_marked does not change until the
-       // next mark termination.
-       heap_marked uint64
-
        // heapStats is a set of statistics
        heapStats consistentHeapStats
 
@@ -443,10 +377,6 @@ type MemStats struct {
 }
 
 func init() {
-       if offset := unsafe.Offsetof(memstats.heap_live); offset%8 != 0 {
-               println(offset)
-               throw("memstats.heap_live not aligned to 8 bytes")
-       }
        if offset := unsafe.Offsetof(memstats.heapStats); offset%8 != 0 {
                println(offset)
                throw("memstats.heapStats not aligned to 8 bytes")
@@ -523,7 +453,7 @@ func readmemstats_m(stats *MemStats) {
        // at a more granular level in the runtime.
        stats.GCSys = memstats.gcMiscSys.load() + memstats.gcWorkBufInUse + memstats.gcProgPtrScalarBitsInUse
        stats.OtherSys = memstats.other_sys.load()
-       stats.NextGC = memstats.next_gc
+       stats.NextGC = gcController.heapGoal
        stats.LastGC = memstats.last_gc_unix
        stats.PauseTotalNs = memstats.pause_total_ns
        stats.PauseNs = memstats.pause_ns
@@ -656,8 +586,8 @@ func updatememstats() {
        }
 
        // Account for tiny allocations.
-       memstats.nfree += memstats.tinyallocs
-       memstats.nmalloc += memstats.tinyallocs
+       memstats.nfree += uint64(consStats.tinyAllocCount)
+       memstats.nmalloc += uint64(consStats.tinyAllocCount)
 
        // Calculate derived stats.
        memstats.total_alloc = totalAlloc
@@ -772,6 +702,7 @@ type heapStatsDelta struct {
        inPtrScalarBits int64 // byte delta of memory reserved for unrolled GC prog bits
 
        // Allocator stats.
+       tinyAllocCount  uintptr                  // number of tiny allocations
        largeAlloc      uintptr                  // bytes allocated for large objects
        largeAllocCount uintptr                  // number of large object allocations
        smallAllocCount [_NumSizeClasses]uintptr // number of allocs for small objects
@@ -781,7 +712,7 @@ type heapStatsDelta struct {
 
        // Add a uint32 to ensure this struct is a multiple of 8 bytes in size.
        // Only necessary on 32-bit platforms.
-       // _ [(sys.PtrSize / 4) % 2]uint32
+       _ [(sys.PtrSize / 4) % 2]uint32
 }
 
 // merge adds in the deltas from b into a.
@@ -793,6 +724,7 @@ func (a *heapStatsDelta) merge(b *heapStatsDelta) {
        a.inWorkBufs += b.inWorkBufs
        a.inPtrScalarBits += b.inPtrScalarBits
 
+       a.tinyAllocCount += b.tinyAllocCount
        a.largeAlloc += b.largeAlloc
        a.largeAllocCount += b.largeAllocCount
        for i := range b.smallAllocCount {
index 822b2944dbf9c97d3bf1fa87dba4fa57cc743225..b17257e9ec3649ba4cf5eebe671f5897648d5e88 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build aix darwin dragonfly
+//go:build aix || darwin
+// +build aix darwin
 
 package runtime
 
index 76fb40c460a67b5653daa1b2c971e9c93da8670e..34ead010a30022900242eab93b5c75937a6ffe64 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build freebsd hurd linux netbsd openbsd solaris
 
 package runtime
index d7c5d45c854be6ab0628de6488d4d9a432fe48c6..22d41cd1caaf65f6497e46ab8c64fbd38bfea29c 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package runtime_test
index 879112a728d6b84cacddd6152a635122aa393f3a..82380f6a85b43c126744ecdde61b0578b750cdaf 100644 (file)
@@ -26,6 +26,9 @@ import (
 //     Arm edge-triggered notifications for fd. The pd argument is to pass
 //     back to netpollready when fd is ready. Return an errno value.
 //
+// func netpollclose(fd uintptr) int32
+//     Disable notifications for fd. Return an errno value.
+//
 // func netpoll(delta int64) gList
 //     Poll the network. If delta < 0, block indefinitely. If delta == 0,
 //     poll without blocking. If delta > 0, block for up to delta nanoseconds.
@@ -165,9 +168,12 @@ func poll_runtime_pollOpen(fd uintptr) (uintptr, int) {
        pd.self = pd
        unlock(&pd.lock)
 
-       var errno int32
-       errno = netpollopen(fd, pd)
-       return uintptr(unsafe.Pointer(pd)), int(errno)
+       errno := netpollopen(fd, pd)
+       if errno != 0 {
+               pollcache.free(pd)
+               return 0, int(errno)
+       }
+       return uintptr(unsafe.Pointer(pd)), 0
 }
 
 //go:linkname poll_runtime_pollClose internal_1poll.runtime__pollClose
index 9c5d33851cb3ee673ce3d989534427f42245d418..60a1dc00d3a088e0663a620615065d1bf3904a03 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build linux
 // +build linux
 
 package runtime
index b2af3b89b2c51c034d4e5271a5b2b11693e852e6..8366f289144cf4f377d6e7ed94271d3caadca56c 100644 (file)
@@ -5,6 +5,7 @@
 // Fake network poller for wasm/js.
 // Should never be used, because wasm/js network connections do not honor "SetNonblock".
 
+//go:build js && wasm
 // +build js,wasm
 
 package runtime
index 1724f37e7322758ede422f1ac9daac0757caa12a..1e1b110a74ca826c5e23ac65fd7727c5fc5b6297 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || netbsd || openbsd
 // +build darwin dragonfly freebsd netbsd openbsd
 
 package runtime
index 3599f2d01b7a2b968ac7d90fdd3c6ede7d52babf..33ab8eba58cc48a36f81763b8559f67b26b9a858 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build plan9
 // +build plan9
 
 package runtime
index e90128bb6d412a866656713b42a949c28f186583..9ad5dde3829924d338010a2e7df96b70a8784d3f 100644 (file)
@@ -3,6 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // The file contains tests that cannot run under race detector for some reason.
+//go:build !race
 // +build !race
 
 package runtime_test
index d902ae04dc988c214e013b946f00554f2d6cee1f..390fefaf7d376d65ccbc0d00711ab749c32c09e8 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix
 // +build aix
 
 package runtime
index 58e0412600ce642a98ee91d011cb9cd209490bed..0ae716c42d7746f78670bf577fe546e4268af842 100644 (file)
@@ -4,7 +4,9 @@
 
 package runtime
 
-import "unsafe"
+import (
+       "unsafe"
+)
 
 type mOS struct {
        initialized bool
@@ -115,10 +117,15 @@ func sigNoteWakeup(*note) {
 
 // sigNoteSleep waits for a note created by sigNoteSetup to be woken.
 func sigNoteSleep(*note) {
-       entersyscallblock()
-       var b byte
-       read(sigNoteRead, unsafe.Pointer(&b), 1)
-       exitsyscall()
+       for {
+               var b byte
+               entersyscallblock()
+               n := read(sigNoteRead, unsafe.Pointer(&b), 1)
+               exitsyscall()
+               if n != -_EINTR {
+                       return
+               }
+       }
 }
 
 // BSD interface for threading.
index 65d7aef165a94c4ce515019d14efa3c25487c1d8..da12c35d26c91064c0b37103db3f509ee5664db6 100644 (file)
@@ -97,3 +97,11 @@ func setNonblock(fd int32) {
                fcntlUintptr(uintptr(fd), _F_SETFL, flags|_O_NONBLOCK)
        }
 }
+
+// For gccgo this is in the C code.
+func osyield()
+
+//go:nosplit
+func osyield_no_g() {
+       osyield()
+}
index 24261e88a2060310ea155375c1e17673ebc9c9c3..52b64e76027648239fe16ed75a6a95334bc82f2e 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build js && wasm
 // +build js,wasm
 
 package runtime
@@ -30,12 +31,22 @@ func wasmWrite(fd uintptr, p unsafe.Pointer, n int32)
 
 func usleep(usec uint32)
 
+//go:nosplit
+func usleep_no_g(usec uint32) {
+       usleep(usec)
+}
+
 func exitThread(wait *uint32)
 
 type mOS struct{}
 
 func osyield()
 
+//go:nosplit
+func osyield_no_g() {
+       osyield()
+}
+
 const _SIGSEGV = 0xb
 
 func sigpanic() {
index 3844620b20345cbbae145ebeac8c6e23f96aa00c..2b51a2a5176942c460999bea42f0a5047b66404e 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build arm64
 // +build arm64
 
 package runtime
index f9059382757c804b614b171102b56e97e1effd55..bc85ab3b8f709483f7b4b03ee74875441f37b0f3 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build linux && (mips64 || mips64le)
 // +build linux
 // +build mips64 mips64le
 
index 2bfd6f40cc9ac42e54ef623965217fc862a1e43f..be31f191f1fdfe165445fb12e38e38198d94a5c5 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build linux && (mips || mipsle)
 // +build linux
 // +build mips mipsle
 
index 895b4cd5f44cb610c996a6bb1f3ae6e63b2a68e2..59b5aacaebc318a142d4e8cc0bcdcf143c5ac66e 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build linux
-// +build !arm,!arm64,!mips,!mipsle,!mips64,!mips64le,!s390x,!ppc64,!ppc64le
+//go:build linux && !arm && !arm64 && !mips && !mipsle && !mips64 && !mips64le && !s390x && !ppc64 && !ppc64le
+// +build linux,!arm,!arm64,!mips,!mipsle,!mips64,!mips64le,!s390x,!ppc64,!ppc64le
 
 package runtime
 
index cc79cc4a66c3110638a10a96cdf7cec669881c4f..43a75c71004bfdbc4b5822a5be439eac18957b22 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build linux && (ppc64 || ppc64le)
 // +build linux
 // +build ppc64 ppc64le
 
index e2f5409354d6cd796de3192563d7efe7a0eead6f..3829683c807186b38ae75c84bccb22a641658ac4 100644 (file)
@@ -4,6 +4,7 @@
 
 // Solaris code that doesn't also apply to illumos.
 
+//go:build !illumos
 // +build !illumos
 
 package runtime
diff --git a/libgo/go/runtime/os_windows_arm64.go b/libgo/go/runtime/os_windows_arm64.go
new file mode 100644 (file)
index 0000000..7e41344
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+//go:nosplit
+func cputicks() int64 {
+       var counter int64
+       stdcall1(_QueryPerformanceCounter, uintptr(unsafe.Pointer(&counter)))
+       return counter
+}
index fa314afc20a3f9f9ba4f4e8759f28a3646442bae..a2bf7e8fa2a1ac13e1bfb139626988e88d2b961f 100644 (file)
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build 386 || arm || mips || mipsle || armbe || m68k || nios2 || ppc || riscv || s390 || sh || shbe || sparc
+// +build 386 arm mips mipsle armbe m68k nios2 ppc riscv s390 sh shbe sparc
+
 package runtime
 
 import _ "unsafe" // for go:linkname
index 9551ea726f2c78983c159a2cc84400346a33218b..6a448a7561467d5a0ed3a7bfe116e8e158850d55 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js
 // +build !js
 
 package pprof
@@ -85,6 +86,17 @@ func TestMemoryProfiler(t *testing.T) {
 
        runtime.GC() // materialize stats
 
+       // TODO(mknyszek): Fix #45315 and remove this extra call.
+       //
+       // Unfortunately, it's possible for the sweep termination condition
+       // to flap, so with just one runtime.GC call, a freed object could be
+       // missed, leading this test to fail. A second call reduces the chance
+       // of this happening to zero, because sweeping actually has to finish
+       // to move on to the next GC, during which nothing will happen.
+       //
+       // See #46500 for more details.
+       runtime.GC()
+
        memoryProfilerRun++
 
        tests := []struct {
@@ -93,33 +105,33 @@ func TestMemoryProfiler(t *testing.T) {
        }{{
                stk: []string{"runtime/pprof.allocatePersistent1K", "runtime/pprof.TestMemoryProfiler"},
                legacy: fmt.Sprintf(`%v: %v \[%v: %v\] @ 0x[0-9,a-f x]+
-#      0x[0-9,a-f]+    runtime/pprof\.allocatePersistent1K\+0x[0-9,a-f]+       .*/mprof_test\.go:47
-#      0x[0-9,a-f]+    runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test\.go:82
+#      0x[0-9,a-f]+    runtime/pprof\.allocatePersistent1K\+0x[0-9,a-f]+       .*/mprof_test\.go:48
+#      0x[0-9,a-f]+    runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test\.go:83
 `, 32*memoryProfilerRun, 1024*memoryProfilerRun, 32*memoryProfilerRun, 1024*memoryProfilerRun),
        }, {
                stk: []string{"runtime/pprof.allocateTransient1M", "runtime/pprof.TestMemoryProfiler"},
                legacy: fmt.Sprintf(`(0|%v): (0|%v) \[%v: %v\] @ 0x[0-9,a-f x]+
-#      0x[0-9,a-f]+    runtime/pprof\.allocateTransient1M\+0x[0-9,a-f]+        .*/mprof_test.go:24
-#      0x[0-9,a-f]+    runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:79
+#      0x[0-9,a-f]+    runtime/pprof\.allocateTransient1M\+0x[0-9,a-f]+        .*/mprof_test.go:25
+#      0x[0-9,a-f]+    runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:80
 `, (1<<10)*memoryProfilerRun, (1<<20)*memoryProfilerRun, (1<<10)*memoryProfilerRun, (1<<20)*memoryProfilerRun),
        }, {
                stk: []string{"runtime/pprof.allocateTransient2M", "runtime/pprof.TestMemoryProfiler"},
                // This should start with "0: 0" but gccgo's imprecise
                // GC means that sometimes the value is not collected.
                legacy: fmt.Sprintf(`(0|%v): (0|%v) \[%v: %v\] @ 0x[0-9,a-f x]+
-#      0x[0-9,a-f]+    runtime/pprof\.allocateTransient2M\+0x[0-9,a-f]+        .*/mprof_test.go:30
-#      0x[0-9,a-f]+    runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:80
+#      0x[0-9,a-f]+    runtime/pprof\.allocateTransient2M\+0x[0-9,a-f]+        .*/mprof_test.go:31
+#      0x[0-9,a-f]+    runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:81
 `, memoryProfilerRun, (2<<20)*memoryProfilerRun, memoryProfilerRun, (2<<20)*memoryProfilerRun),
        }, {
                stk: []string{"runtime/pprof.allocateTransient2MInline", "runtime/pprof.TestMemoryProfiler"},
                legacy: fmt.Sprintf(`(0|%v): (0|%v) \[%v: %v\] @ 0x[0-9,a-f x]+
-#      0x[0-9,a-f]+    runtime/pprof\.allocateTransient2MInline\+0x[0-9,a-f]+  .*/mprof_test.go:34
-#      0x[0-9,a-f]+    runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:81
+#      0x[0-9,a-f]+    runtime/pprof\.allocateTransient2MInline\+0x[0-9,a-f]+  .*/mprof_test.go:35
+#      0x[0-9,a-f]+    runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:82
 `, memoryProfilerRun, (4<<20)*memoryProfilerRun, memoryProfilerRun, (4<<20)*memoryProfilerRun),
        }, {
                stk: []string{"runtime/pprof.allocateReflectTransient"},
                legacy: fmt.Sprintf(`(0|%v): (0|%v) \[%v: %v\] @( 0x[0-9,a-f]+)+
-#      0x[0-9,a-f]+    runtime/pprof\.allocateReflectTransient\+0x[0-9,a-f]+   .*/mprof_test.go:55
+#      0x[0-9,a-f]+    runtime/pprof\.allocateReflectTransient\+0x[0-9,a-f]+   .*/mprof_test.go:56
 `, memoryProfilerRun, (3<<20)*memoryProfilerRun, memoryProfilerRun, (3<<20)*memoryProfilerRun),
        }}
 
index 52df44a5a10bdb5c89e55a91f3a75ffe2845753e..54838fcc50a2c35bf5ccf9fef947885b87502532 100644 (file)
@@ -857,45 +857,7 @@ func countMutex() int {
 
 // writeBlock writes the current blocking profile to w.
 func writeBlock(w io.Writer, debug int) error {
-       var p []runtime.BlockProfileRecord
-       n, ok := runtime.BlockProfile(nil)
-       for {
-               p = make([]runtime.BlockProfileRecord, n+50)
-               n, ok = runtime.BlockProfile(p)
-               if ok {
-                       p = p[:n]
-                       break
-               }
-       }
-
-       sort.Slice(p, func(i, j int) bool { return p[i].Cycles > p[j].Cycles })
-
-       if debug <= 0 {
-               return printCountCycleProfile(w, "contentions", "delay", scaleBlockProfile, p)
-       }
-
-       b := bufio.NewWriter(w)
-       tw := tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
-       w = tw
-
-       fmt.Fprintf(w, "--- contention:\n")
-       fmt.Fprintf(w, "cycles/second=%v\n", runtime_cyclesPerSecond())
-       for i := range p {
-               r := &p[i]
-               fmt.Fprintf(w, "%v %v @", r.Cycles, r.Count)
-               for _, pc := range r.Stack() {
-                       fmt.Fprintf(w, " %#x", pc)
-               }
-               fmt.Fprint(w, "\n")
-               if debug > 0 {
-                       printStackRecord(w, r.Stack(), true)
-               }
-       }
-
-       if tw != nil {
-               tw.Flush()
-       }
-       return b.Flush()
+       return writeProfileInternal(w, debug, "contention", runtime.BlockProfile, scaleBlockProfile)
 }
 
 func scaleBlockProfile(cnt int64, ns float64) (int64, float64) {
@@ -908,12 +870,16 @@ func scaleBlockProfile(cnt int64, ns float64) (int64, float64) {
 
 // writeMutex writes the current mutex profile to w.
 func writeMutex(w io.Writer, debug int) error {
-       // TODO(pjw): too much common code with writeBlock. FIX!
+       return writeProfileInternal(w, debug, "mutex", runtime.MutexProfile, scaleMutexProfile)
+}
+
+// writeProfileInternal writes the current blocking or mutex profile depending on the passed parameters
+func writeProfileInternal(w io.Writer, debug int, name string, runtimeProfile func([]runtime.BlockProfileRecord) (int, bool), scaleProfile func(int64, float64) (int64, float64)) error {
        var p []runtime.BlockProfileRecord
-       n, ok := runtime.MutexProfile(nil)
+       n, ok := runtimeProfile(nil)
        for {
                p = make([]runtime.BlockProfileRecord, n+50)
-               n, ok = runtime.MutexProfile(p)
+               n, ok = runtimeProfile(p)
                if ok {
                        p = p[:n]
                        break
@@ -923,16 +889,18 @@ func writeMutex(w io.Writer, debug int) error {
        sort.Slice(p, func(i, j int) bool { return p[i].Cycles > p[j].Cycles })
 
        if debug <= 0 {
-               return printCountCycleProfile(w, "contentions", "delay", scaleMutexProfile, p)
+               return printCountCycleProfile(w, "contentions", "delay", scaleProfile, p)
        }
 
        b := bufio.NewWriter(w)
        tw := tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
        w = tw
 
-       fmt.Fprintf(w, "--- mutex:\n")
+       fmt.Fprintf(w, "--- %v:\n", name)
        fmt.Fprintf(w, "cycles/second=%v\n", runtime_cyclesPerSecond())
-       fmt.Fprintf(w, "sampling period=%d\n", runtime.SetMutexProfileFraction(-1))
+       if name == "mutex" {
+               fmt.Fprintf(w, "sampling period=%d\n", runtime.SetMutexProfileFraction(-1))
+       }
        for i := range p {
                r := &p[i]
                fmt.Fprintf(w, "%v %v @", r.Cycles, r.Count)
index 6fdcc6cc38dcdb68b65deff2a531f03b70ac9c03..e175dd380cfb62d51f2a48a8baa83a642a977c79 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !darwin && !linux
 // +build !darwin,!linux
 
 package pprof
index 79546738119abe3be39f8fb06b614a7f05001a97..269f21bc2f93c520d7b280af186318ad2a431627 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || linux
 // +build darwin linux
 
 package pprof
index 73d7aaaf9f82c0e13c65d30513c8afb8f2331fa1..ab96b0ced0bbe70cfcad275f9ec1c5a3932ecb32 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js
 // +build !js
 
 package pprof
@@ -13,6 +14,7 @@ import (
        "internal/profile"
        "internal/testenv"
        "io"
+       "math"
        "math/big"
        "os"
        "os/exec"
@@ -23,6 +25,7 @@ import (
        "sync/atomic"
        "testing"
        "time"
+       _ "unsafe"
 )
 
 func cpuHogger(f func(x int) int, y *int, dur time.Duration) {
@@ -257,40 +260,43 @@ func parseProfile(t *testing.T, valBytes []byte, f func(uintptr, []*profile.Loca
        return p
 }
 
+func cpuProfilingBroken() bool {
+       switch runtime.GOOS {
+       case "plan9":
+               // Profiling unimplemented.
+               return true
+       case "aix":
+               // See https://golang.org/issue/45170.
+               return true
+       case "ios", "dragonfly", "netbsd", "illumos", "solaris":
+               // See https://golang.org/issue/13841.
+               return true
+       case "openbsd":
+               if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" {
+                       // See https://golang.org/issue/13841.
+                       return true
+               }
+       }
+
+       return false
+}
+
 // testCPUProfile runs f under the CPU profiler, checking for some conditions specified by need,
 // as interpreted by matches, and returns the parsed profile.
 func testCPUProfile(t *testing.T, matches matchFunc, need []string, avoid []string, f func(dur time.Duration)) *profile.Profile {
        switch runtime.GOOS {
-       case "darwin", "ios":
-               switch runtime.GOARCH {
-               case "arm64":
-                       // nothing
-               default:
-                       out, err := exec.Command("uname", "-a").CombinedOutput()
-                       if err != nil {
-                               t.Fatal(err)
-                       }
-                       vers := string(out)
-                       t.Logf("uname -a: %v", vers)
+       case "darwin":
+               out, err := exec.Command("uname", "-a").CombinedOutput()
+               if err != nil {
+                       t.Fatal(err)
                }
+               vers := string(out)
+               t.Logf("uname -a: %v", vers)
        case "plan9":
                t.Skip("skipping on plan9")
        }
 
-       broken := false
-       switch runtime.GOOS {
-       // See https://golang.org/issue/45170 for AIX.
-       case "darwin", "ios", "dragonfly", "netbsd", "illumos", "solaris", "aix":
-               broken = true
-       case "openbsd":
-               if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" {
-                       broken = true
-               }
-       case "windows":
-               if runtime.GOARCH == "arm" {
-                       broken = true // See https://golang.org/issues/42862
-               }
-       }
+       broken := cpuProfilingBroken()
 
        maxDuration := 5 * time.Second
        if testing.Short() && broken {
@@ -524,8 +530,10 @@ func TestGoroutineSwitch(t *testing.T) {
                }
                StopCPUProfile()
 
-               // Read profile to look for entries for runtime.gogo with an attempt at a traceback.
-               // The special entry
+               // Read profile to look for entries for gogo with an attempt at a traceback.
+               // "runtime.gogo" is OK, because that's the part of the context switch
+               // before the actual switch begins. But we should not see "gogo",
+               // aka "gogo<>(SB)", which does the actual switch and is marked SPWRITE.
                parseProfile(t, prof.Bytes(), func(count uintptr, stk []*profile.Location, _ map[string][]string) {
                        // An entry with two frames with 'System' in its top frame
                        // exists to record a PC without a traceback. Those are okay.
@@ -536,13 +544,19 @@ func TestGoroutineSwitch(t *testing.T) {
                                }
                        }
 
-                       // Otherwise, should not see runtime.gogo.
+                       // An entry with just one frame is OK too:
+                       // it knew to stop at gogo.
+                       if len(stk) == 1 {
+                               return
+                       }
+
+                       // Otherwise, should not see gogo.
                        // The place we'd see it would be the inner most frame.
                        name := stk[0].Line[0].Function.Name
-                       if name == "runtime.gogo" {
+                       if name == "gogo" {
                                var buf bytes.Buffer
                                fprintStack(&buf, stk)
-                               t.Fatalf("found profile entry for runtime.gogo:\n%s", buf.String())
+                               t.Fatalf("found profile entry for gogo:\n%s", buf.String())
                        }
                })
        }
@@ -616,17 +630,20 @@ func TestMorestack(t *testing.T) {
 
 //go:noinline
 func growstack1() {
-       growstack()
+       growstack(10)
 }
 
 //go:noinline
-func growstack() {
-       var buf [8 << 10]byte
+func growstack(n int) {
+       var buf [8 << 18]byte
        use(buf)
+       if n > 0 {
+               growstack(n - 1)
+       }
 }
 
 //go:noinline
-func use(x [8 << 10]byte) {}
+func use(x [8 << 18]byte) {}
 
 func TestBlockProfile(t *testing.T) {
        t.Skip("lots of details are different for gccgo; FIXME")
@@ -905,6 +922,74 @@ func blockCond() {
        mu.Unlock()
 }
 
+// See http://golang.org/cl/299991.
+func TestBlockProfileBias(t *testing.T) {
+       rate := int(1000) // arbitrary value
+       runtime.SetBlockProfileRate(rate)
+       defer runtime.SetBlockProfileRate(0)
+
+       // simulate blocking events
+       blockFrequentShort(rate)
+       blockInfrequentLong(rate)
+
+       var w bytes.Buffer
+       Lookup("block").WriteTo(&w, 0)
+       p, err := profile.Parse(&w)
+       if err != nil {
+               t.Fatalf("failed to parse profile: %v", err)
+       }
+       t.Logf("parsed proto: %s", p)
+
+       il := float64(-1) // blockInfrequentLong duration
+       fs := float64(-1) // blockFrequentShort duration
+       for _, s := range p.Sample {
+               for _, l := range s.Location {
+                       for _, line := range l.Line {
+                               if len(s.Value) < 2 {
+                                       t.Fatal("block profile has less than 2 sample types")
+                               }
+
+                               if line.Function.Name == "runtime/pprof.blockInfrequentLong" {
+                                       il = float64(s.Value[1])
+                               } else if line.Function.Name == "runtime/pprof.blockFrequentShort" {
+                                       fs = float64(s.Value[1])
+                               }
+                       }
+               }
+       }
+       if il == -1 || fs == -1 {
+               t.Fatal("block profile is missing expected functions")
+       }
+
+       // stddev of bias from 100 runs on local machine multiplied by 10x
+       const threshold = 0.2
+       if bias := (il - fs) / il; math.Abs(bias) > threshold {
+               t.Fatalf("bias: abs(%f) > %f", bias, threshold)
+       } else {
+               t.Logf("bias: abs(%f) < %f", bias, threshold)
+       }
+}
+
+// blockFrequentShort produces 100000 block events with an average duration of
+// rate / 10.
+func blockFrequentShort(rate int) {
+       for i := 0; i < 100000; i++ {
+               blockevent(int64(rate/10), 1)
+       }
+}
+
+// blockFrequentShort produces 10000 block events with an average duration of
+// rate.
+func blockInfrequentLong(rate int) {
+       for i := 0; i < 10000; i++ {
+               blockevent(int64(rate), 1)
+       }
+}
+
+// Used by TestBlockProfileBias.
+//go:linkname blockevent runtime.blockevent
+func blockevent(cycles int64, skip int)
+
 func TestMutexProfile(t *testing.T) {
        // Generate mutex profile
 
index 3066a1521eb644aaad772885cbb578d5e4f4b74e..365e86a611a4daa8c56ff827b7ceed5c2ce5887e 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !windows
 // +build !windows
 
 package runtime
index be51ac0c0c2ef606a17b95f695ebe53a3d975c8e..d141061c1587a85035adeccd5e778197a8ad64c5 100644 (file)
@@ -238,13 +238,15 @@ func printint(v int64) {
        printuint(uint64(v))
 }
 
+var minhexdigits = 0 // protected by printlock
+
 func printhex(v uint64) {
        const dig = "0123456789abcdef"
        var buf [100]byte
        i := len(buf)
        for i--; i > 0; i-- {
                buf[i] = dig[v%16]
-               if v < 16 {
+               if v < 16 && len(buf)-i >= minhexdigits {
                        break
                }
                v /= 16
@@ -287,29 +289,16 @@ func printiface(i iface) {
 // and should return a character mark to appear just before that
 // word's value. It can return 0 to indicate no mark.
 func hexdumpWords(p, end uintptr, mark func(uintptr) byte) {
-       p1 := func(x uintptr) {
-               var buf [2 * sys.PtrSize]byte
-               for i := len(buf) - 1; i >= 0; i-- {
-                       if x&0xF < 10 {
-                               buf[i] = byte(x&0xF) + '0'
-                       } else {
-                               buf[i] = byte(x&0xF) - 10 + 'a'
-                       }
-                       x >>= 4
-               }
-               gwrite(buf[:])
-       }
-
        printlock()
        var markbuf [1]byte
        markbuf[0] = ' '
+       minhexdigits = int(unsafe.Sizeof(uintptr(0)) * 2)
        for i := uintptr(0); p+i < end; i += sys.PtrSize {
                if i%16 == 0 {
                        if i != 0 {
                                println()
                        }
-                       p1(p + i)
-                       print(": ")
+                       print(hex(p+i), ": ")
                }
 
                if mark != nil {
@@ -320,16 +309,17 @@ func hexdumpWords(p, end uintptr, mark func(uintptr) byte) {
                }
                gwrite(markbuf[:])
                val := *(*uintptr)(unsafe.Pointer(p + i))
-               p1(val)
+               print(hex(val))
                print(" ")
 
                // Can we symbolize val?
                name, _, _, _ := funcfileline(val, -1, false)
                if name != "" {
                        entry := funcentry(val)
-                       print("<", name, "+", val-entry, "> ")
+                       print("<", name, "+", hex(val-entry), "> ")
                }
        }
+       minhexdigits = 0
        println()
        printunlock()
 }
index 037e7798a3827db5fb26a705e084476e63d9b319..05342905ff1e35871294704a70fcddafb1cd8410 100644 (file)
@@ -68,8 +68,6 @@ func main_init()
 //extern main.main
 func main_main()
 
-var buildVersion = sys.TheVersion
-
 // set using cmd/go/internal/modload.ModInfoProg
 var modinfo string
 
@@ -108,33 +106,64 @@ var modinfo string
 //    any work to do.
 //
 // The current approach:
-// We unpark an additional thread when we ready a goroutine if (1) there is an
-// idle P and there are no "spinning" worker threads. A worker thread is considered
-// spinning if it is out of local work and did not find work in global run queue/
-// netpoller; the spinning state is denoted in m.spinning and in sched.nmspinning.
-// Threads unparked this way are also considered spinning; we don't do goroutine
-// handoff so such threads are out of work initially. Spinning threads do some
-// spinning looking for work in per-P run queues before parking. If a spinning
+//
+// This approach applies to three primary sources of potential work: readying a
+// goroutine, new/modified-earlier timers, and idle-priority GC. See below for
+// additional details.
+//
+// We unpark an additional thread when we submit work if (this is wakep()):
+// 1. There is an idle P, and
+// 2. There are no "spinning" worker threads.
+//
+// A worker thread is considered spinning if it is out of local work and did
+// not find work in the global run queue or netpoller; the spinning state is
+// denoted in m.spinning and in sched.nmspinning. Threads unparked this way are
+// also considered spinning; we don't do goroutine handoff so such threads are
+// out of work initially. Spinning threads spin on looking for work in per-P
+// run queues and timer heaps or from the GC before parking. If a spinning
 // thread finds work it takes itself out of the spinning state and proceeds to
-// execution. If it does not find work it takes itself out of the spinning state
-// and then parks.
-// If there is at least one spinning thread (sched.nmspinning>1), we don't unpark
-// new threads when readying goroutines. To compensate for that, if the last spinning
-// thread finds work and stops spinning, it must unpark a new spinning thread.
-// This approach smooths out unjustified spikes of thread unparking,
-// but at the same time guarantees eventual maximal CPU parallelism utilization.
+// execution. If it does not find work it takes itself out of the spinning
+// state and then parks.
+//
+// If there is at least one spinning thread (sched.nmspinning>1), we don't
+// unpark new threads when submitting work. To compensate for that, if the last
+// spinning thread finds work and stops spinning, it must unpark a new spinning
+// thread.  This approach smooths out unjustified spikes of thread unparking,
+// but at the same time guarantees eventual maximal CPU parallelism
+// utilization.
+//
+// The main implementation complication is that we need to be very careful
+// during spinning->non-spinning thread transition. This transition can race
+// with submission of new work, and either one part or another needs to unpark
+// another worker thread. If they both fail to do that, we can end up with
+// semi-persistent CPU underutilization.
 //
-// The main implementation complication is that we need to be very careful during
-// spinning->non-spinning thread transition. This transition can race with submission
-// of a new goroutine, and either one part or another needs to unpark another worker
-// thread. If they both fail to do that, we can end up with semi-persistent CPU
-// underutilization. The general pattern for goroutine readying is: submit a goroutine
-// to local work queue, #StoreLoad-style memory barrier, check sched.nmspinning.
-// The general pattern for spinning->non-spinning transition is: decrement nmspinning,
-// #StoreLoad-style memory barrier, check all per-P work queues for new work.
-// Note that all this complexity does not apply to global run queue as we are not
-// sloppy about thread unparking when submitting to global queue. Also see comments
-// for nmspinning manipulation.
+// The general pattern for submission is:
+// 1. Submit work to the local run queue, timer heap, or GC state.
+// 2. #StoreLoad-style memory barrier.
+// 3. Check sched.nmspinning.
+//
+// The general pattern for spinning->non-spinning transition is:
+// 1. Decrement nmspinning.
+// 2. #StoreLoad-style memory barrier.
+// 3. Check all per-P work queues and GC for new work.
+//
+// Note that all this complexity does not apply to global run queue as we are
+// not sloppy about thread unparking when submitting to global queue. Also see
+// comments for nmspinning manipulation.
+//
+// How these different sources of work behave varies, though it doesn't affect
+// the synchronization approach:
+// * Ready goroutine: this is an obvious source of work; the goroutine is
+//   immediately ready and must run on some thread eventually.
+// * New/modified-earlier timer: The current timer implementation (see time.go)
+//   uses netpoll in a thread with no work available to wait for the soonest
+//   timer. If there is no thread waiting, we want a new spinning thread to go
+//   wait.
+// * Idle-priority GC: The GC wakes a stopped idle thread to contribute to
+//   background GC work (note: currently disabled per golang.org/issue/19112).
+//   Also see golang.org/issue/44313, as this should be extended to all GC
+//   workers.
 
 var (
        m0           m
@@ -514,8 +543,8 @@ var (
        allglock mutex
        allgs    []*g
 
-       // allglen and allgptr are atomic variables that contain len(allg) and
-       // &allg[0] respectively. Proper ordering depends on totally-ordered
+       // allglen and allgptr are atomic variables that contain len(allgs) and
+       // &allgs[0] respectively. Proper ordering depends on totally-ordered
        // loads and stores. Writes are protected by allglock.
        //
        // allgptr is updated before allglen. Readers should read allglen
@@ -556,6 +585,30 @@ func atomicAllGIndex(ptr **g, i uintptr) *g {
        return *(**g)(add(unsafe.Pointer(ptr), i*sys.PtrSize))
 }
 
+// forEachG calls fn on every G from allgs.
+//
+// forEachG takes a lock to exclude concurrent addition of new Gs.
+func forEachG(fn func(gp *g)) {
+       lock(&allglock)
+       for _, gp := range allgs {
+               fn(gp)
+       }
+       unlock(&allglock)
+}
+
+// forEachGRace calls fn on every G from allgs.
+//
+// forEachGRace avoids locking, but does not exclude addition of new Gs during
+// execution, which may be missed.
+func forEachGRace(fn func(gp *g)) {
+       ptr, length := atomicAllG()
+       for i := uintptr(0); i < length; i++ {
+               gp := atomicAllGIndex(ptr, i)
+               fn(gp)
+       }
+       return
+}
+
 const (
        // Number of goroutine ids to grab from sched.goidgen to local per-P cache at once.
        // 16 seems to provide enough amortization, but other than that it's mostly arbitrary number.
@@ -649,6 +702,11 @@ func schedinit() {
        sigsave(&_g_.m.sigmask)
        initSigmask = _g_.m.sigmask
 
+       if offset := unsafe.Offsetof(sched.timeToRun); offset%8 != 0 {
+               println(offset)
+               throw("sched.timeToRun not aligned to 8 bytes")
+       }
+
        goargs()
        goenvs()
        parsedebugvars()
@@ -925,6 +983,37 @@ func casgstatus(gp *g, oldval, newval uint32) {
                        nextYield = nanotime() + yieldDelay/2
                }
        }
+
+       // Handle tracking for scheduling latencies.
+       if oldval == _Grunning {
+               // Track every 8th time a goroutine transitions out of running.
+               if gp.trackingSeq%gTrackingPeriod == 0 {
+                       gp.tracking = true
+               }
+               gp.trackingSeq++
+       }
+       if gp.tracking {
+               now := nanotime()
+               if oldval == _Grunnable {
+                       // We transitioned out of runnable, so measure how much
+                       // time we spent in this state and add it to
+                       // runnableTime.
+                       gp.runnableTime += now - gp.runnableStamp
+                       gp.runnableStamp = 0
+               }
+               if newval == _Grunnable {
+                       // We just transitioned into runnable, so record what
+                       // time that happened.
+                       gp.runnableStamp = now
+               } else if newval == _Grunning {
+                       // We're transitioning into running, so turn off
+                       // tracking and record how much time we spent in
+                       // runnable.
+                       gp.tracking = false
+                       sched.timeToRun.record(gp.runnableTime)
+                       gp.runnableTime = 0
+               }
+       }
 }
 
 // casGToPreemptScan transitions gp from _Grunning to _Gscan|_Gpreempted.
@@ -1235,6 +1324,9 @@ func kickoff() {
        goexit1()
 }
 
+// The go:noinline is to guarantee the getcallerpc/getcallersp below are safe,
+// so that we can set up g0.sched to return to the call of mstart1 above.
+//go:noinline
 func mstart1() {
        _g_ := getg()
 
@@ -1370,6 +1462,8 @@ found:
        }
        unlock(&sched.lock)
 
+       atomic.Xadd64(&ncgocall, int64(m.ncgocall))
+
        // Release the P.
        handoffp(releasep())
        // After this point we must not have write barriers.
@@ -1661,6 +1755,10 @@ func needm() {
        // Store the original signal mask for use by minit.
        mp.sigmask = sigmask
 
+       // Install TLS on some platforms (previously setg
+       // would do this if necessary).
+       osSetupTLS(mp)
+
        // Install g (= m->curg).
        setg(mp.curg)
 
@@ -1822,7 +1920,7 @@ func lockextra(nilokay bool) *m {
        for {
                old := atomic.Loaduintptr(&extram)
                if old == locked {
-                       osyield()
+                       osyield_no_g()
                        continue
                }
                if old == 0 && !nilokay {
@@ -1833,13 +1931,13 @@ func lockextra(nilokay bool) *m {
                                atomic.Xadd(&extraMWaiters, 1)
                                incr = true
                        }
-                       usleep(1)
+                       usleep_no_g(1)
                        continue
                }
                if atomic.Casuintptr(&extram, old, locked) {
                        return (*m)(unsafe.Pointer(old))
                }
-               osyield()
+               osyield_no_g()
                continue
        }
 }
@@ -2417,85 +2515,40 @@ top:
                }
        }
 
-       // Steal work from other P's.
+       // Spinning Ms: steal work from other Ps.
+       //
+       // Limit the number of spinning Ms to half the number of busy Ps.
+       // This is necessary to prevent excessive CPU consumption when
+       // GOMAXPROCS>>1 but the program parallelism is low.
        procs := uint32(gomaxprocs)
-       ranTimer := false
-       // If number of spinning M's >= number of busy P's, block.
-       // This is necessary to prevent excessive CPU consumption
-       // when GOMAXPROCS>>1 but the program parallelism is low.
-       if !_g_.m.spinning && 2*atomic.Load(&sched.nmspinning) >= procs-atomic.Load(&sched.npidle) {
-               goto stop
-       }
-       if !_g_.m.spinning {
-               _g_.m.spinning = true
-               atomic.Xadd(&sched.nmspinning, 1)
-       }
-       const stealTries = 4
-       for i := 0; i < stealTries; i++ {
-               stealTimersOrRunNextG := i == stealTries-1
-
-               for enum := stealOrder.start(fastrand()); !enum.done(); enum.next() {
-                       if sched.gcwaiting != 0 {
-                               goto top
-                       }
-                       p2 := allp[enum.position()]
-                       if _p_ == p2 {
-                               continue
-                       }
-
-                       // Steal timers from p2. This call to checkTimers is the only place
-                       // where we might hold a lock on a different P's timers. We do this
-                       // once on the last pass before checking runnext because stealing
-                       // from the other P's runnext should be the last resort, so if there
-                       // are timers to steal do that first.
-                       //
-                       // We only check timers on one of the stealing iterations because
-                       // the time stored in now doesn't change in this loop and checking
-                       // the timers for each P more than once with the same value of now
-                       // is probably a waste of time.
-                       //
-                       // timerpMask tells us whether the P may have timers at all. If it
-                       // can't, no need to check at all.
-                       if stealTimersOrRunNextG && timerpMask.read(enum.position()) {
-                               tnow, w, ran := checkTimers(p2, now)
-                               now = tnow
-                               if w != 0 && (pollUntil == 0 || w < pollUntil) {
-                                       pollUntil = w
-                               }
-                               if ran {
-                                       // Running the timers may have
-                                       // made an arbitrary number of G's
-                                       // ready and added them to this P's
-                                       // local run queue. That invalidates
-                                       // the assumption of runqsteal
-                                       // that is always has room to add
-                                       // stolen G's. So check now if there
-                                       // is a local G to run.
-                                       if gp, inheritTime := runqget(_p_); gp != nil {
-                                               return gp, inheritTime
-                                       }
-                                       ranTimer = true
-                               }
-                       }
+       if _g_.m.spinning || 2*atomic.Load(&sched.nmspinning) < procs-atomic.Load(&sched.npidle) {
+               if !_g_.m.spinning {
+                       _g_.m.spinning = true
+                       atomic.Xadd(&sched.nmspinning, 1)
+               }
 
-                       // Don't bother to attempt to steal if p2 is idle.
-                       if !idlepMask.read(enum.position()) {
-                               if gp := runqsteal(_p_, p2, stealTimersOrRunNextG); gp != nil {
-                                       return gp, false
-                               }
-                       }
+               gp, inheritTime, tnow, w, newWork := stealWork(now)
+               now = tnow
+               if gp != nil {
+                       // Successfully stole.
+                       return gp, inheritTime
+               }
+               if newWork {
+                       // There may be new timer or GC work; restart to
+                       // discover.
+                       goto top
+               }
+               if w != 0 && (pollUntil == 0 || w < pollUntil) {
+                       // Earlier timer to wait for.
+                       pollUntil = w
                }
-       }
-       if ranTimer {
-               // Running a timer may have made some goroutine ready.
-               goto top
        }
 
-stop:
-
-       // We have nothing to do. If we're in the GC mark phase, can
-       // safely scan and blacken objects, and have work to do, run
-       // idle-time marking rather than give up the P.
+       // We have nothing to do.
+       //
+       // If we're in the GC mark phase, can safely scan and blacken objects,
+       // and have work to do, run idle-time marking rather than give up the
+       // P.
        if gcBlackenEnabled != 0 && gcMarkWorkAvailable(_p_) {
                node := (*gcBgMarkWorkerNode)(gcBgMarkWorkerPool.pop())
                if node != nil {
@@ -2509,17 +2562,11 @@ stop:
                }
        }
 
-       delta := int64(-1)
-       if pollUntil != 0 {
-               // checkTimers ensures that polluntil > now.
-               delta = pollUntil - now
-       }
-
        // wasm only:
        // If a callback returned and no other goroutine is awake,
        // then wake event handler goroutine which pauses execution
        // until a callback was triggered.
-       gp, otherReady := beforeIdle(delta)
+       gp, otherReady := beforeIdle(now, pollUntil)
        if gp != nil {
                casgstatus(gp, _Gwaiting, _Grunnable)
                if trace.enabled {
@@ -2558,18 +2605,25 @@ stop:
        pidleput(_p_)
        unlock(&sched.lock)
 
-       // Delicate dance: thread transitions from spinning to non-spinning state,
-       // potentially concurrently with submission of new goroutines. We must
-       // drop nmspinning first and then check all per-P queues again (with
-       // #StoreLoad memory barrier in between). If we do it the other way around,
-       // another thread can submit a goroutine after we've checked all run queues
-       // but before we drop nmspinning; as a result nobody will unpark a thread
-       // to run the goroutine.
+       // Delicate dance: thread transitions from spinning to non-spinning
+       // state, potentially concurrently with submission of new work. We must
+       // drop nmspinning first and then check all sources again (with
+       // #StoreLoad memory barrier in between). If we do it the other way
+       // around, another thread can submit work after we've checked all
+       // sources but before we drop nmspinning; as a result nobody will
+       // unpark a thread to run the work.
+       //
+       // This applies to the following sources of work:
+       //
+       // * Goroutines added to a per-P run queue.
+       // * New/modified-earlier timers on a per-P timer heap.
+       // * Idle-priority GC work (barring golang.org/issue/19112).
+       //
        // If we discover new work below, we need to restore m.spinning as a signal
        // for resetspinning to unpark a new worker thread (because there can be more
        // than one starving goroutine). However, if after discovering new work
-       // we also observe no idle Ps, it is OK to just park the current thread:
-       // the system is fully loaded so no spinning threads are required.
+       // we also observe no idle Ps it is OK to skip unparking a new worker
+       // thread: the system is fully loaded so no spinning threads are required.
        // Also see "Worker thread parking/unparking" comment at the top of the file.
        wasSpinning := _g_.m.spinning
        if _g_.m.spinning {
@@ -2577,97 +2631,48 @@ stop:
                if int32(atomic.Xadd(&sched.nmspinning, -1)) < 0 {
                        throw("findrunnable: negative nmspinning")
                }
-       }
 
-       // check all runqueues once again
-       for id, _p_ := range allpSnapshot {
-               if !idlepMaskSnapshot.read(uint32(id)) && !runqempty(_p_) {
-                       lock(&sched.lock)
-                       _p_ = pidleget()
-                       unlock(&sched.lock)
-                       if _p_ != nil {
-                               acquirep(_p_)
-                               if wasSpinning {
-                                       _g_.m.spinning = true
-                                       atomic.Xadd(&sched.nmspinning, 1)
-                               }
-                               goto top
-                       }
-                       break
-               }
-       }
-
-       // Similar to above, check for timer creation or expiry concurrently with
-       // transitioning from spinning to non-spinning. Note that we cannot use
-       // checkTimers here because it calls adjusttimers which may need to allocate
-       // memory, and that isn't allowed when we don't have an active P.
-       for id, _p_ := range allpSnapshot {
-               if timerpMaskSnapshot.read(uint32(id)) {
-                       w := nobarrierWakeTime(_p_)
-                       if w != 0 && (pollUntil == 0 || w < pollUntil) {
-                               pollUntil = w
-                       }
-               }
-       }
-       if pollUntil != 0 {
-               if now == 0 {
-                       now = nanotime()
-               }
-               delta = pollUntil - now
-               if delta < 0 {
-                       delta = 0
-               }
-       }
+               // Note the for correctness, only the last M transitioning from
+               // spinning to non-spinning must perform these rechecks to
+               // ensure no missed work. We are performing it on every M that
+               // transitions as a conservative change to monitor effects on
+               // latency. See golang.org/issue/43997.
 
-       // Check for idle-priority GC work again.
-       //
-       // N.B. Since we have no P, gcBlackenEnabled may change at any time; we
-       // must check again after acquiring a P.
-       if atomic.Load(&gcBlackenEnabled) != 0 && gcMarkWorkAvailable(nil) {
-               // Work is available; we can start an idle GC worker only if
-               // there is an available P and available worker G.
-               //
-               // We can attempt to acquire these in either order. Workers are
-               // almost always available (see comment in findRunnableGCWorker
-               // for the one case there may be none). Since we're slightly
-               // less likely to find a P, check for that first.
-               lock(&sched.lock)
-               var node *gcBgMarkWorkerNode
-               _p_ = pidleget()
+               // Check all runqueues once again.
+               _p_ = checkRunqsNoP(allpSnapshot, idlepMaskSnapshot)
                if _p_ != nil {
-                       // Now that we own a P, gcBlackenEnabled can't change
-                       // (as it requires STW).
-                       if gcBlackenEnabled != 0 {
-                               node = (*gcBgMarkWorkerNode)(gcBgMarkWorkerPool.pop())
-                               if node == nil {
-                                       pidleput(_p_)
-                                       _p_ = nil
-                               }
-                       } else {
-                               pidleput(_p_)
-                               _p_ = nil
-                       }
+                       acquirep(_p_)
+                       _g_.m.spinning = true
+                       atomic.Xadd(&sched.nmspinning, 1)
+                       goto top
                }
-               unlock(&sched.lock)
+
+               // Check for idle-priority GC work again.
+               _p_, gp = checkIdleGCNoP()
                if _p_ != nil {
                        acquirep(_p_)
-                       if wasSpinning {
-                               _g_.m.spinning = true
-                               atomic.Xadd(&sched.nmspinning, 1)
-                       }
+                       _g_.m.spinning = true
+                       atomic.Xadd(&sched.nmspinning, 1)
 
                        // Run the idle worker.
                        _p_.gcMarkWorkerMode = gcMarkWorkerIdleMode
-                       gp := node.gp.ptr()
                        casgstatus(gp, _Gwaiting, _Grunnable)
                        if trace.enabled {
                                traceGoUnpark(gp, 0)
                        }
                        return gp, false
                }
+
+               // Finally, check for timer creation or expiry concurrently with
+               // transitioning from spinning to non-spinning.
+               //
+               // Note that we cannot use checkTimers here because it calls
+               // adjusttimers which may need to allocate memory, and that isn't
+               // allowed when we don't have an active P.
+               pollUntil = checkTimersNoP(allpSnapshot, timerpMaskSnapshot, pollUntil)
        }
 
-       // poll network
+       // Poll network until next timer.
        if netpollinited() && (atomic.Load(&netpollWaiters) > 0 || pollUntil != 0) && atomic.Xchg64(&sched.lastpoll, 0) != 0 {
                atomic.Store64(&sched.pollUntil, uint64(pollUntil))
                if _g_.m.p != 0 {
@@ -2676,11 +2681,21 @@ stop:
                if _g_.m.spinning {
                        throw("findrunnable: netpoll with spinning")
                }
+               delay := int64(-1)
+               if pollUntil != 0 {
+                       if now == 0 {
+                               now = nanotime()
+                       }
+                       delay = pollUntil - now
+                       if delay < 0 {
+                               delay = 0
+                       }
+               }
                if faketime != 0 {
                        // When using fake time, just poll.
-                       delta = 0
+                       delay = 0
                }
-               list := netpoll(delta) // block until new work is available
+               list := netpoll(delay) // block until new work is available
                atomic.Store64(&sched.pollUntil, 0)
                atomic.Store64(&sched.lastpoll, uint64(nanotime()))
                if faketime != 0 && list.empty() {
@@ -2742,6 +2757,178 @@ func pollWork() bool {
        return false
 }
 
+// stealWork attempts to steal a runnable goroutine or timer from any P.
+//
+// If newWork is true, new work may have been readied.
+//
+// If now is not 0 it is the current time. stealWork returns the passed time or
+// the current time if now was passed as 0.
+func stealWork(now int64) (gp *g, inheritTime bool, rnow, pollUntil int64, newWork bool) {
+       pp := getg().m.p.ptr()
+
+       ranTimer := false
+
+       const stealTries = 4
+       for i := 0; i < stealTries; i++ {
+               stealTimersOrRunNextG := i == stealTries-1
+
+               for enum := stealOrder.start(fastrand()); !enum.done(); enum.next() {
+                       if sched.gcwaiting != 0 {
+                               // GC work may be available.
+                               return nil, false, now, pollUntil, true
+                       }
+                       p2 := allp[enum.position()]
+                       if pp == p2 {
+                               continue
+                       }
+
+                       // Steal timers from p2. This call to checkTimers is the only place
+                       // where we might hold a lock on a different P's timers. We do this
+                       // once on the last pass before checking runnext because stealing
+                       // from the other P's runnext should be the last resort, so if there
+                       // are timers to steal do that first.
+                       //
+                       // We only check timers on one of the stealing iterations because
+                       // the time stored in now doesn't change in this loop and checking
+                       // the timers for each P more than once with the same value of now
+                       // is probably a waste of time.
+                       //
+                       // timerpMask tells us whether the P may have timers at all. If it
+                       // can't, no need to check at all.
+                       if stealTimersOrRunNextG && timerpMask.read(enum.position()) {
+                               tnow, w, ran := checkTimers(p2, now)
+                               now = tnow
+                               if w != 0 && (pollUntil == 0 || w < pollUntil) {
+                                       pollUntil = w
+                               }
+                               if ran {
+                                       // Running the timers may have
+                                       // made an arbitrary number of G's
+                                       // ready and added them to this P's
+                                       // local run queue. That invalidates
+                                       // the assumption of runqsteal
+                                       // that it always has room to add
+                                       // stolen G's. So check now if there
+                                       // is a local G to run.
+                                       if gp, inheritTime := runqget(pp); gp != nil {
+                                               return gp, inheritTime, now, pollUntil, ranTimer
+                                       }
+                                       ranTimer = true
+                               }
+                       }
+
+                       // Don't bother to attempt to steal if p2 is idle.
+                       if !idlepMask.read(enum.position()) {
+                               if gp := runqsteal(pp, p2, stealTimersOrRunNextG); gp != nil {
+                                       return gp, false, now, pollUntil, ranTimer
+                               }
+                       }
+               }
+       }
+
+       // No goroutines found to steal. Regardless, running a timer may have
+       // made some goroutine ready that we missed. Indicate the next timer to
+       // wait for.
+       return nil, false, now, pollUntil, ranTimer
+}
+
+// Check all Ps for a runnable G to steal.
+//
+// On entry we have no P. If a G is available to steal and a P is available,
+// the P is returned which the caller should acquire and attempt to steal the
+// work to.
+func checkRunqsNoP(allpSnapshot []*p, idlepMaskSnapshot pMask) *p {
+       for id, p2 := range allpSnapshot {
+               if !idlepMaskSnapshot.read(uint32(id)) && !runqempty(p2) {
+                       lock(&sched.lock)
+                       pp := pidleget()
+                       unlock(&sched.lock)
+                       if pp != nil {
+                               return pp
+                       }
+
+                       // Can't get a P, don't bother checking remaining Ps.
+                       break
+               }
+       }
+
+       return nil
+}
+
+// Check all Ps for a timer expiring sooner than pollUntil.
+//
+// Returns updated pollUntil value.
+func checkTimersNoP(allpSnapshot []*p, timerpMaskSnapshot pMask, pollUntil int64) int64 {
+       for id, p2 := range allpSnapshot {
+               if timerpMaskSnapshot.read(uint32(id)) {
+                       w := nobarrierWakeTime(p2)
+                       if w != 0 && (pollUntil == 0 || w < pollUntil) {
+                               pollUntil = w
+                       }
+               }
+       }
+
+       return pollUntil
+}
+
+// Check for idle-priority GC, without a P on entry.
+//
+// If some GC work, a P, and a worker G are all available, the P and G will be
+// returned. The returned P has not been wired yet.
+func checkIdleGCNoP() (*p, *g) {
+       // N.B. Since we have no P, gcBlackenEnabled may change at any time; we
+       // must check again after acquiring a P.
+       if atomic.Load(&gcBlackenEnabled) == 0 {
+               return nil, nil
+       }
+       if !gcMarkWorkAvailable(nil) {
+               return nil, nil
+       }
+
+       // Work is available; we can start an idle GC worker only if there is
+       // an available P and available worker G.
+       //
+       // We can attempt to acquire these in either order, though both have
+       // synchronization concerns (see below). Workers are almost always
+       // available (see comment in findRunnableGCWorker for the one case
+       // there may be none). Since we're slightly less likely to find a P,
+       // check for that first.
+       //
+       // Synchronization: note that we must hold sched.lock until we are
+       // committed to keeping it. Otherwise we cannot put the unnecessary P
+       // back in sched.pidle without performing the full set of idle
+       // transition checks.
+       //
+       // If we were to check gcBgMarkWorkerPool first, we must somehow handle
+       // the assumption in gcControllerState.findRunnableGCWorker that an
+       // empty gcBgMarkWorkerPool is only possible if gcMarkDone is running.
+       lock(&sched.lock)
+       pp := pidleget()
+       if pp == nil {
+               unlock(&sched.lock)
+               return nil, nil
+       }
+
+       // Now that we own a P, gcBlackenEnabled can't change (as it requires
+       // STW).
+       if gcBlackenEnabled == 0 {
+               pidleput(pp)
+               unlock(&sched.lock)
+               return nil, nil
+       }
+
+       node := (*gcBgMarkWorkerNode)(gcBgMarkWorkerPool.pop())
+       if node == nil {
+               pidleput(pp)
+               unlock(&sched.lock)
+               return nil, nil
+       }
+
+       unlock(&sched.lock)
+
+       return pp, node.gp.ptr()
+}
+
 // wakeNetPoller wakes up the thread sleeping in the network poller if it isn't
 // going to wake up before the when argument; or it wakes an idle P to service
 // timers and the network poller if there isn't one already.
@@ -2908,7 +3095,9 @@ top:
        }
        if gp == nil && gcBlackenEnabled != 0 {
                gp = gcController.findRunnableGCWorker(_g_.m.p.ptr())
-               tryWakeP = tryWakeP || gp != nil
+               if gp != nil {
+                       tryWakeP = true
+               }
        }
        if gp == nil {
                // Check the global runnable queue once in a while to ensure fairness.
@@ -2999,7 +3188,7 @@ func dropg() {
 
 // checkTimers runs any timers for the P that are ready.
 // If now is not 0 it is the current time.
-// It returns the current time or 0 if it is not known,
+// It returns the passed time or the current time if now was passed as 0.
 // and the time when the next timer should run or 0 if there is no next timer,
 // and reports whether it ran any timers.
 // If the time when the next timer should run is not 0,
@@ -3149,6 +3338,7 @@ func preemptPark(gp *g) {
                throw("bad g status")
        }
        gp.waitreason = waitReasonPreempted
+
        // Transition from _Grunning to _Gscan|_Gpreempted. We can't
        // be in _Grunning when we dropg because then we'd be running
        // without an M, but the moment we're in _Gpreempted,
@@ -3527,20 +3717,28 @@ func exitsyscallfast_pidle() bool {
 // exitsyscall slow path on g0.
 // Failed to acquire P, enqueue gp as runnable.
 //
+// Called via mcall, so gp is the calling g from this M.
+//
 //go:nowritebarrierrec
 func exitsyscall0(gp *g) {
-       _g_ := getg()
-
        casgstatus(gp, _Gsyscall, _Gexitingsyscall)
        dropg()
        casgstatus(gp, _Gexitingsyscall, _Grunnable)
        lock(&sched.lock)
        var _p_ *p
-       if schedEnabled(_g_) {
+       if schedEnabled(gp) {
                _p_ = pidleget()
        }
+       var locked bool
        if _p_ == nil {
                globrunqput(gp)
+
+               // Below, we stoplockedm if gp is locked. globrunqput releases
+               // ownership of gp, so we must check if gp is locked prior to
+               // committing the release by unlocking sched.lock, otherwise we
+               // could race with another M transitioning gp from unlocked to
+               // locked.
+               locked = gp.lockedm != 0
        } else if atomic.Load(&sched.sysmonwait) != 0 {
                atomic.Store(&sched.sysmonwait, 0)
                notewakeup(&sched.sysmonnote)
@@ -3550,8 +3748,11 @@ func exitsyscall0(gp *g) {
                acquirep(_p_)
                execute(gp, false) // Never returns.
        }
-       if _g_.m.lockedg != 0 {
+       if locked {
                // Wait until another thread schedules gp and so m again.
+               //
+               // N.B. lockedm must be this M, as this g was running on this M
+               // before entersyscall.
                stoplockedm()
                execute(gp, false) // Never returns.
        }
@@ -3586,7 +3787,10 @@ func syscall_exitsyscall() {
        exitsyscall()
 }
 
-func beforefork() {
+// Called from syscall package before fork.
+//go:linkname syscall_runtime_BeforeFork syscall.runtime__BeforeFork
+//go:nosplit
+func syscall_runtime_BeforeFork() {
        gp := getg().m.curg
 
        // Block signals during a fork, so that the child does not run
@@ -3597,14 +3801,10 @@ func beforefork() {
        sigblock(false)
 }
 
-// Called from syscall package before fork.
-//go:linkname syscall_runtime_BeforeFork syscall.runtime__BeforeFork
+// Called from syscall package after fork in parent.
+//go:linkname syscall_runtime_AfterFork syscall.runtime__AfterFork
 //go:nosplit
-func syscall_runtime_BeforeFork() {
-       systemstack(beforefork)
-}
-
-func afterfork() {
+func syscall_runtime_AfterFork() {
        gp := getg().m.curg
 
        msigrestore(gp.m.sigmask)
@@ -3612,13 +3812,6 @@ func afterfork() {
        gp.m.locks--
 }
 
-// Called from syscall package after fork in parent.
-//go:linkname syscall_runtime_AfterFork syscall.runtime__AfterFork
-//go:nosplit
-func syscall_runtime_AfterFork() {
-       systemstack(afterfork)
-}
-
 // inForkedChild is true while manipulating signals in the child process.
 // This is used to avoid calling libc functions in case we are using vfork.
 var inForkedChild bool
@@ -3734,6 +3927,11 @@ func newproc(fn uintptr, arg unsafe.Pointer) *g {
        if isSystemGoroutine(newg, false) {
                atomic.Xadd(&sched.ngsys, +1)
        }
+       // Track initial transition?
+       newg.trackingSeq = uint8(fastrand())
+       if newg.trackingSeq%gTrackingPeriod == 0 {
+               newg.tracking = true
+       }
        casgstatus(newg, _Gdead, _Grunnable)
 
        if _p_.goidcache == _p_.goidcacheend {
@@ -3844,13 +4042,19 @@ func gfput(_p_ *p, gp *g) {
        _p_.gFree.push(gp)
        _p_.gFree.n++
        if _p_.gFree.n >= 64 {
-               lock(&sched.gFree.lock)
+               var (
+                       inc      int32
+                       noStackQ gQueue
+               )
                for _p_.gFree.n >= 32 {
-                       _p_.gFree.n--
                        gp = _p_.gFree.pop()
-                       sched.gFree.list.push(gp)
-                       sched.gFree.n++
+                       _p_.gFree.n--
+                       noStackQ.push(gp)
+                       inc++
                }
+               lock(&sched.gFree.lock)
+               sched.gFree.list.pushAll(noStackQ)
+               sched.gFree.n += inc
                unlock(&sched.gFree.lock)
        }
 }
@@ -3884,13 +4088,19 @@ retry:
 
 // Purge all cached G's from gfree list to the global list.
 func gfpurge(_p_ *p) {
-       lock(&sched.gFree.lock)
+       var (
+               inc      int32
+               noStackQ gQueue
+       )
        for !_p_.gFree.empty() {
                gp := _p_.gFree.pop()
                _p_.gFree.n--
-               sched.gFree.list.push(gp)
-               sched.gFree.n++
+               noStackQ.push(gp)
+               inc++
        }
+       lock(&sched.gFree.lock)
+       sched.gFree.list.pushAll(noStackQ)
+       sched.gFree.n += inc
        unlock(&sched.gFree.lock)
 }
 
@@ -4061,71 +4271,6 @@ func sigprof(pc uintptr, gp *g, mp *m) {
        // See golang.org/issue/17165.
        getg().m.mallocing++
 
-       // Define that a "user g" is a user-created goroutine, and a "system g"
-       // is one that is m->g0 or m->gsignal.
-       //
-       // We might be interrupted for profiling halfway through a
-       // goroutine switch. The switch involves updating three (or four) values:
-       // g, PC, SP, and (on arm) LR. The PC must be the last to be updated,
-       // because once it gets updated the new g is running.
-       //
-       // When switching from a user g to a system g, LR is not considered live,
-       // so the update only affects g, SP, and PC. Since PC must be last, there
-       // the possible partial transitions in ordinary execution are (1) g alone is updated,
-       // (2) both g and SP are updated, and (3) SP alone is updated.
-       // If SP or g alone is updated, we can detect the partial transition by checking
-       // whether the SP is within g's stack bounds. (We could also require that SP
-       // be changed only after g, but the stack bounds check is needed by other
-       // cases, so there is no need to impose an additional requirement.)
-       //
-       // There is one exceptional transition to a system g, not in ordinary execution.
-       // When a signal arrives, the operating system starts the signal handler running
-       // with an updated PC and SP. The g is updated last, at the beginning of the
-       // handler. There are two reasons this is okay. First, until g is updated the
-       // g and SP do not match, so the stack bounds check detects the partial transition.
-       // Second, signal handlers currently run with signals disabled, so a profiling
-       // signal cannot arrive during the handler.
-       //
-       // When switching from a system g to a user g, there are three possibilities.
-       //
-       // First, it may be that the g switch has no PC update, because the SP
-       // either corresponds to a user g throughout (as in asmcgocall)
-       // or because it has been arranged to look like a user g frame
-       // (as in cgocallback). In this case, since the entire
-       // transition is a g+SP update, a partial transition updating just one of
-       // those will be detected by the stack bounds check.
-       //
-       // Second, when returning from a signal handler, the PC and SP updates
-       // are performed by the operating system in an atomic update, so the g
-       // update must be done before them. The stack bounds check detects
-       // the partial transition here, and (again) signal handlers run with signals
-       // disabled, so a profiling signal cannot arrive then anyway.
-       //
-       // Third, the common case: it may be that the switch updates g, SP, and PC
-       // separately. If the PC is within any of the functions that does this,
-       // we don't ask for a traceback. C.F. the function setsSP for more about this.
-       //
-       // There is another apparently viable approach, recorded here in case
-       // the "PC within setsSP function" check turns out not to be usable.
-       // It would be possible to delay the update of either g or SP until immediately
-       // before the PC update instruction. Then, because of the stack bounds check,
-       // the only problematic interrupt point is just before that PC update instruction,
-       // and the sigprof handler can detect that instruction and simulate stepping past
-       // it in order to reach a consistent state. On ARM, the update of g must be made
-       // in two places (in R10 and also in a TLS slot), so the delayed update would
-       // need to be the SP update. The sigprof handler must read the instruction at
-       // the current PC and if it was the known instruction (for example, JMP BX or
-       // MOV R2, PC), use that other register in place of the PC value.
-       // The biggest drawback to this solution is that it requires that we can tell
-       // whether it's safe to read from the memory pointed at by PC.
-       // In a correct program, we can test PC == nil and otherwise read,
-       // but if a profiling signal happens at the instant that a program executes
-       // a bad jump (before the program manages to handle the resulting fault)
-       // the profiling handler could fault trying to read nonexistent memory.
-       //
-       // To recap, there are no constraints on the assembly being used for the
-       // transition. We simply require that g and SP match and that the PC is not
-       // in gogo.
        traceback := true
 
        // If SIGPROF arrived while already fetching runtime callers
@@ -4351,7 +4496,6 @@ func (pp *p) destroy() {
                moveTimers(plocal, pp.timers)
                pp.timers = nil
                pp.numTimers = 0
-               pp.adjustTimers = 0
                pp.deletedTimers = 0
                atomic.Store64(&pp.timer0When, 0)
                unlock(&pp.timersLock)
@@ -4650,11 +4794,9 @@ func checkdead() {
        }
 
        grunning := 0
-       lock(&allglock)
-       for i := 0; i < len(allgs); i++ {
-               gp := allgs[i]
+       forEachG(func(gp *g) {
                if isSystemGoroutine(gp, false) {
-                       continue
+                       return
                }
                s := readgstatus(gp)
                switch s &^ _Gscan {
@@ -4667,8 +4809,7 @@ func checkdead() {
                        print("runtime: checkdead: find g ", gp.goid, " in status ", s, "\n")
                        throw("checkdead: runnable g")
                }
-       }
-       unlock(&allglock)
+       })
        if grunning == 0 { // possible if main goroutine calls runtime·Goexit()
                unlock(&sched.lock) // unlock so that GODEBUG=scheddetail=1 doesn't hang
                throw("no goroutines (main called runtime.Goexit) - deadlock!")
@@ -4972,7 +5113,7 @@ func preemptall() bool {
 
 // Tell the goroutine running on processor P to stop.
 // This function is purely best-effort. It can incorrectly fail to inform the
-// goroutine. It can send inform the wrong goroutine. Even if it informs the
+// goroutine. It can inform the wrong goroutine. Even if it informs the
 // correct goroutine, that goroutine might ignore the request if it is
 // simultaneously executing newstack.
 // No lock needs to be held.
@@ -5080,9 +5221,7 @@ func schedtrace(detailed bool) {
                print("  M", mp.id, ": p=", id1, " curg=", id2, " mallocing=", mp.mallocing, " throwing=", mp.throwing, " preemptoff=", mp.preemptoff, ""+" locks=", mp.locks, " dying=", mp.dying, " spinning=", mp.spinning, " blocked=", mp.blocked, " lockedg=", id3, "\n")
        }
 
-       lock(&allglock)
-       for gi := 0; gi < len(allgs); gi++ {
-               gp := allgs[gi]
+       forEachG(func(gp *g) {
                mp := gp.m
                lockedm := gp.lockedm.ptr()
                id1 := int64(-1)
@@ -5094,8 +5233,7 @@ func schedtrace(detailed bool) {
                        id2 = lockedm.id
                }
                print("  G", gp.goid, ": status=", readgstatus(gp), "(", gp.waitreason.String(), ") m=", id1, " lockedm=", id2, "\n")
-       }
-       unlock(&allglock)
+       })
        unlock(&sched.lock)
 }
 
@@ -5190,6 +5328,8 @@ func globrunqputhead(gp *g) {
 // Put a batch of runnable goroutines on the global runnable queue.
 // This clears *batch.
 // sched.lock must be held.
+// May run during STW, so write barriers are not allowed.
+//go:nowritebarrierrec
 func globrunqputbatch(batch *gQueue, n int32) {
        assertLockHeld(&sched.lock)
 
@@ -5505,6 +5645,45 @@ func runqget(_p_ *p) (gp *g, inheritTime bool) {
        }
 }
 
+// runqdrain drains the local runnable queue of _p_ and returns all goroutines in it.
+// Executed only by the owner P.
+func runqdrain(_p_ *p) (drainQ gQueue, n uint32) {
+       oldNext := _p_.runnext
+       if oldNext != 0 && _p_.runnext.cas(oldNext, 0) {
+               drainQ.pushBack(oldNext.ptr())
+               n++
+       }
+
+retry:
+       h := atomic.LoadAcq(&_p_.runqhead) // load-acquire, synchronize with other consumers
+       t := _p_.runqtail
+       qn := t - h
+       if qn == 0 {
+               return
+       }
+       if qn > uint32(len(_p_.runq)) { // read inconsistent h and t
+               goto retry
+       }
+
+       if !atomic.CasRel(&_p_.runqhead, h, h+qn) { // cas-release, commits consume
+               goto retry
+       }
+
+       // We've inverted the order in which it gets G's from the local P's runnable queue
+       // and then advances the head pointer because we don't want to mess up the statuses of G's
+       // while runqdrain() and runqsteal() are running in parallel.
+       // Thus we should advance the head pointer before draining the local P into a gQueue,
+       // so that we can update any gp.schedlink only after we take the full ownership of G,
+       // meanwhile, other P's can't access to all G's in local P's runnable queue and steal them.
+       // See https://groups.google.com/g/golang-dev/c/0pTKxEKhHSc/m/6Q85QjdVBQAJ for more details.
+       for i := uint32(0); i < qn; i++ {
+               gp := _p_.runq[(h+i)%uint32(len(_p_.runq))].ptr()
+               drainQ.pushBack(gp)
+               n++
+       }
+       return
+}
+
 // Grabs a batch of goroutines from _p_'s runnable queue into batch.
 // Batch is a ring buffer starting at batchHead.
 // Returns number of grabbed goroutines.
@@ -5698,11 +5877,6 @@ func setMaxThreads(in int) (out int) {
        return
 }
 
-func haveexperiment(name string) bool {
-       // The gofrontend does not support experiments.
-       return false
-}
-
 //go:nosplit
 func procPin() int {
        _g_ := getg()
@@ -5828,7 +6002,7 @@ var inittrace tracestat
 
 type tracestat struct {
        active bool   // init tracing activation status
-       id     int64  // init go routine id
+       id     int64  // init goroutine id
        allocs uint64 // heap allocations
        bytes  uint64 // heap allocated bytes
 }
index a8f0dc39c0c7da39c44dbd2a394cd46066c689e8..d7549a8874f6a3aa743f80693214307c0eeaea60 100644 (file)
@@ -699,6 +699,55 @@ func BenchmarkCreateGoroutinesCapture(b *testing.B) {
        }
 }
 
+// warmupScheduler ensures the scheduler has at least targetThreadCount threads
+// in its thread pool.
+func warmupScheduler(targetThreadCount int) {
+       var wg sync.WaitGroup
+       var count int32
+       for i := 0; i < targetThreadCount; i++ {
+               wg.Add(1)
+               go func() {
+                       atomic.AddInt32(&count, 1)
+                       for atomic.LoadInt32(&count) < int32(targetThreadCount) {
+                               // spin until all threads started
+                       }
+
+                       // spin a bit more to ensure they are all running on separate CPUs.
+                       doWork(time.Millisecond)
+                       wg.Done()
+               }()
+       }
+       wg.Wait()
+}
+
+func doWork(dur time.Duration) {
+       start := time.Now()
+       for time.Since(start) < dur {
+       }
+}
+
+// BenchmarkCreateGoroutinesSingle creates many goroutines, all from a single
+// producer (the main benchmark goroutine).
+//
+// Compared to BenchmarkCreateGoroutines, this causes different behavior in the
+// scheduler because Ms are much more likely to need to steal work from the
+// main P rather than having work in the local run queue.
+func BenchmarkCreateGoroutinesSingle(b *testing.B) {
+       // Since we are interested in stealing behavior, warm the scheduler to
+       // get all the Ps running first.
+       warmupScheduler(runtime.GOMAXPROCS(0))
+       b.ResetTimer()
+
+       var wg sync.WaitGroup
+       wg.Add(b.N)
+       for i := 0; i < b.N; i++ {
+               go func() {
+                       wg.Done()
+               }()
+       }
+       wg.Wait()
+}
+
 func BenchmarkClosureCall(b *testing.B) {
        sum := 0
        off1 := 1
index 180f707b1a74294288ddff98fd9b58620fb9e585..0e431b8103e060323b4080a096aa59451335cf28 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !race
 // +build !race
 
 // Dummy race detection API, used when not built with -race.
index 81ed1291b8b812435414ca254d32bbfa264e70d1..5b92879c20bc5ce3dba3b9063349c527e235bbc2 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !windows
 // +build !windows
 
 package runtime
index c923b872aa1ecaa40455e7df355242d19cbc2609..19a6cc6f8d385a2aede64c36c6a888c1ea9edb5b 100644 (file)
@@ -142,14 +142,10 @@ func TestLldbPython(t *testing.T) {
 
        checkLldbPython(t)
 
-       dir, err := os.MkdirTemp("", "go-build")
-       if err != nil {
-               t.Fatalf("failed to create temp directory: %v", err)
-       }
-       defer os.RemoveAll(dir)
+       dir := t.TempDir()
 
        src := filepath.Join(dir, "main.go")
-       err = os.WriteFile(src, []byte(lldbHelloSource), 0644)
+       err := os.WriteFile(src, []byte(lldbHelloSource), 0644)
        if err != nil {
                t.Fatalf("failed to create src file: %v", err)
        }
index 143d19eb1347a045c61dc9040006e7f35b29119b..68e7b9ea6facb9f520e607a907b4352ebc7ec880 100644 (file)
@@ -321,7 +321,6 @@ var debug struct {
        gctrace            int32
        invalidptr         int32
        madvdontneed       int32 // for Linux; issue 28466
-       scavenge           int32
        scavtrace          int32
        scheddetail        int32
        schedtrace         int32
@@ -350,7 +349,6 @@ var dbgvars = []dbgVar{
        {"invalidptr", &debug.invalidptr},
        {"madvdontneed", &debug.madvdontneed},
        {"sbrk", &debug.sbrk},
-       {"scavenge", &debug.scavenge},
        {"scavtrace", &debug.scavtrace},
        {"scheddetail", &debug.scheddetail},
        {"schedtrace", &debug.schedtrace},
index 1879b829be7275bec01466ca71feea3e2be19d12..81a40d5633eaf4303f1836362a149c74e4c339c4 100644 (file)
@@ -5,7 +5,6 @@
 package runtime
 
 import (
-       "internal/cpu"
        "runtime/internal/atomic"
        "runtime/internal/sys"
        "unsafe"
@@ -412,7 +411,18 @@ type g struct {
        syscallsp uintptr // if status==Gsyscall, syscallsp = sched.sp to use during gc
        syscallpc uintptr // if status==Gsyscall, syscallpc = sched.pc to use during gc
        // Not for gccgo: stktopsp       uintptr        // expected sp at top of stack, to check in traceback
-       param        unsafe.Pointer // passed parameter on wakeup
+       // param is a generic pointer parameter field used to pass
+       // values in particular contexts where other storage for the
+       // parameter would be difficult to find. It is currently used
+       // in three ways:
+       // 1. When a channel operation wakes up a blocked goroutine, it sets param to
+       //    point to the sudog of the completed blocking operation.
+       // 2. By gcAssistAlloc1 to signal back to its caller that the goroutine completed
+       //    the GC cycle. It is unsafe to do so in any other way, because the goroutine's
+       //    stack may have moved in the meantime.
+       // 3. By debugCallWrap to pass parameters to a new goroutine because allocating a
+       //    closure in the runtime is forbidden.
+       param        unsafe.Pointer
        atomicstatus uint32
        // Not for gccgo: stackLock      uint32 // sigprof/scang lock; TODO: fold in to atomicstatus
        goid        int64
@@ -446,6 +456,10 @@ type g struct {
 
        raceignore     int8     // ignore race detection events
        sysblocktraced bool     // StartTrace has emitted EvGoInSyscall about this goroutine
+       tracking       bool     // whether we're tracking this G for sched latency statistics
+       trackingSeq    uint8    // used to decide whether to track this G
+       runnableStamp  int64    // timestamp of when the G last became runnable, only used when tracking
+       runnableTime   int64    // the amount of time spent runnable, cleared when running, only used when tracking
        sysexitticks   int64    // cputicks when syscall has returned (for tracing)
        traceseq       uint64   // trace event sequencer
        tracelastp     puintptr // last P emitted an event for this goroutine
@@ -529,6 +543,17 @@ type g struct {
        stackcontext [10]uintptr  // split-stack context
 }
 
+// gTrackingPeriod is the number of transitions out of _Grunning between
+// latency tracking runs.
+const gTrackingPeriod = 8
+
+const (
+       // tlsSlots is the number of pointer-sized slots reserved for TLS on some platforms,
+       // like Windows.
+       tlsSlots = 6
+       tlsSize  = tlsSlots * sys.PtrSize
+)
+
 type m struct {
        g0 *g // goroutine with scheduling stack
        // Not for gccgo: morebuf gobuf  // gobuf arg to morestack
@@ -539,7 +564,7 @@ type m struct {
        gsignal *g     // signal-handling g
        // Not for gccgo: goSigStack    gsignalStack // Go-allocated signal handling stack
        sigmask sigset // storage for saved signal mask
-       // Not for gccgo: tls           [6]uintptr   // thread-local storage (for x86 extern register)
+       // Not for gccgo: tls           [tlsSlots]uintptr   // thread-local storage (for x86 extern register)
        mstartfn    func()
        curg        *g       // current running goroutine
        caughtsig   guintptr // goroutine running during fatal signal
@@ -663,6 +688,9 @@ type p struct {
        // unit and eliminates the (potentially large) scheduling
        // latency that otherwise arises from adding the ready'd
        // goroutines to the end of the run queue.
+       //
+       // Note that while other P's may atomically CAS this to zero,
+       // only the owner P can CAS it to a valid G.
        runnext guintptr
 
        // Available G's (status == Gdead)
@@ -708,7 +736,7 @@ type p struct {
        // timerModifiedEarlier status. Because the timer may have been
        // modified again, there need not be any timer with this value.
        // This is updated using atomic functions.
-       // This is 0 if the value is unknown.
+       // This is 0 if there are no timerModifiedEarlier timers.
        timerModifiedEarliest uint64
 
        // Per-P GC state
@@ -754,12 +782,6 @@ type p struct {
        // Modified using atomic instructions.
        numTimers uint32
 
-       // Number of timerModifiedEarlier timers on P's heap.
-       // This should only be modified while holding timersLock,
-       // or while the timer status is in a transient state
-       // such as timerModifying.
-       adjustTimers uint32
-
        // Number of timerDeleted timers in P's heap.
        // Modified using atomic instructions.
        deletedTimers uint32
@@ -771,7 +793,8 @@ type p struct {
        // scheduler ASAP (regardless of what G is running on it).
        preempt bool
 
-       pad cpu.CacheLinePad
+       // Padding is no longer needed. False sharing is now not a worry because p is large enough
+       // that its size class is an integer multiple of the cache line size (for any of our architectures).
 }
 
 type schedt struct {
@@ -860,6 +883,13 @@ type schedt struct {
        // Acquire and hold this mutex to block sysmon from interacting
        // with the rest of the runtime.
        sysmonlock mutex
+
+       // timeToRun is a distribution of scheduling latencies, defined
+       // as the sum of time a G spends in the _Grunnable state before
+       // it transitions to _Grunning.
+       //
+       // timeToRun is protected by sched.lock.
+       timeToRun timeHistogram
 }
 
 // Values for the flags field of a sigTabT.
index 21918c50bb4482bd27ddb96cb7980e9c00115371..8f72daa5c65bffd3a357ec510b3f932f73f70f90 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package runtime_test
index ca3520557555ea1c39c92ca857a32bc6a36a4759..bda09cfd05e89b34241c8b5b4a0a09358e6b96a5 100644 (file)
@@ -270,8 +270,8 @@ func TestTrailingZero(t *testing.T) {
                n int64
                z struct{}
        }
-       if unsafe.Sizeof(T2{}) != 8+unsafe.Sizeof(Uintreg(0)) {
-               t.Errorf("sizeof(%#v)==%d, want %d", T2{}, unsafe.Sizeof(T2{}), 8+unsafe.Sizeof(Uintreg(0)))
+       if unsafe.Sizeof(T2{}) != 8+unsafe.Sizeof(uintptr(0)) {
+               t.Errorf("sizeof(%#v)==%d, want %d", T2{}, unsafe.Sizeof(T2{}), 8+unsafe.Sizeof(uintptr(0)))
        }
        type T3 struct {
                n byte
index cdad0e2b94380ee239967560bc8caa02194397bf..54e14c9a1ee6d803be10a168c0cd97e22f05132e 100644 (file)
@@ -6,6 +6,7 @@
 // We need a fast system call to provoke the race,
 // and Close(-1) is nearly universally fast.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || plan9
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd plan9
 
 package runtime_test
index 31272b035605f9cd21e314e7001271ee2a527c63..d84af07d7988ff46377bb828a44a88cfac5d6be2 100644 (file)
@@ -20,7 +20,7 @@ const debugSelect = false
 
 // Select case descriptor.
 // Known to compiler.
-// Changes here must also be made in src/cmd/internal/gc/select.go's scasetype.
+// Changes here must also be made in src/cmd/compile/internal/walk/select.go's scasetype.
 type scase struct {
        c    *hchan         // chan
        elem unsafe.Pointer // data element
index 9b371b07324ff95329172fb8072a350233004198..905e932b7d857efb1643e9fc314b7693a1222a45 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !plan9 && !windows && !js
 // +build !plan9,!windows,!js
 
 package runtime_test
index e85136af7d19948c9c98bcf4d8c1d3e4012f44b3..a291d2b6bd49448944127636286f91ccd8954622 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package runtime
@@ -288,6 +289,8 @@ func setProcessCPUProfiler(hz int32) {
                it.it_value = it.it_interval
                setitimer(_ITIMER_PROF, &it, nil)
        } else {
+               setitimer(_ITIMER_PROF, &_itimerval{}, nil)
+
                // If the Go signal handler should be disabled by default,
                // switch back to the signal handler that was installed
                // when we enabled profiling. We don't try to handle the case
@@ -311,8 +314,6 @@ func setProcessCPUProfiler(hz int32) {
                                setsig(_SIGPROF, h)
                        }
                }
-
-               setitimer(_ITIMER_PROF, &_itimerval{}, nil)
        }
 }
 
index 33a9b92ee73f1f51b9ca265ed3be6c1587e67331..1b7cb9d4c453aeb930fbe11a5403205a1b643ace 100644 (file)
@@ -1,3 +1,4 @@
+//go:build windows
 // +build windows
 
 package runtime_test
@@ -7,7 +8,6 @@ import (
        "bytes"
        "fmt"
        "internal/testenv"
-       "os"
        "os/exec"
        "path/filepath"
        "runtime"
@@ -28,15 +28,11 @@ func TestVectoredHandlerDontCrashOnLibrary(t *testing.T) {
        testenv.MustHaveExecPath(t, "gcc")
        testprog.Lock()
        defer testprog.Unlock()
-       dir, err := os.MkdirTemp("", "go-build")
-       if err != nil {
-               t.Fatalf("failed to create temp directory: %v", err)
-       }
-       defer os.RemoveAll(dir)
+       dir := t.TempDir()
 
        // build go dll
        dll := filepath.Join(dir, "testwinlib.dll")
-       cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", dll, "--buildmode", "c-shared", "testdata/testwinlib/main.go")
+       cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", dll, "-buildmode", "c-shared", "testdata/testwinlib/main.go")
        out, err := testenv.CleanCmdEnv(cmd).CombinedOutput()
        if err != nil {
                t.Fatalf("failed to build go library: %s\n%s", err, out)
@@ -156,15 +152,11 @@ func TestLibraryCtrlHandler(t *testing.T) {
        testenv.MustHaveExecPath(t, "gcc")
        testprog.Lock()
        defer testprog.Unlock()
-       dir, err := os.MkdirTemp("", "go-build")
-       if err != nil {
-               t.Fatalf("failed to create temp directory: %v", err)
-       }
-       defer os.RemoveAll(dir)
+       dir := t.TempDir()
 
        // build go dll
        dll := filepath.Join(dir, "dummy.dll")
-       cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", dll, "--buildmode", "c-shared", "testdata/testwinlibsignal/dummy.go")
+       cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", dll, "-buildmode", "c-shared", "testdata/testwinlibsignal/dummy.go")
        out, err := testenv.CleanCmdEnv(cmd).CombinedOutput()
        if err != nil {
                t.Fatalf("failed to build go library: %s\n%s", err, out)
index 7ca755740d27b3ec85a6c05e005e30fc7cc6f655..d5539f1cd827c58bd4817d969eea2c78fda25c2e 100644 (file)
@@ -28,6 +28,7 @@
 // unnecessary rechecks of sig.mask, but it cannot lead to missed signals
 // nor deadlocks.
 
+//go:build !plan9
 // +build !plan9
 
 package runtime
@@ -71,7 +72,7 @@ const (
 // It runs from the signal handler, so it's limited in what it can do.
 func sigsend(s uint32) bool {
        bit := uint32(1) << uint(s&31)
-       if !sig.inuse || s >= uint32(32*len(sig.wanted)) {
+       if s >= uint32(32*len(sig.wanted)) {
                return false
        }
 
index 16aeeb2ef0b41a5e4e60f897eabbab678121ff46..e23446bea47b776bf48189390f2906f3a24f0176 100644 (file)
@@ -7,8 +7,8 @@
 // signal_recv thread. This file holds the non-Darwin implementations of
 // those functions. These functions will never be called.
 
-// +build !darwin
-// +build !plan9
+//go:build !darwin && !plan9
+// +build !darwin,!plan9
 
 package runtime
 
index c5521ce1bd29313f4923c1b63d0206d7aa743b94..067871eaf3453615cda0e6479f2ebef44d8eac57 100644 (file)
@@ -3,74 +3,83 @@
 
 package runtime
 
-// class  bytes/obj  bytes/span  objects  tail waste  max waste
-//     1          8        8192     1024           0     87.50%
-//     2         16        8192      512           0     43.75%
-//     3         24        8192      341           8     29.24%
-//     4         32        8192      256           0     21.88%
-//     5         48        8192      170          32     31.52%
-//     6         64        8192      128           0     23.44%
-//     7         80        8192      102          32     19.07%
-//     8         96        8192       85          32     15.95%
-//     9        112        8192       73          16     13.56%
-//    10        128        8192       64           0     11.72%
-//    11        144        8192       56         128     11.82%
-//    12        160        8192       51          32      9.73%
-//    13        176        8192       46          96      9.59%
-//    14        192        8192       42         128      9.25%
-//    15        208        8192       39          80      8.12%
-//    16        224        8192       36         128      8.15%
-//    17        240        8192       34          32      6.62%
-//    18        256        8192       32           0      5.86%
-//    19        288        8192       28         128     12.16%
-//    20        320        8192       25         192     11.80%
-//    21        352        8192       23          96      9.88%
-//    22        384        8192       21         128      9.51%
-//    23        416        8192       19         288     10.71%
-//    24        448        8192       18         128      8.37%
-//    25        480        8192       17          32      6.82%
-//    26        512        8192       16           0      6.05%
-//    27        576        8192       14         128     12.33%
-//    28        640        8192       12         512     15.48%
-//    29        704        8192       11         448     13.93%
-//    30        768        8192       10         512     13.94%
-//    31        896        8192        9         128     15.52%
-//    32       1024        8192        8           0     12.40%
-//    33       1152        8192        7         128     12.41%
-//    34       1280        8192        6         512     15.55%
-//    35       1408       16384       11         896     14.00%
-//    36       1536        8192        5         512     14.00%
-//    37       1792       16384        9         256     15.57%
-//    38       2048        8192        4           0     12.45%
-//    39       2304       16384        7         256     12.46%
-//    40       2688        8192        3         128     15.59%
-//    41       3072       24576        8           0     12.47%
-//    42       3200       16384        5         384      6.22%
-//    43       3456       24576        7         384      8.83%
-//    44       4096        8192        2           0     15.60%
-//    45       4864       24576        5         256     16.65%
-//    46       5376       16384        3         256     10.92%
-//    47       6144       24576        4           0     12.48%
-//    48       6528       32768        5         128      6.23%
-//    49       6784       40960        6         256      4.36%
-//    50       6912       49152        7         768      3.37%
-//    51       8192        8192        1           0     15.61%
-//    52       9472       57344        6         512     14.28%
-//    53       9728       49152        5         512      3.64%
-//    54      10240       40960        4           0      4.99%
-//    55      10880       32768        3         128      6.24%
-//    56      12288       24576        2           0     11.45%
-//    57      13568       40960        3         256      9.99%
-//    58      14336       57344        4           0      5.35%
-//    59      16384       16384        1           0     12.49%
-//    60      18432       73728        4           0     11.11%
-//    61      19072       57344        3         128      3.57%
-//    62      20480       40960        2           0      6.87%
-//    63      21760       65536        3         256      6.25%
-//    64      24576       24576        1           0     11.45%
-//    65      27264       81920        3         128     10.00%
-//    66      28672       57344        2           0      4.91%
-//    67      32768       32768        1           0     12.50%
+// class  bytes/obj  bytes/span  objects  tail waste  max waste  min align
+//     1          8        8192     1024           0     87.50%          8
+//     2         16        8192      512           0     43.75%         16
+//     3         24        8192      341           8     29.24%          8
+//     4         32        8192      256           0     21.88%         32
+//     5         48        8192      170          32     31.52%         16
+//     6         64        8192      128           0     23.44%         64
+//     7         80        8192      102          32     19.07%         16
+//     8         96        8192       85          32     15.95%         32
+//     9        112        8192       73          16     13.56%         16
+//    10        128        8192       64           0     11.72%        128
+//    11        144        8192       56         128     11.82%         16
+//    12        160        8192       51          32      9.73%         32
+//    13        176        8192       46          96      9.59%         16
+//    14        192        8192       42         128      9.25%         64
+//    15        208        8192       39          80      8.12%         16
+//    16        224        8192       36         128      8.15%         32
+//    17        240        8192       34          32      6.62%         16
+//    18        256        8192       32           0      5.86%        256
+//    19        288        8192       28         128     12.16%         32
+//    20        320        8192       25         192     11.80%         64
+//    21        352        8192       23          96      9.88%         32
+//    22        384        8192       21         128      9.51%        128
+//    23        416        8192       19         288     10.71%         32
+//    24        448        8192       18         128      8.37%         64
+//    25        480        8192       17          32      6.82%         32
+//    26        512        8192       16           0      6.05%        512
+//    27        576        8192       14         128     12.33%         64
+//    28        640        8192       12         512     15.48%        128
+//    29        704        8192       11         448     13.93%         64
+//    30        768        8192       10         512     13.94%        256
+//    31        896        8192        9         128     15.52%        128
+//    32       1024        8192        8           0     12.40%       1024
+//    33       1152        8192        7         128     12.41%        128
+//    34       1280        8192        6         512     15.55%        256
+//    35       1408       16384       11         896     14.00%        128
+//    36       1536        8192        5         512     14.00%        512
+//    37       1792       16384        9         256     15.57%        256
+//    38       2048        8192        4           0     12.45%       2048
+//    39       2304       16384        7         256     12.46%        256
+//    40       2688        8192        3         128     15.59%        128
+//    41       3072       24576        8           0     12.47%       1024
+//    42       3200       16384        5         384      6.22%        128
+//    43       3456       24576        7         384      8.83%        128
+//    44       4096        8192        2           0     15.60%       4096
+//    45       4864       24576        5         256     16.65%        256
+//    46       5376       16384        3         256     10.92%        256
+//    47       6144       24576        4           0     12.48%       2048
+//    48       6528       32768        5         128      6.23%        128
+//    49       6784       40960        6         256      4.36%        128
+//    50       6912       49152        7         768      3.37%        256
+//    51       8192        8192        1           0     15.61%       8192
+//    52       9472       57344        6         512     14.28%        256
+//    53       9728       49152        5         512      3.64%        512
+//    54      10240       40960        4           0      4.99%       2048
+//    55      10880       32768        3         128      6.24%        128
+//    56      12288       24576        2           0     11.45%       4096
+//    57      13568       40960        3         256      9.99%        256
+//    58      14336       57344        4           0      5.35%       2048
+//    59      16384       16384        1           0     12.49%       8192
+//    60      18432       73728        4           0     11.11%       2048
+//    61      19072       57344        3         128      3.57%        128
+//    62      20480       40960        2           0      6.87%       4096
+//    63      21760       65536        3         256      6.25%        256
+//    64      24576       24576        1           0     11.45%       8192
+//    65      27264       81920        3         128     10.00%        128
+//    66      28672       57344        2           0      4.91%       4096
+//    67      32768       32768        1           0     12.50%       8192
+
+// alignment  bits  min obj size
+//         8     3             8
+//        16     4            32
+//        32     5           256
+//        64     6           512
+//       128     7           768
+//      4096    12         28672
+//      8192    13         32768
 
 const (
        _MaxSmallSize   = 32768
@@ -83,14 +92,6 @@ const (
 
 var class_to_size = [_NumSizeClasses]uint16{0, 8, 16, 24, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 256, 288, 320, 352, 384, 416, 448, 480, 512, 576, 640, 704, 768, 896, 1024, 1152, 1280, 1408, 1536, 1792, 2048, 2304, 2688, 3072, 3200, 3456, 4096, 4864, 5376, 6144, 6528, 6784, 6912, 8192, 9472, 9728, 10240, 10880, 12288, 13568, 14336, 16384, 18432, 19072, 20480, 21760, 24576, 27264, 28672, 32768}
 var class_to_allocnpages = [_NumSizeClasses]uint8{0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 3, 2, 3, 1, 3, 2, 3, 4, 5, 6, 1, 7, 6, 5, 4, 3, 5, 7, 2, 9, 7, 5, 8, 3, 10, 7, 4}
-
-type divMagic struct {
-       shift    uint8
-       shift2   uint8
-       mul      uint16
-       baseMask uint16
-}
-
-var class_to_divmagic = [_NumSizeClasses]divMagic{{0, 0, 0, 0}, {3, 0, 1, 65528}, {4, 0, 1, 65520}, {3, 11, 683, 0}, {5, 0, 1, 65504}, {4, 11, 683, 0}, {6, 0, 1, 65472}, {4, 10, 205, 0}, {5, 9, 171, 0}, {4, 11, 293, 0}, {7, 0, 1, 65408}, {4, 13, 911, 0}, {5, 10, 205, 0}, {4, 12, 373, 0}, {6, 9, 171, 0}, {4, 13, 631, 0}, {5, 11, 293, 0}, {4, 13, 547, 0}, {8, 0, 1, 65280}, {5, 9, 57, 0}, {6, 9, 103, 0}, {5, 12, 373, 0}, {7, 7, 43, 0}, {5, 10, 79, 0}, {6, 10, 147, 0}, {5, 11, 137, 0}, {9, 0, 1, 65024}, {6, 9, 57, 0}, {7, 9, 103, 0}, {6, 11, 187, 0}, {8, 7, 43, 0}, {7, 8, 37, 0}, {10, 0, 1, 64512}, {7, 9, 57, 0}, {8, 6, 13, 0}, {7, 11, 187, 0}, {9, 5, 11, 0}, {8, 8, 37, 0}, {11, 0, 1, 63488}, {8, 9, 57, 0}, {7, 10, 49, 0}, {10, 5, 11, 0}, {7, 10, 41, 0}, {7, 9, 19, 0}, {12, 0, 1, 61440}, {8, 9, 27, 0}, {8, 10, 49, 0}, {11, 5, 11, 0}, {7, 13, 161, 0}, {7, 13, 155, 0}, {8, 9, 19, 0}, {13, 0, 1, 57344}, {8, 12, 111, 0}, {9, 9, 27, 0}, {11, 6, 13, 0}, {7, 14, 193, 0}, {12, 3, 3, 0}, {8, 13, 155, 0}, {11, 8, 37, 0}, {14, 0, 1, 49152}, {11, 8, 29, 0}, {7, 13, 55, 0}, {12, 5, 7, 0}, {8, 14, 193, 0}, {13, 3, 3, 0}, {7, 14, 77, 0}, {12, 7, 19, 0}, {15, 0, 1, 32768}}
+var class_to_divmagic = [_NumSizeClasses]uint32{0, ^uint32(0)/8 + 1, ^uint32(0)/16 + 1, ^uint32(0)/24 + 1, ^uint32(0)/32 + 1, ^uint32(0)/48 + 1, ^uint32(0)/64 + 1, ^uint32(0)/80 + 1, ^uint32(0)/96 + 1, ^uint32(0)/112 + 1, ^uint32(0)/128 + 1, ^uint32(0)/144 + 1, ^uint32(0)/160 + 1, ^uint32(0)/176 + 1, ^uint32(0)/192 + 1, ^uint32(0)/208 + 1, ^uint32(0)/224 + 1, ^uint32(0)/240 + 1, ^uint32(0)/256 + 1, ^uint32(0)/288 + 1, ^uint32(0)/320 + 1, ^uint32(0)/352 + 1, ^uint32(0)/384 + 1, ^uint32(0)/416 + 1, ^uint32(0)/448 + 1, ^uint32(0)/480 + 1, ^uint32(0)/512 + 1, ^uint32(0)/576 + 1, ^uint32(0)/640 + 1, ^uint32(0)/704 + 1, ^uint32(0)/768 + 1, ^uint32(0)/896 + 1, ^uint32(0)/1024 + 1, ^uint32(0)/1152 + 1, ^uint32(0)/1280 + 1, ^uint32(0)/1408 + 1, ^uint32(0)/1536 + 1, ^uint32(0)/1792 + 1, ^uint32(0)/2048 + 1, ^uint32(0)/2304 + 1, ^uint32(0)/2688 + 1, ^uint32(0)/3072 + 1, ^uint32(0)/3200 + 1, ^uint32(0)/3456 + 1, ^uint32(0)/4096 + 1, ^uint32(0)/4864 + 1, ^uint32(0)/5376 + 1, ^uint32(0)/6144 + 1, ^uint32(0)/6528 + 1, ^uint32(0)/6784 + 1, ^uint32(0)/6912 + 1, ^uint32(0)/8192 + 1, ^uint32(0)/9472 + 1, ^uint32(0)/9728 + 1, ^uint32(0)/10240 + 1, ^uint32(0)/10880 + 1, ^uint32(0)/12288 + 1, ^uint32(0)/13568 + 1, ^uint32(0)/14336 + 1, ^uint32(0)/16384 + 1, ^uint32(0)/18432 + 1, ^uint32(0)/19072 + 1, ^uint32(0)/20480 + 1, ^uint32(0)/21760 + 1, ^uint32(0)/24576 + 1, ^uint32(0)/27264 + 1, ^uint32(0)/28672 + 1, ^uint32(0)/32768 + 1}
 var size_to_class8 = [smallSizeMax/smallSizeDiv + 1]uint8{0, 1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}
 var size_to_class128 = [(_MaxSmallSize-smallSizeMax)/largeSizeDiv + 1]uint8{32, 33, 34, 35, 36, 37, 37, 38, 38, 39, 39, 40, 40, 40, 41, 41, 41, 42, 43, 43, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 48, 48, 48, 49, 49, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67}
index 0afb05e19d2adacf35b308845f752e911aa68b98..f510eeb2f67f85028333f975a5a21108c609fbe3 100644 (file)
@@ -25,7 +25,7 @@ func TestSizeof(t *testing.T) {
                _32bit uintptr     // size on 32bit platforms
                _64bit uintptr     // size on 64bit platforms
        }{
-               {runtime.G{}, 216, 376},   // g, but exported for testing
+               {runtime.G{}, 236, 392},   // g, but exported for testing
                {runtime.Sudog{}, 56, 88}, // sudog, but exported for testing
        }
 
index d4c0e9028b7607fb540990fbda0fa5600dfffa6f..8654abab18d70dbcff68e204b72519ddb1d51dd1 100644 (file)
@@ -152,6 +152,18 @@ func unsafeslice64(et *_type, ptr unsafe.Pointer, len64 int64) {
        unsafeslice(et, ptr, len)
 }
 
+func unsafeslicecheckptr(et *_type, ptr unsafe.Pointer, len64 int64) {
+       unsafeslice64(et, ptr, len64)
+
+       /* Commented out for gofrontend.
+       // Check that underlying array doesn't straddle multiple heap objects.
+       // unsafeslice64 has already checked for overflow.
+       if checkptrStraddles(ptr, uintptr(len64)*et.size) {
+               throw("checkptr: unsafe.Slice result straddles multiple allocations")
+       }
+       */
+}
+
 func panicunsafeslicelen() {
        panic(errorString("unsafe.Slice: len out of range"))
 }
index dea7234b3adcaf5319e39ba821a5836f996f3721..e24313c411b8dfd0b7f63dca937c0f6213a36895 100644 (file)
@@ -274,9 +274,6 @@ func checkASM() bool {
        return true
 }
 
-// For gccgo this is in the C code.
-func osyield()
-
 //extern __go_syscall6
 func syscall(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) uintptr
 
index 93ff56618801282e136cb0c6381386bbd45d71fa..c9e5f3d0c4a50c9d00177844051dc3642dcd9269 100644 (file)
@@ -2,9 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !js
-// +build !plan9
-// +build !windows
+//go:build !js && !plan9 && !windows
+// +build !js,!plan9,!windows
 
 package runtime
 
@@ -21,6 +20,11 @@ func closefd(fd int32) int32
 func exit(code int32)
 func usleep(usec uint32)
 
+//go:nosplit
+func usleep_no_g(usec uint32) {
+       usleep(usec)
+}
+
 // write calls the write system call.
 // It returns a non-negative number of bytes written or a negative errno value.
 //go:noescape
index 35feb100c85fa43d93babd669970cf27dd5e81ae..cb900b23aae08ea59ca25e445103fd76d22100ce 100644 (file)
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//-go:build !aix && !darwin && !freebsd && !openbsd && !plan9 && !solaris
+// -build !aix,!darwin,!freebsd,!openbsd,!plan9,!solaris
+
 package runtime
 
 func nanotime1() int64
index 3c733e37d9ad6d1a5a567ff6530d328307314520..b8c957991fdf9105ddd8f1ed6d6ee3ffc3cbb41d 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build linux
 // +build linux
 
 package runtime
index 325d35d537db8f99fa27b4776e6b01de9be889a0..4f081d5b18531f5f0d1fc6df22b7840c79e815b1 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !linux
 // +build !linux
 
 package runtime
index 22a2b13977dc5c5dfb09597a314a29e199996fc0..89a27c43fb0b59781ed3c164505909adcf7c9e7f 100644 (file)
@@ -62,8 +62,15 @@ func CallersFrames(callers []uintptr) *Frames {
        return &Frames{callers: callers}
 }
 
-// Next returns frame information for the next caller.
-// If more is false, there are no more callers (the Frame value is valid).
+// Next returns a Frame representing the next call frame in the slice
+// of PC values. If it has already returned all call frames, Next
+// returns a zero Frame.
+//
+// The more result indicates whether the next call to Next will return
+// a valid Frame. It does not necessarily indicate whether this call
+// returned one.
+//
+// See the Frames example for idiomatic usage.
 func (ci *Frames) Next() (frame Frame, more bool) {
        if len(ci.callers) == 0 {
                return Frame{}, false
index 9bf710ba0e799d3213eb865e1a0f0106e59ceb12..057ed4ccd90a7513ff8211f00a7685d450bfeef5 100644 (file)
@@ -27,13 +27,9 @@ func wasmTruncU()
 func wasmExit(code int32)
 
 // adjust Gobuf as it if executed a call to fn with context ctxt
-// and then did an immediate gosave.
+// and then stopped before the first instruction in fn.
 func gostartcall(buf *gobuf, fn, ctxt unsafe.Pointer) {
        sp := buf.sp
-       if sys.RegSize > sys.PtrSize {
-               sp -= sys.PtrSize
-               *(*uintptr)(unsafe.Pointer(sp)) = 0
-       }
        sp -= sys.PtrSize
        *(*uintptr)(unsafe.Pointer(sp)) = buf.pc
        buf.sp = sp
index e0a2794f4c1da108a7883285a20526e3738bebed..9c5561396e5d43b335c3b270201025809c307f1c 100644 (file)
@@ -4,15 +4,22 @@
 
 package main
 
-import "unsafe"
+import (
+       "runtime"
+       "time"
+       "unsafe"
+)
 
 func init() {
        register("CheckPtrAlignmentNoPtr", CheckPtrAlignmentNoPtr)
        register("CheckPtrAlignmentPtr", CheckPtrAlignmentPtr)
+       register("CheckPtrAlignmentNilPtr", CheckPtrAlignmentNilPtr)
        register("CheckPtrArithmetic", CheckPtrArithmetic)
        register("CheckPtrArithmetic2", CheckPtrArithmetic2)
        register("CheckPtrSize", CheckPtrSize)
        register("CheckPtrSmall", CheckPtrSmall)
+       register("CheckPtrSliceOK", CheckPtrSliceOK)
+       register("CheckPtrSliceFail", CheckPtrSliceFail)
 }
 
 func CheckPtrAlignmentNoPtr() {
@@ -27,6 +34,35 @@ func CheckPtrAlignmentPtr() {
        sink2 = (**int64)(unsafe.Pointer(uintptr(p) + 1))
 }
 
+// CheckPtrAlignmentNilPtr tests that checkptrAlignment doesn't crash
+// on nil pointers (#47430).
+func CheckPtrAlignmentNilPtr() {
+       var do func(int)
+       do = func(n int) {
+               // Inflate the stack so runtime.shrinkstack gets called during GC
+               if n > 0 {
+                       do(n - 1)
+               }
+
+               var p unsafe.Pointer
+               _ = (*int)(p)
+       }
+
+       go func() {
+               for {
+                       runtime.GC()
+               }
+       }()
+
+       go func() {
+               for i := 0; ; i++ {
+                       do(i % 1024)
+               }
+       }()
+
+       time.Sleep(time.Second)
+}
+
 func CheckPtrArithmetic() {
        var x int
        i := uintptr(unsafe.Pointer(&x))
@@ -49,3 +85,14 @@ func CheckPtrSize() {
 func CheckPtrSmall() {
        sink2 = unsafe.Pointer(uintptr(1))
 }
+
+func CheckPtrSliceOK() {
+       p := new([4]int64)
+       sink2 = unsafe.Slice(&p[1], 3)
+}
+
+func CheckPtrSliceFail() {
+       p := new(int64)
+       sink2 = p
+       sink2 = unsafe.Slice(p, 100)
+}
diff --git a/libgo/go/runtime/testdata/testprog/crashdump.go b/libgo/go/runtime/testdata/testprog/crashdump.go
new file mode 100644 (file)
index 0000000..bced397
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+       "fmt"
+       "os"
+       "runtime"
+)
+
+func init() {
+       register("CrashDumpsAllThreads", CrashDumpsAllThreads)
+}
+
+func CrashDumpsAllThreads() {
+       const count = 4
+       runtime.GOMAXPROCS(count + 1)
+
+       chans := make([]chan bool, count)
+       for i := range chans {
+               chans[i] = make(chan bool)
+               go crashDumpsAllThreadsLoop(i, chans[i])
+       }
+
+       // Wait for all the goroutines to start executing.
+       for _, c := range chans {
+               <-c
+       }
+
+       // Tell our parent that all the goroutines are executing.
+       if _, err := os.NewFile(3, "pipe").WriteString("x"); err != nil {
+               fmt.Fprintf(os.Stderr, "write to pipe failed: %v\n", err)
+               os.Exit(2)
+       }
+
+       select {}
+}
+
+func crashDumpsAllThreadsLoop(i int, c chan bool) {
+       close(c)
+       for {
+               for j := 0; j < 0x7fffffff; j++ {
+               }
+       }
+}
index aabca9e1ebd978dfa4b4f2c8de789837da78e71c..44a15b08650377adb509b61118081d79a3d26c05 100644 (file)
@@ -10,7 +10,7 @@ package main
 // The test fails when the function is the first C function.
 // The exported functions are the first C functions, so we use that.
 
-// extern void GoNop();
+// extern void CallGoNop();
 import "C"
 
 import (
@@ -38,7 +38,7 @@ func CgoCCodeSIGPROF() {
                                        break
                                }
                        }
-                       C.GoNop()
+                       C.CallGoNop()
                }
                c <- true
        }()
diff --git a/libgo/go/runtime/testdata/testprogcgo/aprof_c.c b/libgo/go/runtime/testdata/testprogcgo/aprof_c.c
new file mode 100644 (file)
index 0000000..d588e13
--- /dev/null
@@ -0,0 +1,9 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "_cgo_export.h"
+
+void CallGoNop() {
+       GoNop();
+}
diff --git a/libgo/go/runtime/testdata/testprogcgo/bigstack1_windows.c b/libgo/go/runtime/testdata/testprogcgo/bigstack1_windows.c
new file mode 100644 (file)
index 0000000..551fb68
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This is not in bigstack_windows.c because it needs to be part of
+// testprogcgo but is not part of the DLL built from bigstack_windows.c.
+
+#include "_cgo_export.h"
+
+void CallGoBigStack1(char* p) {
+       goBigStack1(p);
+}
index f58fcf993f0217846369d3c745ceb037eaad16f4..135b5fcfe04e3502daff61c0e50d5cc9992c76fc 100644 (file)
@@ -6,7 +6,7 @@ package main
 
 /*
 typedef void callback(char*);
-extern void goBigStack1(char*);
+extern void CallGoBigStack1(char*);
 extern void bigStack(callback*);
 */
 import "C"
@@ -18,7 +18,7 @@ func init() {
 func BigStack() {
        // Create a large thread stack and call back into Go to test
        // if Go correctly determines the stack bounds.
-       C.bigStack((*C.callback)(C.goBigStack1))
+       C.bigStack((*C.callback)(C.CallGoBigStack1))
 }
 
 //export goBigStack1
index 9a8c057761e8f114120ca5055a38d04b55c18cd0..b10cc4f3b920b4ffb5275c9fabc753ac9d3d8e18 100644 (file)
@@ -9,5 +9,5 @@
 uint32_t threadExited;
 
 void setExited(void *x) {
-       __atomic_add_fetch(&threadExited, 1, __ATOMIC_SEQ_CST);
+       __sync_fetch_and_add(&threadExited, 1);
 }
index 3a3176d220194b657b3b750d155df8c32cd6061f..668d4e0c7bec88619c51c9203952121eef90be74 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !gccgo
 // +build !gccgo
 
 package main
index 0750ec168c55a8d80cc7142d64ae516de5db2c02..c17bb3956e023ee2ff2c6a1ce209c1c6b457f153 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ((linux && amd64) || (freebsd && amd64)) && !gccgo
 // +build linux,amd64 freebsd,amd64
 // +build !gccgo
 
index 3b36c3096ea46a905fbce4efee514ad1fbe540f3..ed3faed404cf4fc6d47eb33eaa68fc92aa916c9f 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !plan9,!windows
-// +build !gccgo
+//go:build !plan9 && !windows && !gccgo
+// +build !plan9,!windows,!gccgo
 
 package main
 
@@ -50,13 +50,13 @@ void pprofCgoThreadTraceback(void* parg) {
        arg->buf[0] = (uintptr_t)(cpuHogThread) + 0x10;
        arg->buf[1] = (uintptr_t)(cpuHogThread2) + 0x4;
        arg->buf[2] = 0;
-       __atomic_add_fetch(&cpuHogThreadCount, 1, __ATOMIC_SEQ_CST);
+       __sync_add_and_fetch(&cpuHogThreadCount, 1);
 }
 
 // getCPUHogThreadCount fetches the number of times we've seen cpuHogThread
 // in the traceback.
 int getCPUHogThreadCount() {
-       return __atomic_load(&cpuHogThreadCount, __ATOMIC_SEQ_CST);
+       return __sync_add_and_fetch(&cpuHogThreadCount, 0);
 }
 
 static void* cpuHogDriver(void* arg __attribute__ ((unused))) {
index 46cf644ec985f4f326b80749f49e67d7d7ff8ed3..e04a63587709ed5fb9677211387a43c6244896af 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !gccgo
 // +build !gccgo
 
 package main
diff --git a/libgo/go/runtime/testdata/testprogcgo/traceback_c.c b/libgo/go/runtime/testdata/testprogcgo/traceback_c.c
new file mode 100644 (file)
index 0000000..4de749c
--- /dev/null
@@ -0,0 +1,68 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !gccgo
+// +build !gccgo
+
+// The C definitions for traceback.go. That file uses //export so
+// it can't put function definitions in the "C" import comment.
+
+#include <stdint.h>
+
+char *p;
+
+int crashInGo;
+extern void h1(void);
+
+int tracebackF3(void) {
+       if (crashInGo)
+               h1();
+       else
+               *p = 0;
+       return 0;
+}
+
+int tracebackF2(void) {
+       return tracebackF3();
+}
+
+int tracebackF1(void) {
+       return tracebackF2();
+}
+
+struct cgoTracebackArg {
+       uintptr_t  context;
+       uintptr_t  sigContext;
+       uintptr_t* buf;
+       uintptr_t  max;
+};
+
+struct cgoSymbolizerArg {
+       uintptr_t   pc;
+       const char* file;
+       uintptr_t   lineno;
+       const char* func;
+       uintptr_t   entry;
+       uintptr_t   more;
+       uintptr_t   data;
+};
+
+void cgoTraceback(void* parg) {
+       struct cgoTracebackArg* arg = (struct cgoTracebackArg*)(parg);
+       arg->buf[0] = 1;
+       arg->buf[1] = 2;
+       arg->buf[2] = 3;
+       arg->buf[3] = 0;
+}
+
+void cgoSymbolizer(void* parg) {
+       struct cgoSymbolizerArg* arg = (struct cgoSymbolizerArg*)(parg);
+       if (arg->pc != arg->data + 1) {
+               arg->file = "unexpected data";
+       } else {
+               arg->file = "cgo symbolizer";
+       }
+       arg->lineno = arg->data + 1;
+       arg->data++;
+}
index 83357fdd5d987357771b5bf45ab3223ad9c3ebcc..2d07c2db8a42f31adc82272a61e75ef025247f26 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build gccgo
 // +build gccgo
 
 package main
index 3940a77d4f9c0163df13fe2ce56e9b46088fc806..69078b7bc70883d7643859dc992f8301c8d1b75c 100644 (file)
@@ -2,8 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The __attribute__((weak)) used below doesn't seem to work on Windows.
-
+//go:build !gccgo
 // +build !gccgo
 
 package main
@@ -16,20 +15,24 @@ package main
 extern void C1(void);
 extern void C2(void);
 extern void tcContext(void*);
+extern void tcContextSimple(void*);
 extern void tcTraceback(void*);
 extern void tcSymbolizer(void*);
 extern int getContextCount(void);
+extern void TracebackContextPreemptionCallGo(int);
 */
 import "C"
 
 import (
        "fmt"
        "runtime"
+       "sync"
        "unsafe"
 )
 
 func init() {
        register("TracebackContext", TracebackContext)
+       register("TracebackContextPreemption", TracebackContextPreemption)
 }
 
 var tracebackOK bool
@@ -107,3 +110,30 @@ wantLoop:
                tracebackOK = false
        }
 }
+
+// Issue 47441.
+func TracebackContextPreemption() {
+       runtime.SetCgoTraceback(0, unsafe.Pointer(C.tcTraceback), unsafe.Pointer(C.tcContextSimple), unsafe.Pointer(C.tcSymbolizer))
+
+       const funcs = 10
+       const calls = 1e5
+       var wg sync.WaitGroup
+       for i := 0; i < funcs; i++ {
+               wg.Add(1)
+               go func(i int) {
+                       defer wg.Done()
+                       for j := 0; j < calls; j++ {
+                               C.TracebackContextPreemptionCallGo(C.int(i*calls + j))
+                       }
+               }(i)
+       }
+       wg.Wait()
+
+       fmt.Println("OK")
+}
+
+//export TracebackContextPreemptionGoFunction
+func TracebackContextPreemptionGoFunction(i C.int) {
+       // Do some busy work.
+       fmt.Sprintf("%d\n", i)
+}
index ff6895e637c1af4b2bf6293b451f3f4adea29371..ff8430948a1dfd2783b053753b2b1a0ade262b29 100644 (file)
@@ -5,6 +5,7 @@
 // The C definitions for tracebackctxt.go. That file uses //export so
 // it can't put function definitions in the "C" import comment.
 
+//go:build !gccgo
 // +build !gccgo
 
 #include <stdlib.h>
@@ -13,6 +14,7 @@
 // Functions exported from Go.
 extern void G1(void);
 extern void G2(void);
+extern void TracebackContextPreemptionGoFunction(int);
 
 void C1() {
        G1();
@@ -49,25 +51,32 @@ struct cgoSymbolizerArg {
 static int contextCount;
 
 int getContextCount() {
-       return __atomic_load_n(&contextCount, __ATOMIC_SEQ_CST);
+       return __sync_add_and_fetch(&contextCount, 0);
 }
 
 void tcContext(void* parg) {
        struct cgoContextArg* arg = (struct cgoContextArg*)(parg);
        if (arg->context == 0) {
-               arg->context = __atomic_add_fetch(&contextCount, 1, __ATOMIC_SEQ_CST);
+               arg->context = __sync_add_and_fetch(&contextCount, 1);
        } else {
-               if (arg->context != __atomic_load_n(&contextCount, __ATOMIC_SEQ_CST))
+               if (arg->context != __sync_add_and_fetch(&contextCount, 0)) {
                        abort();
                }
-               __atomic_sub_fetch(&contextCount, 1, __ATOMIC_SEQ_CST);
+               __sync_sub_and_fetch(&contextCount, 1);
+       }
+}
+
+void tcContextSimple(void* parg) {
+       struct cgoContextArg* arg = (struct cgoContextArg*)(parg);
+       if (arg->context == 0) {
+               arg->context = 1;
        }
 }
 
 void tcTraceback(void* parg) {
        int base, i;
        struct cgoTracebackArg* arg = (struct cgoTracebackArg*)(parg);
-       if (arg->context == 0) {
+       if (arg->context == 0 && arg->sigContext == 0) {
                // This shouldn't happen in this program.
                abort();
        }
@@ -91,3 +100,7 @@ void tcSymbolizer(void *parg) {
        arg->func = "cFunction";
        arg->lineno = arg->pc + (arg->more << 16);
 }
+
+void TracebackContextPreemptionCallGo(int i) {
+       TracebackContextPreemptionGoFunction(i);
+}
index f2eabb95488b72757ed1f01b257b6f277315af12..12488aa6588b08c6ac9c13495a59401463b2bdfd 100644 (file)
@@ -1,7 +1,7 @@
 package windows
 
 /*
-#cgo CFLAGS: -mnop-fun-dllimport
+#cgo amd64 386 CFLAGS: -mnop-fun-dllimport
 
 #include <windows.h>
 
index 82dfd91c93a2d91864ac7a38cf6a506d2529b175..e610f15d06cb5b995993f45b62b18e60db38624a 100644 (file)
@@ -1,7 +1,10 @@
+//go:build windows
 // +build windows
 
 package main
 
+import "C"
+
 //export Dummy
 func Dummy() int {
        return 42
diff --git a/libgo/go/runtime/testdata/testwinlibsignal/main.c b/libgo/go/runtime/testdata/testwinlibsignal/main.c
new file mode 100644 (file)
index 0000000..37f2482
--- /dev/null
@@ -0,0 +1,57 @@
+#include <windows.h>
+#include <stdio.h>
+
+HANDLE waitForCtrlBreakEvent;
+
+BOOL WINAPI CtrlHandler(DWORD fdwCtrlType)
+{
+    switch (fdwCtrlType)
+    {
+    case CTRL_BREAK_EVENT:
+        SetEvent(waitForCtrlBreakEvent);
+        return TRUE;
+    default:
+        return FALSE;
+    }
+}
+
+int main(void)
+{
+    waitForCtrlBreakEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+    if (!waitForCtrlBreakEvent) {
+        fprintf(stderr, "ERROR: Could not create event\n");
+        return 1;
+    }
+
+    if (!SetConsoleCtrlHandler(CtrlHandler, TRUE))
+    {
+        fprintf(stderr, "ERROR: Could not set control handler\n");
+        return 1;
+    }
+
+    // The library must be loaded after the SetConsoleCtrlHandler call
+    // so that the library handler registers after the main program.
+    // This way the library handler gets called first.
+    HMODULE dummyDll = LoadLibrary("dummy.dll");
+    if (!dummyDll) {
+        fprintf(stderr, "ERROR: Could not load dummy.dll\n");
+        return 1;
+    }
+
+    // Call the Dummy function so that Go initialization completes, since
+    // all cgo entry points call out to _cgo_wait_runtime_init_done.
+    if (((int(*)(void))GetProcAddress(dummyDll, "Dummy"))() != 42) {
+        fprintf(stderr, "ERROR: Dummy function did not return 42\n");
+        return 1;
+    }
+
+    printf("ready\n");
+    fflush(stdout);
+
+    if (WaitForSingleObject(waitForCtrlBreakEvent, 5000) != WAIT_OBJECT_0) {
+        fprintf(stderr, "FAILURE: No signal received\n");
+        return 1;
+    }
+
+    return 0;
+}
index 327726c09db2e33ef6897683a770ffe7f8d5e321..7cc9156d19cf4e29d38cb6d73a05e99501318da9 100644 (file)
@@ -332,7 +332,6 @@ func deltimer(t *timer) bool {
                                // Must fetch t.pp before setting status
                                // to timerDeleted.
                                tpp := t.pp.ptr()
-                               atomic.Xadd(&tpp.adjustTimers, -1)
                                if !atomic.Cas(&t.status, timerModifying, timerDeleted) {
                                        badTimer()
                                }
@@ -509,20 +508,9 @@ loop:
 
                tpp := t.pp.ptr()
 
-               // Update the adjustTimers field.  Subtract one if we
-               // are removing a timerModifiedEarlier, add one if we
-               // are adding a timerModifiedEarlier.
-               adjust := int32(0)
-               if status == timerModifiedEarlier {
-                       adjust--
-               }
                if newStatus == timerModifiedEarlier {
-                       adjust++
                        updateTimerModifiedEarliest(tpp, when)
                }
-               if adjust != 0 {
-                       atomic.Xadd(&tpp.adjustTimers, adjust)
-               }
 
                // Set the new status of the timer.
                if !atomic.Cas(&t.status, timerModifying, newStatus) {
@@ -590,9 +578,6 @@ func cleantimers(pp *p) {
                        // Move t to the right position.
                        dodeltimer0(pp)
                        doaddtimer(pp, t)
-                       if s == timerModifiedEarlier {
-                               atomic.Xadd(&pp.adjustTimers, -1)
-                       }
                        if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
                                badTimer()
                        }
@@ -663,37 +648,23 @@ func moveTimers(pp *p, timers []*timer) {
 // it also moves timers that have been modified to run later,
 // and removes deleted timers. The caller must have locked the timers for pp.
 func adjusttimers(pp *p, now int64) {
-       if atomic.Load(&pp.adjustTimers) == 0 {
-               if verifyTimers {
-                       verifyTimerHeap(pp)
-               }
-               // There are no timers to adjust, so it is safe to clear
-               // timerModifiedEarliest. Do so in case it is stale.
-               // Everything will work if we don't do this,
-               // but clearing here may save future calls to adjusttimers.
-               atomic.Store64(&pp.timerModifiedEarliest, 0)
-               return
-       }
-
        // If we haven't yet reached the time of the first timerModifiedEarlier
        // timer, don't do anything. This speeds up programs that adjust
        // a lot of timers back and forth if the timers rarely expire.
        // We'll postpone looking through all the adjusted timers until
        // one would actually expire.
-       if first := atomic.Load64(&pp.timerModifiedEarliest); first != 0 {
-               if int64(first) > now {
-                       if verifyTimers {
-                               verifyTimerHeap(pp)
-                       }
-                       return
+       first := atomic.Load64(&pp.timerModifiedEarliest)
+       if first == 0 || int64(first) > now {
+               if verifyTimers {
+                       verifyTimerHeap(pp)
                }
-
-               // We are going to clear all timerModifiedEarlier timers.
-               atomic.Store64(&pp.timerModifiedEarliest, 0)
+               return
        }
 
+       // We are going to clear all timerModifiedEarlier timers.
+       atomic.Store64(&pp.timerModifiedEarliest, 0)
+
        var moved []*timer
-loop:
        for i := 0; i < len(pp.timers); i++ {
                t := pp.timers[i]
                if t.pp.ptr() != pp {
@@ -720,11 +691,6 @@ loop:
                                // loop to skip some other timer.
                                dodeltimer(pp, i)
                                moved = append(moved, t)
-                               if s == timerModifiedEarlier {
-                                       if n := atomic.Xadd(&pp.adjustTimers, -1); int32(n) <= 0 {
-                                               break loop
-                                       }
-                               }
                                // Look at this heap position again.
                                i--
                        }
@@ -823,9 +789,6 @@ func runtimer(pp *p, now int64) int64 {
                        t.when = t.nextwhen
                        dodeltimer0(pp)
                        doaddtimer(pp, t)
-                       if s == timerModifiedEarlier {
-                               atomic.Xadd(&pp.adjustTimers, -1)
-                       }
                        if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
                                badTimer()
                        }
@@ -898,7 +861,6 @@ func clearDeletedTimers(pp *p) {
        atomic.Store64(&pp.timerModifiedEarliest, 0)
 
        cdel := int32(0)
-       cearlier := int32(0)
        to := 0
        changedHeap := false
        timers := pp.timers
@@ -923,9 +885,6 @@ nextTimer:
                                        if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
                                                badTimer()
                                        }
-                                       if s == timerModifiedEarlier {
-                                               cearlier++
-                                       }
                                        continue nextTimer
                                }
                        case timerDeleted:
@@ -962,7 +921,6 @@ nextTimer:
 
        atomic.Xadd(&pp.deletedTimers, -cdel)
        atomic.Xadd(&pp.numTimers, -cdel)
-       atomic.Xadd(&pp.adjustTimers, -cearlier)
 
        timers = timers[:to]
        pp.timers = timers
index c64d2994a901303463fc4ceb86831272355977bf..c790faba3d6b75744b7a9afdba58e2c22183ede0 100644 (file)
@@ -2,20 +2,13 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build faketime
-// +build !windows
-
-// Faketime isn't currently supported on Windows. This would require:
-//
-// 1. Shadowing time_now, which is implemented in assembly on Windows.
-//    Since that's exported directly to the time package from runtime
-//    assembly, this would involve moving it from sys_windows_*.s into
-//    its own assembly files build-tagged with !faketime and using the
-//    implementation of time_now from timestub.go in faketime mode.
-//
-// 2. Modifying syscall.Write to call syscall.faketimeWrite,
-//    translating the Stdout and Stderr handles into FDs 1 and 2.
-//    (See CL 192739 PS 3.)
+//go:build faketime && !windows
+// +build faketime,!windows
+
+// Faketime isn't currently supported on Windows. This would require
+// modifying syscall.Write to call syscall.faketimeWrite,
+// translating the Stdout and Stderr handles into FDs 1 and 2.
+// (See CL 192739 PS 3.)
 
 package runtime
 
@@ -44,8 +37,9 @@ func nanotime() int64 {
        return faketime
 }
 
-func walltime() (sec int64, nsec int32) {
-       return faketime / 1000000000, int32(faketime % 1000000000)
+//go:linkname time_now time.now
+func time_now() (sec int64, nsec int32, mono int64) {
+       return faketime / 1e9, int32(faketime % 1e9), faketime
 }
 
 func write(fd uintptr, p unsafe.Pointer, n int32) int32 {
index 1912a94e873c803fd788fa6da605277062b146f4..5a4ceaf43d280ceacd4fec036405316ae0f32ea1 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !faketime
 // +build !faketime
 
 package runtime
@@ -19,10 +20,6 @@ func nanotime() int64 {
        return nanotime1()
 }
 
-func walltime() (sec int64, nsec int32) {
-       return walltime1()
-}
-
 // write must be nosplit on Windows (see write1)
 //
 //go:nosplit
index 6bfaa8a8f0ea0d7f085dc5d76c58a700a606c4b2..2c06dcb940ea8ec218015bbfa98efc8c6f6ff604 100644 (file)
@@ -4,8 +4,10 @@
 
 // Declarations for operating systems implementing time.now directly in assembly.
 
+//go:build ignore && !faketime && (windows || (linux && amd64))
 // +build ignore
-// +build windows
+// +build !faketime
+// +build windows linux,amd64
 
 package runtime
 
index 14165cee9745e8eefaa58c7b34be748e68559086..76de76f2548957de474f4ce0878787de5cd530f6 100644 (file)
@@ -5,7 +5,10 @@
 // Declarations for operating systems implementing time.now
 // indirectly, in terms of walltime and nanotime assembly.
 
+//-go:build !faketime && !windows && !(linux && amd64)
+// -build !faketime
 // -build !windows
+// -build !linux !amd64
 
 package runtime
 
index f691388c7293df4ca19893c7c373bbd695ee6c94..d9b4ee0c0ac2b156b8a4166c1f32b8d5d729ef68 100644 (file)
@@ -2,6 +2,15 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//-go:build !aix && !darwin && !freebsd && !openbsd && !solaris && !windows && !(linux && amd64)
+// -build !aix
+// -build !darwin
+// -build !freebsd
+// -build !openbsd
+// -build !solaris
+// -build !windows
+// -build !linux !amd64
+
 package runtime
 
-func walltime1() (sec int64, nsec int32)
+func walltime() (sec int64, nsec int32)
diff --git a/libgo/go/runtime/tls_stub.go b/libgo/go/runtime/tls_stub.go
new file mode 100644 (file)
index 0000000..95dafd0
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build (windows && !amd64) || !windows
+// +build windows,!amd64 !windows
+
+package runtime
+
+//go:nosplit
+func osSetupTLS(mp *m) {}
diff --git a/libgo/go/runtime/tls_windows_amd64.go b/libgo/go/runtime/tls_windows_amd64.go
new file mode 100644 (file)
index 0000000..cacaa84
--- /dev/null
@@ -0,0 +1,10 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+// osSetupTLS is called by needm to set up TLS for non-Go threads.
+//
+// Defined in assembly.
+func osSetupTLS(mp *m)
index f13c81a37997c3b478b9329ec5831f89fe895cbe..a7c36bac8786a8936c961e3fc31318beba3561a1 100644 (file)
@@ -53,8 +53,8 @@ const (
        traceEvGoSysBlock        = 30 // syscall blocks [timestamp]
        traceEvGoWaiting         = 31 // denotes that goroutine is blocked when tracing starts [timestamp, goroutine id]
        traceEvGoInSyscall       = 32 // denotes that goroutine is in syscall when tracing starts [timestamp, goroutine id]
-       traceEvHeapAlloc         = 33 // memstats.heap_live change [timestamp, heap_alloc]
-       traceEvNextGC            = 34 // memstats.next_gc change [timestamp, next_gc]
+       traceEvHeapAlloc         = 33 // gcController.heapLive change [timestamp, heap_alloc]
+       traceEvHeapGoal          = 34 // gcController.heapGoal (formerly next_gc) change [timestamp, heap goal in bytes]
        traceEvTimerGoroutine    = 35 // not currently used; previously denoted timer goroutine [timer goroutine id]
        traceEvFutileWakeup      = 36 // denotes that the previous wakeup of this goroutine was futile [timestamp]
        traceEvString            = 37 // string dictionary entry [ID, length, string]
@@ -222,7 +222,8 @@ func StartTrace() error {
        stackID := traceStackID(mp, stkBuf, 2)
        releasem(mp)
 
-       for _, gp := range allgs {
+       // World is stopped, no need to lock.
+       forEachGRace(func(gp *g) {
                status := readgstatus(gp)
                if status != _Gdead {
                        gp.traceseq = 0
@@ -242,7 +243,7 @@ func StartTrace() error {
                } else {
                        gp.sysblocktraced = false
                }
-       }
+       })
        traceProcStart()
        traceGoStart()
        // Note: ticksStart needs to be set after we emit traceEvGoInSyscall events.
@@ -1138,15 +1139,15 @@ func traceGoSysBlock(pp *p) {
 }
 
 func traceHeapAlloc() {
-       traceEvent(traceEvHeapAlloc, -1, memstats.heap_live)
+       traceEvent(traceEvHeapAlloc, -1, gcController.heapLive)
 }
 
-func traceNextGC() {
-       if nextGC := atomic.Load64(&memstats.next_gc); nextGC == ^uint64(0) {
+func traceHeapGoal() {
+       if heapGoal := atomic.Load64(&gcController.heapGoal); heapGoal == ^uint64(0) {
                // Heap-based triggering is disabled.
-               traceEvent(traceEvNextGC, -1, 0)
+               traceEvent(traceEvHeapGoal, -1, 0)
        } else {
-               traceEvent(traceEvNextGC, -1, nextGC)
+               traceEvent(traceEvHeapGoal, -1, heapGoal)
        }
 }
 
diff --git a/libgo/go/runtime/traceback_test.go b/libgo/go/runtime/traceback_test.go
new file mode 100644 (file)
index 0000000..152db6c
--- /dev/null
@@ -0,0 +1,297 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime_test
+
+import (
+       "bytes"
+       "runtime"
+       "strings"
+       "testing"
+)
+
+var testTracebackArgsBuf [1000]byte
+
+func TestTracebackArgs(t *testing.T) {
+       tests := []struct {
+               fn     func() int
+               expect string
+       }{
+               // simple ints
+               {
+                       func() int { return testTracebackArgs1(1, 2, 3, 4, 5) },
+                       "testTracebackArgs1(0x1, 0x2, 0x3, 0x4, 0x5)",
+               },
+               // some aggregates
+               {
+                       func() int {
+                               return testTracebackArgs2(false, struct {
+                                       a, b, c int
+                                       x       [2]int
+                               }{1, 2, 3, [2]int{4, 5}}, [0]int{}, [3]byte{6, 7, 8})
+                       },
+                       "testTracebackArgs2(0x0, {0x1, 0x2, 0x3, {0x4, 0x5}}, {}, {0x6, 0x7, 0x8})",
+               },
+               {
+                       func() int { return testTracebackArgs3([3]byte{1, 2, 3}, 4, 5, 6, [3]byte{7, 8, 9}) },
+                       "testTracebackArgs3({0x1, 0x2, 0x3}, 0x4, 0x5, 0x6, {0x7, 0x8, 0x9})",
+               },
+               // too deeply nested type
+               {
+                       func() int { return testTracebackArgs4(false, [1][1][1][1][1][1][1][1][1][1]int{}) },
+                       "testTracebackArgs4(0x0, {{{{{...}}}}})",
+               },
+               // a lot of zero-sized type
+               {
+                       func() int {
+                               z := [0]int{}
+                               return testTracebackArgs5(false, struct {
+                                       x int
+                                       y [0]int
+                                       z [2][0]int
+                               }{1, z, [2][0]int{}}, z, z, z, z, z, z, z, z, z, z, z, z)
+                       },
+                       "testTracebackArgs5(0x0, {0x1, {}, {{}, {}}}, {}, {}, {}, {}, {}, ...)",
+               },
+
+               // edge cases for ...
+               // no ... for 10 args
+               {
+                       func() int { return testTracebackArgs6a(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) },
+                       "testTracebackArgs6a(0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa)",
+               },
+               // has ... for 11 args
+               {
+                       func() int { return testTracebackArgs6b(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) },
+                       "testTracebackArgs6b(0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, ...)",
+               },
+               // no ... for aggregates with 10 words
+               {
+                       func() int { return testTracebackArgs7a([10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) },
+                       "testTracebackArgs7a({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa})",
+               },
+               // has ... for aggregates with 11 words
+               {
+                       func() int { return testTracebackArgs7b([11]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}) },
+                       "testTracebackArgs7b({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, ...})",
+               },
+               // no ... for aggregates, but with more args
+               {
+                       func() int { return testTracebackArgs7c([10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 11) },
+                       "testTracebackArgs7c({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa}, ...)",
+               },
+               // has ... for aggregates and also for more args
+               {
+                       func() int { return testTracebackArgs7d([11]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 12) },
+                       "testTracebackArgs7d({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, ...}, ...)",
+               },
+               // nested aggregates, no ...
+               {
+                       func() int { return testTracebackArgs8a(testArgsType8a{1, 2, 3, 4, 5, 6, 7, 8, [2]int{9, 10}}) },
+                       "testTracebackArgs8a({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, {0x9, 0xa}})",
+               },
+               // nested aggregates, ... in inner but not outer
+               {
+                       func() int { return testTracebackArgs8b(testArgsType8b{1, 2, 3, 4, 5, 6, 7, 8, [3]int{9, 10, 11}}) },
+                       "testTracebackArgs8b({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, {0x9, 0xa, ...}})",
+               },
+               // nested aggregates, ... in outer but not inner
+               {
+                       func() int { return testTracebackArgs8c(testArgsType8c{1, 2, 3, 4, 5, 6, 7, 8, [2]int{9, 10}, 11}) },
+                       "testTracebackArgs8c({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, {0x9, 0xa}, ...})",
+               },
+               // nested aggregates, ... in both inner and outer
+               {
+                       func() int { return testTracebackArgs8d(testArgsType8d{1, 2, 3, 4, 5, 6, 7, 8, [3]int{9, 10, 11}, 12}) },
+                       "testTracebackArgs8d({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, {0x9, 0xa, ...}, ...})",
+               },
+       }
+       for _, test := range tests {
+               n := test.fn()
+               got := testTracebackArgsBuf[:n]
+               expect := test.expect
+               if runtime.Compiler == "gccgo" {
+                       expect = expect[:strings.Index(expect, "(")]
+               }
+               if !bytes.Contains(got, []byte(expect)) {
+                       t.Errorf("traceback does not contain expected string: want %q, got\n%s", expect, got)
+               }
+       }
+}
+
+//go:noinline
+func testTracebackArgs1(a, b, c, d, e int) int {
+       n := runtime.Stack(testTracebackArgsBuf[:], false)
+       if a < 0 {
+               // use in-reg args to keep them alive
+               return a + b + c + d + e
+       }
+       return n
+}
+
+//go:noinline
+func testTracebackArgs2(a bool, b struct {
+       a, b, c int
+       x       [2]int
+}, _ [0]int, d [3]byte) int {
+       n := runtime.Stack(testTracebackArgsBuf[:], false)
+       if a {
+               // use in-reg args to keep them alive
+               return b.a + b.b + b.c + b.x[0] + b.x[1] + int(d[0]) + int(d[1]) + int(d[2])
+       }
+       return n
+
+}
+
+//go:noinline
+//go:registerparams
+func testTracebackArgs3(x [3]byte, a, b, c int, y [3]byte) int {
+       n := runtime.Stack(testTracebackArgsBuf[:], false)
+       if a < 0 {
+               // use in-reg args to keep them alive
+               return int(x[0]) + int(x[1]) + int(x[2]) + a + b + c + int(y[0]) + int(y[1]) + int(y[2])
+       }
+       return n
+}
+
+//go:noinline
+func testTracebackArgs4(a bool, x [1][1][1][1][1][1][1][1][1][1]int) int {
+       n := runtime.Stack(testTracebackArgsBuf[:], false)
+       if a {
+               panic(x) // use args to keep them alive
+       }
+       return n
+}
+
+//go:noinline
+func testTracebackArgs5(a bool, x struct {
+       x int
+       y [0]int
+       z [2][0]int
+}, _, _, _, _, _, _, _, _, _, _, _, _ [0]int) int {
+       n := runtime.Stack(testTracebackArgsBuf[:], false)
+       if a {
+               panic(x) // use args to keep them alive
+       }
+       return n
+}
+
+//go:noinline
+func testTracebackArgs6a(a, b, c, d, e, f, g, h, i, j int) int {
+       n := runtime.Stack(testTracebackArgsBuf[:], false)
+       if a < 0 {
+               // use in-reg args to keep them alive
+               return a + b + c + d + e + f + g + h + i + j
+       }
+       return n
+}
+
+//go:noinline
+func testTracebackArgs6b(a, b, c, d, e, f, g, h, i, j, k int) int {
+       n := runtime.Stack(testTracebackArgsBuf[:], false)
+       if a < 0 {
+               // use in-reg args to keep them alive
+               return a + b + c + d + e + f + g + h + i + j + k
+       }
+       return n
+}
+
+//go:noinline
+func testTracebackArgs7a(a [10]int) int {
+       n := runtime.Stack(testTracebackArgsBuf[:], false)
+       if a[0] < 0 {
+               // use in-reg args to keep them alive
+               return a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9]
+       }
+       return n
+}
+
+//go:noinline
+func testTracebackArgs7b(a [11]int) int {
+       n := runtime.Stack(testTracebackArgsBuf[:], false)
+       if a[0] < 0 {
+               // use in-reg args to keep them alive
+               return a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9] + a[10]
+       }
+       return n
+}
+
+//go:noinline
+func testTracebackArgs7c(a [10]int, b int) int {
+       n := runtime.Stack(testTracebackArgsBuf[:], false)
+       if a[0] < 0 {
+               // use in-reg args to keep them alive
+               return a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9] + b
+       }
+       return n
+}
+
+//go:noinline
+func testTracebackArgs7d(a [11]int, b int) int {
+       n := runtime.Stack(testTracebackArgsBuf[:], false)
+       if a[0] < 0 {
+               // use in-reg args to keep them alive
+               return a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9] + a[10] + b
+       }
+       return n
+}
+
+type testArgsType8a struct {
+       a, b, c, d, e, f, g, h int
+       i                      [2]int
+}
+type testArgsType8b struct {
+       a, b, c, d, e, f, g, h int
+       i                      [3]int
+}
+type testArgsType8c struct {
+       a, b, c, d, e, f, g, h int
+       i                      [2]int
+       j                      int
+}
+type testArgsType8d struct {
+       a, b, c, d, e, f, g, h int
+       i                      [3]int
+       j                      int
+}
+
+//go:noinline
+func testTracebackArgs8a(a testArgsType8a) int {
+       n := runtime.Stack(testTracebackArgsBuf[:], false)
+       if a.a < 0 {
+               // use in-reg args to keep them alive
+               return a.b + a.c + a.d + a.e + a.f + a.g + a.h + a.i[0] + a.i[1]
+       }
+       return n
+}
+
+//go:noinline
+func testTracebackArgs8b(a testArgsType8b) int {
+       n := runtime.Stack(testTracebackArgsBuf[:], false)
+       if a.a < 0 {
+               // use in-reg args to keep them alive
+               return a.b + a.c + a.d + a.e + a.f + a.g + a.h + a.i[0] + a.i[1] + a.i[2]
+       }
+       return n
+}
+
+//go:noinline
+func testTracebackArgs8c(a testArgsType8c) int {
+       n := runtime.Stack(testTracebackArgsBuf[:], false)
+       if a.a < 0 {
+               // use in-reg args to keep them alive
+               return a.b + a.c + a.d + a.e + a.f + a.g + a.h + a.i[0] + a.i[1] + a.j
+       }
+       return n
+}
+
+//go:noinline
+func testTracebackArgs8d(a testArgsType8d) int {
+       n := runtime.Stack(testTracebackArgsBuf[:], false)
+       if a.a < 0 {
+               // use in-reg args to keep them alive
+               return a.b + a.c + a.d + a.e + a.f + a.g + a.h + a.i[0] + a.i[1] + a.i[2] + a.j
+       }
+       return n
+}
index 56b4fe6a111c34103ba5972565b6544d1469fa71..c788342aee3ee5aafb9d06c0805981415e6e384f 100644 (file)
@@ -24,6 +24,10 @@ const (
        tflagRegularMemory tflag = 1 << 3 // equal and hash can treat values of this type as a single region of t.size bytes
 )
 
+// Needs to be in sync with
+// go/types.cc
+// ../reflect/type.go:/^type.rtype.
+// ../internal/reflectlite/type.go:/^type.rtype.
 type _type struct {
        size       uintptr
        ptrdata    uintptr
@@ -118,7 +122,7 @@ type maptype struct {
 }
 
 // Note: flag values must match those used in the TMAP case
-// in ../cmd/compile/internal/gc/reflect.go:dtypesym.
+// in ../cmd/compile/internal/reflectdata/reflect.go:writeType.
 func (mt *maptype) indirectkey() bool { // store ptr to key instead of key itself
        return mt.flags&1 != 0
 }
index 6b1467b1c48aefe65671e7354262cdec2b853780..a4656fd72810d7b8d9a30695a732a5cdd11918aa 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !android
 // +build !android
 
 package runtime
index 2419fc8663e4cdb501094b99a2aadd06ede6e0cb..a876900c95481a4a222e112969e45693a1f445cf 100644 (file)
@@ -144,7 +144,7 @@ func writeLogdHeader() int {
        //      hdr[3:7] sec unsigned uint32, little endian.
        //      hdr[7:11] nsec unsigned uint32, little endian.
        hdr[0] = 0 // LOG_ID_MAIN
-       sec, nsec := walltime()
+       sec, nsec, _ := time_now()
        packUint32(hdr[3:7], uint32(sec))
        packUint32(hdr[7:11], uint32(nsec))
 
index 6928f0f092db415f260e6590404a82f1e8313f4e..856422a385e57aa6ee861a2e1161e02f88188c14 100644 (file)
@@ -40,3 +40,35 @@ func ExampleSearch_descendingOrder() {
        // Output:
        // found 6 at index 7 in [55 45 36 28 21 15 10 6 3 1]
 }
+
+// This example demonstrates searching for float64 in a list sorted in ascending order.
+func ExampleSearchFloat64s() {
+       a := []float64{1.0, 2.0, 3.3, 4.6, 6.1, 7.2, 8.0}
+
+       x := 2.0
+       i := sort.SearchFloat64s(a, x)
+       fmt.Printf("found %g at index %d in %v\n", x, i, a)
+
+       x = 0.5
+       i = sort.SearchFloat64s(a, x)
+       fmt.Printf("%g not found, can be inserted at index %d in %v\n", x, i, a)
+       // Output:
+       // found 2 at index 1 in [1 2 3.3 4.6 6.1 7.2 8]
+       // 0.5 not found, can be inserted at index 0 in [1 2 3.3 4.6 6.1 7.2 8]
+}
+
+// This example demonstrates searching for int in a list sorted in ascending order.
+func ExampleSearchInts() {
+       a := []int{1, 2, 3, 4, 6, 7, 8}
+
+       x := 2
+       i := sort.SearchInts(a, x)
+       fmt.Printf("found %d at index %d in %v\n", x, i, a)
+
+       x = 5
+       i = sort.SearchInts(a, x)
+       fmt.Printf("%d not found, can be inserted at index %d in %v\n", x, i, a)
+       // Output:
+       // found 2 at index 1 in [1 2 3 4 6 7 8]
+       // 5 not found, can be inserted at index 4 in [1 2 3 4 6 7 8]
+}
index e7eb5737371f9e5a0b017231a1b39c8044d8e6bd..ed04e33568f4c6f6b5a7fa04790c76f7da29b10a 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 // This program is run via "go generate" (via a directive in sort.go)
index bf24db714a308ac6a3e7b3cc10ed5cc86813bb87..53542dbd1a9b97cf97d6d16110332cec18b0a9c8 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build go1.13
 // +build go1.13
 
 package sort
index 3bf5cbc00bf339f332b726abc030ae20909f0130..5d5949f3cade56f2df3cf32a8a3f48417e58d3a5 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !go1.8
 // +build !go1.8
 
 package sort
index e1766040a78a567736c1a202593b84624cff3756..1538477bc5d205d815a97289c2a4bb5ba623d238 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build go1.8 && !go1.13
 // +build go1.8,!go1.13
 
 package sort
index 1c500575cf0f8ad7bceda844e4b62bc931266377..6ecd4f14d8abd3dae34ffc0d79a3d3e9963f6af9 100644 (file)
@@ -695,7 +695,7 @@ func atof64(s string) (f float64, n int, err error) {
 // as their respective special floating point values. It ignores case when matching.
 func ParseFloat(s string, bitSize int) (float64, error) {
        f, n, err := parseFloatPrefix(s, bitSize)
-       if err == nil && n != len(s) {
+       if n != len(s) && (err == nil || err.(*NumError).Err != ErrSyntax) {
                return 0, syntaxError(fnParseFloat, s)
        }
        return f, err
index 3c058b9be5adc223414a498d6b27e812a0fba08d..aa587a473cdde8deff38643cf44983d773c9afc2 100644 (file)
@@ -342,6 +342,9 @@ var atoftests = []atofTest{
        {"0x12.345p-_12", "0", ErrSyntax},
        {"0x12.345p+1__2", "0", ErrSyntax},
        {"0x12.345p+12_", "0", ErrSyntax},
+
+       {"1e100x", "0", ErrSyntax},
+       {"1e1000x", "0", ErrSyntax},
 }
 
 var atof32tests = []atofTest{
index f6c4efaef60165477f15ea5fc07cbb530212e6fa..631b487d9762bb71368b619e66feb454e5379bc2 100644 (file)
@@ -57,6 +57,8 @@ const IntSize = intSize
 const maxUint64 = 1<<64 - 1
 
 // ParseUint is like ParseInt but for unsigned numbers.
+//
+// A sign prefix is not permitted.
 func ParseUint(s string, base int, bitSize int) (uint64, error) {
        const fnParseUint = "ParseUint"
 
@@ -143,7 +145,7 @@ func ParseUint(s string, base int, bitSize int) (uint64, error) {
 
                n1 := n + uint64(d)
                if n1 < n || n1 > maxVal {
-                       // n+v overflows
+                       // n+d overflows
                        return maxVal, rangeError(fnParseUint, s0)
                }
                n = n1
@@ -159,10 +161,13 @@ func ParseUint(s string, base int, bitSize int) (uint64, error) {
 // ParseInt interprets a string s in the given base (0, 2 to 36) and
 // bit size (0 to 64) and returns the corresponding value i.
 //
+// The string may begin with a leading sign: "+" or "-".
+//
 // If the base argument is 0, the true base is implied by the string's
-// prefix: 2 for "0b", 8 for "0" or "0o", 16 for "0x", and 10 otherwise.
-// Also, for argument base 0 only, underscore characters are permitted
-// as defined by the Go syntax for integer literals.
+// prefix following the sign (if present): 2 for "0b", 8 for "0" or "0o",
+// 16 for "0x", and 10 otherwise. Also, for argument base 0 only,
+// underscore characters are permitted as defined by the Go syntax for
+// integer literals.
 //
 // The bitSize argument specifies the integer type
 // that the result must fit into. Bit sizes 0, 8, 16, 32, and 64
index 178fb01ea7edac7f3178de5c0a1c1b7523bded43..867fa66a14ca8bbe8e13fe4a364129ef1150c1db 100644 (file)
@@ -33,6 +33,9 @@ var parseUint64Tests = []parseUint64Test{
        {"_12345", 0, ErrSyntax},
        {"1__2345", 0, ErrSyntax},
        {"12345_", 0, ErrSyntax},
+       {"-0", 0, ErrSyntax},
+       {"-1", 0, ErrSyntax},
+       {"+1", 0, ErrSyntax},
 }
 
 type parseUint64BaseTest struct {
@@ -140,8 +143,10 @@ var parseInt64Tests = []parseInt64Test{
        {"", 0, ErrSyntax},
        {"0", 0, nil},
        {"-0", 0, nil},
+       {"+0", 0, nil},
        {"1", 1, nil},
        {"-1", -1, nil},
+       {"+1", 1, nil},
        {"12345", 12345, nil},
        {"-12345", -12345, nil},
        {"012345", 12345, nil},
@@ -236,6 +241,11 @@ var parseInt64BaseTests = []parseInt64BaseTest{
        {"0__12345", 0, 0, ErrSyntax},
        {"01234__5", 0, 0, ErrSyntax},
        {"012345_", 0, 0, ErrSyntax},
+
+       {"+0xf", 0, 0xf, nil},
+       {"-0xf", 0, -0xf, nil},
+       {"0x+f", 0, 0, ErrSyntax},
+       {"0x-f", 0, 0, ErrSyntax},
 }
 
 type parseUint32Test struct {
diff --git a/libgo/go/strconv/bytealg.go b/libgo/go/strconv/bytealg.go
new file mode 100644 (file)
index 0000000..a2bb12c
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !compiler_bootstrap
+// +build !compiler_bootstrap
+
+package strconv
+
+import "internal/bytealg"
+
+// index returns the index of the first instance of c in s, or -1 if missing.
+func index(s string, c byte) int {
+       return bytealg.IndexByteString(s, c)
+}
diff --git a/libgo/go/strconv/bytealg_bootstrap.go b/libgo/go/strconv/bytealg_bootstrap.go
new file mode 100644 (file)
index 0000000..0ed79f4
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build compiler_bootstrap
+// +build compiler_bootstrap
+
+package strconv
+
+// index returns the index of the first instance of c in s, or -1 if missing.
+func index(s string, c byte) int {
+       for i := 0; i < len(s); i++ {
+               if s[i] == c {
+                       return i
+               }
+       }
+       return -1
+}
index 6c7f852eba8061efb18e83aa2741816279ca8064..fecd1b93451d0794af39198efc42462aa41bece1 100644 (file)
@@ -29,7 +29,7 @@ func eiselLemire64(man uint64, exp10 int, neg bool) (f float64, ok bool) {
        // Exp10 Range.
        if man == 0 {
                if neg {
-                       f = math.Float64frombits(0x80000000_00000000) // Negative zero.
+                       f = math.Float64frombits(0x8000000000000000) // Negative zero.
                }
                return f, true
        }
@@ -39,7 +39,7 @@ func eiselLemire64(man uint64, exp10 int, neg bool) (f float64, ok bool) {
 
        // Normalization.
        clz := bits.LeadingZeros64(man)
-       man <<= clz
+       man <<= uint(clz)
        const float64ExponentBias = 1023
        retExp2 := uint64(217706*exp10>>16+64+float64ExponentBias) - uint64(clz)
 
@@ -84,9 +84,9 @@ func eiselLemire64(man uint64, exp10 int, neg bool) (f float64, ok bool) {
        if retExp2-1 >= 0x7FF-1 {
                return 0, false
        }
-       retBits := retExp2<<52 | retMantissa&0x000FFFFF_FFFFFFFF
+       retBits := retExp2<<52 | retMantissa&0x000FFFFFFFFFFFFF
        if neg {
-               retBits |= 0x80000000_00000000
+               retBits |= 0x8000000000000000
        }
        return math.Float64frombits(retBits), true
 }
@@ -114,7 +114,7 @@ func eiselLemire32(man uint64, exp10 int, neg bool) (f float32, ok bool) {
 
        // Normalization.
        clz := bits.LeadingZeros64(man)
-       man <<= clz
+       man <<= uint(clz)
        const float32ExponentBias = 127
        retExp2 := uint64(217706*exp10>>16+64+float32ExponentBias) - uint64(clz)
 
@@ -122,13 +122,13 @@ func eiselLemire32(man uint64, exp10 int, neg bool) (f float32, ok bool) {
        xHi, xLo := bits.Mul64(man, detailedPowersOfTen[exp10-detailedPowersOfTenMinExp10][1])
 
        // Wider Approximation.
-       if xHi&0x3F_FFFFFFFF == 0x3F_FFFFFFFF && xLo+man < man {
+       if xHi&0x3FFFFFFFFF == 0x3FFFFFFFFF && xLo+man < man {
                yHi, yLo := bits.Mul64(man, detailedPowersOfTen[exp10-detailedPowersOfTenMinExp10][0])
                mergedHi, mergedLo := xHi, xLo+yHi
                if mergedLo < xLo {
                        mergedHi++
                }
-               if mergedHi&0x3F_FFFFFFFF == 0x3F_FFFFFFFF && mergedLo+1 == 0 && yLo+man < man {
+               if mergedHi&0x3FFFFFFFFF == 0x3FFFFFFFFF && mergedLo+1 == 0 && yLo+man < man {
                        return 0, false
                }
                xHi, xLo = mergedHi, mergedLo
@@ -140,7 +140,7 @@ func eiselLemire32(man uint64, exp10 int, neg bool) (f float32, ok bool) {
        retExp2 -= 1 ^ msb
 
        // Half-way Ambiguity.
-       if xLo == 0 && xHi&0x3F_FFFFFFFF == 0 && retMantissa&3 == 1 {
+       if xLo == 0 && xHi&0x3FFFFFFFFF == 0 && retMantissa&3 == 1 {
                return 0, false
        }
 
diff --git a/libgo/go/strconv/extfloat.go b/libgo/go/strconv/extfloat.go
deleted file mode 100644 (file)
index e7bfe51..0000000
+++ /dev/null
@@ -1,517 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package strconv
-
-import (
-       "math/bits"
-)
-
-// An extFloat represents an extended floating-point number, with more
-// precision than a float64. It does not try to save bits: the
-// number represented by the structure is mant*(2^exp), with a negative
-// sign if neg is true.
-type extFloat struct {
-       mant uint64
-       exp  int
-       neg  bool
-}
-
-// Powers of ten taken from double-conversion library.
-// https://code.google.com/p/double-conversion/
-const (
-       firstPowerOfTen = -348
-       stepPowerOfTen  = 8
-)
-
-var smallPowersOfTen = [...]extFloat{
-       {1 << 63, -63, false},        // 1
-       {0xa << 60, -60, false},      // 1e1
-       {0x64 << 57, -57, false},     // 1e2
-       {0x3e8 << 54, -54, false},    // 1e3
-       {0x2710 << 50, -50, false},   // 1e4
-       {0x186a0 << 47, -47, false},  // 1e5
-       {0xf4240 << 44, -44, false},  // 1e6
-       {0x989680 << 40, -40, false}, // 1e7
-}
-
-var powersOfTen = [...]extFloat{
-       {0xfa8fd5a0081c0288, -1220, false}, // 10^-348
-       {0xbaaee17fa23ebf76, -1193, false}, // 10^-340
-       {0x8b16fb203055ac76, -1166, false}, // 10^-332
-       {0xcf42894a5dce35ea, -1140, false}, // 10^-324
-       {0x9a6bb0aa55653b2d, -1113, false}, // 10^-316
-       {0xe61acf033d1a45df, -1087, false}, // 10^-308
-       {0xab70fe17c79ac6ca, -1060, false}, // 10^-300
-       {0xff77b1fcbebcdc4f, -1034, false}, // 10^-292
-       {0xbe5691ef416bd60c, -1007, false}, // 10^-284
-       {0x8dd01fad907ffc3c, -980, false},  // 10^-276
-       {0xd3515c2831559a83, -954, false},  // 10^-268
-       {0x9d71ac8fada6c9b5, -927, false},  // 10^-260
-       {0xea9c227723ee8bcb, -901, false},  // 10^-252
-       {0xaecc49914078536d, -874, false},  // 10^-244
-       {0x823c12795db6ce57, -847, false},  // 10^-236
-       {0xc21094364dfb5637, -821, false},  // 10^-228
-       {0x9096ea6f3848984f, -794, false},  // 10^-220
-       {0xd77485cb25823ac7, -768, false},  // 10^-212
-       {0xa086cfcd97bf97f4, -741, false},  // 10^-204
-       {0xef340a98172aace5, -715, false},  // 10^-196
-       {0xb23867fb2a35b28e, -688, false},  // 10^-188
-       {0x84c8d4dfd2c63f3b, -661, false},  // 10^-180
-       {0xc5dd44271ad3cdba, -635, false},  // 10^-172
-       {0x936b9fcebb25c996, -608, false},  // 10^-164
-       {0xdbac6c247d62a584, -582, false},  // 10^-156
-       {0xa3ab66580d5fdaf6, -555, false},  // 10^-148
-       {0xf3e2f893dec3f126, -529, false},  // 10^-140
-       {0xb5b5ada8aaff80b8, -502, false},  // 10^-132
-       {0x87625f056c7c4a8b, -475, false},  // 10^-124
-       {0xc9bcff6034c13053, -449, false},  // 10^-116
-       {0x964e858c91ba2655, -422, false},  // 10^-108
-       {0xdff9772470297ebd, -396, false},  // 10^-100
-       {0xa6dfbd9fb8e5b88f, -369, false},  // 10^-92
-       {0xf8a95fcf88747d94, -343, false},  // 10^-84
-       {0xb94470938fa89bcf, -316, false},  // 10^-76
-       {0x8a08f0f8bf0f156b, -289, false},  // 10^-68
-       {0xcdb02555653131b6, -263, false},  // 10^-60
-       {0x993fe2c6d07b7fac, -236, false},  // 10^-52
-       {0xe45c10c42a2b3b06, -210, false},  // 10^-44
-       {0xaa242499697392d3, -183, false},  // 10^-36
-       {0xfd87b5f28300ca0e, -157, false},  // 10^-28
-       {0xbce5086492111aeb, -130, false},  // 10^-20
-       {0x8cbccc096f5088cc, -103, false},  // 10^-12
-       {0xd1b71758e219652c, -77, false},   // 10^-4
-       {0x9c40000000000000, -50, false},   // 10^4
-       {0xe8d4a51000000000, -24, false},   // 10^12
-       {0xad78ebc5ac620000, 3, false},     // 10^20
-       {0x813f3978f8940984, 30, false},    // 10^28
-       {0xc097ce7bc90715b3, 56, false},    // 10^36
-       {0x8f7e32ce7bea5c70, 83, false},    // 10^44
-       {0xd5d238a4abe98068, 109, false},   // 10^52
-       {0x9f4f2726179a2245, 136, false},   // 10^60
-       {0xed63a231d4c4fb27, 162, false},   // 10^68
-       {0xb0de65388cc8ada8, 189, false},   // 10^76
-       {0x83c7088e1aab65db, 216, false},   // 10^84
-       {0xc45d1df942711d9a, 242, false},   // 10^92
-       {0x924d692ca61be758, 269, false},   // 10^100
-       {0xda01ee641a708dea, 295, false},   // 10^108
-       {0xa26da3999aef774a, 322, false},   // 10^116
-       {0xf209787bb47d6b85, 348, false},   // 10^124
-       {0xb454e4a179dd1877, 375, false},   // 10^132
-       {0x865b86925b9bc5c2, 402, false},   // 10^140
-       {0xc83553c5c8965d3d, 428, false},   // 10^148
-       {0x952ab45cfa97a0b3, 455, false},   // 10^156
-       {0xde469fbd99a05fe3, 481, false},   // 10^164
-       {0xa59bc234db398c25, 508, false},   // 10^172
-       {0xf6c69a72a3989f5c, 534, false},   // 10^180
-       {0xb7dcbf5354e9bece, 561, false},   // 10^188
-       {0x88fcf317f22241e2, 588, false},   // 10^196
-       {0xcc20ce9bd35c78a5, 614, false},   // 10^204
-       {0x98165af37b2153df, 641, false},   // 10^212
-       {0xe2a0b5dc971f303a, 667, false},   // 10^220
-       {0xa8d9d1535ce3b396, 694, false},   // 10^228
-       {0xfb9b7cd9a4a7443c, 720, false},   // 10^236
-       {0xbb764c4ca7a44410, 747, false},   // 10^244
-       {0x8bab8eefb6409c1a, 774, false},   // 10^252
-       {0xd01fef10a657842c, 800, false},   // 10^260
-       {0x9b10a4e5e9913129, 827, false},   // 10^268
-       {0xe7109bfba19c0c9d, 853, false},   // 10^276
-       {0xac2820d9623bf429, 880, false},   // 10^284
-       {0x80444b5e7aa7cf85, 907, false},   // 10^292
-       {0xbf21e44003acdd2d, 933, false},   // 10^300
-       {0x8e679c2f5e44ff8f, 960, false},   // 10^308
-       {0xd433179d9c8cb841, 986, false},   // 10^316
-       {0x9e19db92b4e31ba9, 1013, false},  // 10^324
-       {0xeb96bf6ebadf77d9, 1039, false},  // 10^332
-       {0xaf87023b9bf0ee6b, 1066, false},  // 10^340
-}
-
-// AssignComputeBounds sets f to the floating point value
-// defined by mant, exp and precision given by flt. It returns
-// lower, upper such that any number in the closed interval
-// [lower, upper] is converted back to the same floating point number.
-func (f *extFloat) AssignComputeBounds(mant uint64, exp int, neg bool, flt *floatInfo) (lower, upper extFloat) {
-       f.mant = mant
-       f.exp = exp - int(flt.mantbits)
-       f.neg = neg
-       if f.exp <= 0 && mant == (mant>>uint(-f.exp))<<uint(-f.exp) {
-               // An exact integer
-               f.mant >>= uint(-f.exp)
-               f.exp = 0
-               return *f, *f
-       }
-       expBiased := exp - flt.bias
-
-       upper = extFloat{mant: 2*f.mant + 1, exp: f.exp - 1, neg: f.neg}
-       if mant != 1<<flt.mantbits || expBiased == 1 {
-               lower = extFloat{mant: 2*f.mant - 1, exp: f.exp - 1, neg: f.neg}
-       } else {
-               lower = extFloat{mant: 4*f.mant - 1, exp: f.exp - 2, neg: f.neg}
-       }
-       return
-}
-
-// Normalize normalizes f so that the highest bit of the mantissa is
-// set, and returns the number by which the mantissa was left-shifted.
-func (f *extFloat) Normalize() uint {
-       // bits.LeadingZeros64 would return 64
-       if f.mant == 0 {
-               return 0
-       }
-       shift := bits.LeadingZeros64(f.mant)
-       f.mant <<= uint(shift)
-       f.exp -= shift
-       return uint(shift)
-}
-
-// Multiply sets f to the product f*g: the result is correctly rounded,
-// but not normalized.
-func (f *extFloat) Multiply(g extFloat) {
-       hi, lo := bits.Mul64(f.mant, g.mant)
-       // Round up.
-       f.mant = hi + (lo >> 63)
-       f.exp = f.exp + g.exp + 64
-}
-
-var uint64pow10 = [...]uint64{
-       1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
-       1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
-}
-
-// Frexp10 is an analogue of math.Frexp for decimal powers. It scales
-// f by an approximate power of ten 10^-exp, and returns exp10, so
-// that f*10^exp10 has the same value as the old f, up to an ulp,
-// as well as the index of 10^-exp in the powersOfTen table.
-func (f *extFloat) frexp10() (exp10, index int) {
-       // The constants expMin and expMax constrain the final value of the
-       // binary exponent of f. We want a small integral part in the result
-       // because finding digits of an integer requires divisions, whereas
-       // digits of the fractional part can be found by repeatedly multiplying
-       // by 10.
-       const expMin = -60
-       const expMax = -32
-       // Find power of ten such that x * 10^n has a binary exponent
-       // between expMin and expMax.
-       approxExp10 := ((expMin+expMax)/2 - f.exp) * 28 / 93 // log(10)/log(2) is close to 93/28.
-       i := (approxExp10 - firstPowerOfTen) / stepPowerOfTen
-Loop:
-       for {
-               exp := f.exp + powersOfTen[i].exp + 64
-               switch {
-               case exp < expMin:
-                       i++
-               case exp > expMax:
-                       i--
-               default:
-                       break Loop
-               }
-       }
-       // Apply the desired decimal shift on f. It will have exponent
-       // in the desired range. This is multiplication by 10^-exp10.
-       f.Multiply(powersOfTen[i])
-
-       return -(firstPowerOfTen + i*stepPowerOfTen), i
-}
-
-// frexp10Many applies a common shift by a power of ten to a, b, c.
-func frexp10Many(a, b, c *extFloat) (exp10 int) {
-       exp10, i := c.frexp10()
-       a.Multiply(powersOfTen[i])
-       b.Multiply(powersOfTen[i])
-       return
-}
-
-// FixedDecimal stores in d the first n significant digits
-// of the decimal representation of f. It returns false
-// if it cannot be sure of the answer.
-func (f *extFloat) FixedDecimal(d *decimalSlice, n int) bool {
-       if f.mant == 0 {
-               d.nd = 0
-               d.dp = 0
-               d.neg = f.neg
-               return true
-       }
-       if n == 0 {
-               panic("strconv: internal error: extFloat.FixedDecimal called with n == 0")
-       }
-       // Multiply by an appropriate power of ten to have a reasonable
-       // number to process.
-       f.Normalize()
-       exp10, _ := f.frexp10()
-
-       shift := uint(-f.exp)
-       integer := uint32(f.mant >> shift)
-       fraction := f.mant - (uint64(integer) << shift)
-       ε := uint64(1) // ε is the uncertainty we have on the mantissa of f.
-
-       // Write exactly n digits to d.
-       needed := n        // how many digits are left to write.
-       integerDigits := 0 // the number of decimal digits of integer.
-       pow10 := uint64(1) // the power of ten by which f was scaled.
-       for i, pow := 0, uint64(1); i < 20; i++ {
-               if pow > uint64(integer) {
-                       integerDigits = i
-                       break
-               }
-               pow *= 10
-       }
-       rest := integer
-       if integerDigits > needed {
-               // the integral part is already large, trim the last digits.
-               pow10 = uint64pow10[integerDigits-needed]
-               integer /= uint32(pow10)
-               rest -= integer * uint32(pow10)
-       } else {
-               rest = 0
-       }
-
-       // Write the digits of integer: the digits of rest are omitted.
-       var buf [32]byte
-       pos := len(buf)
-       for v := integer; v > 0; {
-               v1 := v / 10
-               v -= 10 * v1
-               pos--
-               buf[pos] = byte(v + '0')
-               v = v1
-       }
-       for i := pos; i < len(buf); i++ {
-               d.d[i-pos] = buf[i]
-       }
-       nd := len(buf) - pos
-       d.nd = nd
-       d.dp = integerDigits + exp10
-       needed -= nd
-
-       if needed > 0 {
-               if rest != 0 || pow10 != 1 {
-                       panic("strconv: internal error, rest != 0 but needed > 0")
-               }
-               // Emit digits for the fractional part. Each time, 10*fraction
-               // fits in a uint64 without overflow.
-               for needed > 0 {
-                       fraction *= 10
-                       ε *= 10 // the uncertainty scales as we multiply by ten.
-                       if 2*ε > 1<<shift {
-                               // the error is so large it could modify which digit to write, abort.
-                               return false
-                       }
-                       digit := fraction >> shift
-                       d.d[nd] = byte(digit + '0')
-                       fraction -= digit << shift
-                       nd++
-                       needed--
-               }
-               d.nd = nd
-       }
-
-       // We have written a truncation of f (a numerator / 10^d.dp). The remaining part
-       // can be interpreted as a small number (< 1) to be added to the last digit of the
-       // numerator.
-       //
-       // If rest > 0, the amount is:
-       //    (rest<<shift | fraction) / (pow10 << shift)
-       //    fraction being known with a ±ε uncertainty.
-       //    The fact that n > 0 guarantees that pow10 << shift does not overflow a uint64.
-       //
-       // If rest = 0, pow10 == 1 and the amount is
-       //    fraction / (1 << shift)
-       //    fraction being known with a ±ε uncertainty.
-       //
-       // We pass this information to the rounding routine for adjustment.
-
-       ok := adjustLastDigitFixed(d, uint64(rest)<<shift|fraction, pow10, shift, ε)
-       if !ok {
-               return false
-       }
-       // Trim trailing zeros.
-       for i := d.nd - 1; i >= 0; i-- {
-               if d.d[i] != '0' {
-                       d.nd = i + 1
-                       break
-               }
-       }
-       return true
-}
-
-// adjustLastDigitFixed assumes d contains the representation of the integral part
-// of some number, whose fractional part is num / (den << shift). The numerator
-// num is only known up to an uncertainty of size ε, assumed to be less than
-// (den << shift)/2.
-//
-// It will increase the last digit by one to account for correct rounding, typically
-// when the fractional part is greater than 1/2, and will return false if ε is such
-// that no correct answer can be given.
-func adjustLastDigitFixed(d *decimalSlice, num, den uint64, shift uint, ε uint64) bool {
-       if num > den<<shift {
-               panic("strconv: num > den<<shift in adjustLastDigitFixed")
-       }
-       if 2*ε > den<<shift {
-               panic("strconv: ε > (den<<shift)/2")
-       }
-       if 2*(num+ε) < den<<shift {
-               return true
-       }
-       if 2*(num-ε) > den<<shift {
-               // increment d by 1.
-               i := d.nd - 1
-               for ; i >= 0; i-- {
-                       if d.d[i] == '9' {
-                               d.nd--
-                       } else {
-                               break
-                       }
-               }
-               if i < 0 {
-                       d.d[0] = '1'
-                       d.nd = 1
-                       d.dp++
-               } else {
-                       d.d[i]++
-               }
-               return true
-       }
-       return false
-}
-
-// ShortestDecimal stores in d the shortest decimal representation of f
-// which belongs to the open interval (lower, upper), where f is supposed
-// to lie. It returns false whenever the result is unsure. The implementation
-// uses the Grisu3 algorithm.
-func (f *extFloat) ShortestDecimal(d *decimalSlice, lower, upper *extFloat) bool {
-       if f.mant == 0 {
-               d.nd = 0
-               d.dp = 0
-               d.neg = f.neg
-               return true
-       }
-       if f.exp == 0 && *lower == *f && *lower == *upper {
-               // an exact integer.
-               var buf [24]byte
-               n := len(buf) - 1
-               for v := f.mant; v > 0; {
-                       v1 := v / 10
-                       v -= 10 * v1
-                       buf[n] = byte(v + '0')
-                       n--
-                       v = v1
-               }
-               nd := len(buf) - n - 1
-               for i := 0; i < nd; i++ {
-                       d.d[i] = buf[n+1+i]
-               }
-               d.nd, d.dp = nd, nd
-               for d.nd > 0 && d.d[d.nd-1] == '0' {
-                       d.nd--
-               }
-               if d.nd == 0 {
-                       d.dp = 0
-               }
-               d.neg = f.neg
-               return true
-       }
-       upper.Normalize()
-       // Uniformize exponents.
-       if f.exp > upper.exp {
-               f.mant <<= uint(f.exp - upper.exp)
-               f.exp = upper.exp
-       }
-       if lower.exp > upper.exp {
-               lower.mant <<= uint(lower.exp - upper.exp)
-               lower.exp = upper.exp
-       }
-
-       exp10 := frexp10Many(lower, f, upper)
-       // Take a safety margin due to rounding in frexp10Many, but we lose precision.
-       upper.mant++
-       lower.mant--
-
-       // The shortest representation of f is either rounded up or down, but
-       // in any case, it is a truncation of upper.
-       shift := uint(-upper.exp)
-       integer := uint32(upper.mant >> shift)
-       fraction := upper.mant - (uint64(integer) << shift)
-
-       // How far we can go down from upper until the result is wrong.
-       allowance := upper.mant - lower.mant
-       // How far we should go to get a very precise result.
-       targetDiff := upper.mant - f.mant
-
-       // Count integral digits: there are at most 10.
-       var integerDigits int
-       for i, pow := 0, uint64(1); i < 20; i++ {
-               if pow > uint64(integer) {
-                       integerDigits = i
-                       break
-               }
-               pow *= 10
-       }
-       for i := 0; i < integerDigits; i++ {
-               pow := uint64pow10[integerDigits-i-1]
-               digit := integer / uint32(pow)
-               d.d[i] = byte(digit + '0')
-               integer -= digit * uint32(pow)
-               // evaluate whether we should stop.
-               if currentDiff := uint64(integer)<<shift + fraction; currentDiff < allowance {
-                       d.nd = i + 1
-                       d.dp = integerDigits + exp10
-                       d.neg = f.neg
-                       // Sometimes allowance is so large the last digit might need to be
-                       // decremented to get closer to f.
-                       return adjustLastDigit(d, currentDiff, targetDiff, allowance, pow<<shift, 2)
-               }
-       }
-       d.nd = integerDigits
-       d.dp = d.nd + exp10
-       d.neg = f.neg
-
-       // Compute digits of the fractional part. At each step fraction does not
-       // overflow. The choice of minExp implies that fraction is less than 2^60.
-       var digit int
-       multiplier := uint64(1)
-       for {
-               fraction *= 10
-               multiplier *= 10
-               digit = int(fraction >> shift)
-               d.d[d.nd] = byte(digit + '0')
-               d.nd++
-               fraction -= uint64(digit) << shift
-               if fraction < allowance*multiplier {
-                       // We are in the admissible range. Note that if allowance is about to
-                       // overflow, that is, allowance > 2^64/10, the condition is automatically
-                       // true due to the limited range of fraction.
-                       return adjustLastDigit(d,
-                               fraction, targetDiff*multiplier, allowance*multiplier,
-                               1<<shift, multiplier*2)
-               }
-       }
-}
-
-// adjustLastDigit modifies d = x-currentDiff*ε, to get closest to
-// d = x-targetDiff*ε, without becoming smaller than x-maxDiff*ε.
-// It assumes that a decimal digit is worth ulpDecimal*ε, and that
-// all data is known with an error estimate of ulpBinary*ε.
-func adjustLastDigit(d *decimalSlice, currentDiff, targetDiff, maxDiff, ulpDecimal, ulpBinary uint64) bool {
-       if ulpDecimal < 2*ulpBinary {
-               // Approximation is too wide.
-               return false
-       }
-       for currentDiff+ulpDecimal/2+ulpBinary < targetDiff {
-               d.d[d.nd-1]--
-               currentDiff += ulpDecimal
-       }
-       if currentDiff+ulpDecimal <= targetDiff+ulpDecimal/2+ulpBinary {
-               // we have two choices, and don't know what to do.
-               return false
-       }
-       if currentDiff < ulpBinary || currentDiff > maxDiff-ulpBinary {
-               // we went too far
-               return false
-       }
-       if d.nd == 1 && d.d[0] == '0' {
-               // the number has actually reached zero.
-               d.nd = 0
-               d.dp = 0
-       }
-       return true
-}
index 8ce6ef30b44b5d7631d4ad1f1db64e753fe596cd..eca04b851c3ad0e21c295077d8f20f40e833a0b0 100644 (file)
@@ -113,15 +113,11 @@ func genericFtoa(dst []byte, val float64, fmt byte, prec, bitSize int) []byte {
        // Negative precision means "only as much as needed to be exact."
        shortest := prec < 0
        if shortest {
-               // Try Grisu3 algorithm.
-               f := new(extFloat)
-               lower, upper := f.AssignComputeBounds(mant, exp, neg, flt)
+               // Use Ryu algorithm.
                var buf [32]byte
                digs.d = buf[:]
-               ok = f.ShortestDecimal(&digs, &lower, &upper)
-               if !ok {
-                       return bigFtoa(dst, prec, fmt, neg, mant, exp, flt)
-               }
+               ryuFtoaShortest(&digs, mant, exp-int(flt.mantbits), flt)
+               ok = true
                // Precision for shortest representation mode.
                switch fmt {
                case 'e', 'E':
@@ -143,12 +139,15 @@ func genericFtoa(dst []byte, val float64, fmt byte, prec, bitSize int) []byte {
                        }
                        digits = prec
                }
-               if digits <= 15 {
-                       // try fast algorithm when the number of digits is reasonable.
-                       var buf [24]byte
+               var buf [24]byte
+               if bitSize == 32 && digits <= 9 {
+                       digs.d = buf[:]
+                       ryuFtoaFixed32(&digs, uint32(mant), exp-int(flt.mantbits), digits)
+                       ok = true
+               } else if digits <= 18 {
                        digs.d = buf[:]
-                       f := extFloat{mant, exp - int(flt.mantbits), neg}
-                       ok = f.FixedDecimal(&digs, digits)
+                       ryuFtoaFixed64(&digs, mant, exp-int(flt.mantbits), digits)
+                       ok = true
                }
        }
        if !ok {
index 99cca17542ffc2e74a0be94880e987a4ab7cb665..73008b1c6219132b231e220b8d12a0bc8ebe3668 100644 (file)
@@ -40,6 +40,7 @@ var ftoatests = []ftoaTest{
        {200000, 'x', -1, "0x1.86ap+17"},
        {200000, 'X', -1, "0X1.86AP+17"},
        {2000000, 'g', -1, "2e+06"},
+       {1e10, 'g', -1, "1e+10"},
 
        // g conversion and zero suppression
        {400, 'g', 2, "4e+02"},
@@ -77,6 +78,15 @@ var ftoatests = []ftoaTest{
        {1.2345e6, 'f', 5, "1234500.00000"},
        {1.2345e6, 'g', 5, "1.2345e+06"},
 
+       // Round to even
+       {1.2345e6, 'e', 3, "1.234e+06"},
+       {1.2355e6, 'e', 3, "1.236e+06"},
+       {1.2345, 'f', 3, "1.234"},
+       {1.2355, 'f', 3, "1.236"},
+       {1234567890123456.5, 'e', 15, "1.234567890123456e+15"},
+       {1234567890123457.5, 'e', 15, "1.234567890123458e+15"},
+       {108678236358137.625, 'g', -1, "1.0867823635813762e+14"},
+
        {1e23, 'e', 17, "9.99999999999999916e+22"},
        {1e23, 'f', 17, "99999999999999991611392.00000000000000000"},
        {1e23, 'g', 17, "9.9999999999999992e+22"},
@@ -183,6 +193,25 @@ func TestFtoa(t *testing.T) {
        }
 }
 
+func TestFtoaPowersOfTwo(t *testing.T) {
+       for exp := -2048; exp <= 2048; exp++ {
+               f := math.Ldexp(1, exp)
+               if !math.IsInf(f, 0) {
+                       s := FormatFloat(f, 'e', -1, 64)
+                       if x, _ := ParseFloat(s, 64); x != f {
+                               t.Errorf("failed roundtrip %v => %s => %v", f, s, x)
+                       }
+               }
+               f32 := float32(f)
+               if !math.IsInf(float64(f32), 0) {
+                       s := FormatFloat(float64(f32), 'e', -1, 32)
+                       if x, _ := ParseFloat(s, 32); float32(x) != f32 {
+                               t.Errorf("failed roundtrip %v => %s => %v", f32, s, float32(x))
+                       }
+               }
+       }
+}
+
 func TestFtoaRandom(t *testing.T) {
        N := int(1e4)
        if testing.Short() {
@@ -232,6 +261,7 @@ var ftoaBenches = []struct {
        {"Float", 339.7784, 'g', -1, 64},
        {"Exp", -5.09e75, 'g', -1, 64},
        {"NegExp", -5.11e-95, 'g', -1, 64},
+       {"LongExp", 1.234567890123456e-78, 'g', -1, 64},
 
        {"Big", 123456789123456789123456789, 'g', -1, 64},
        {"BinaryExp", -1, 'b', -1, 64},
@@ -241,14 +271,30 @@ var ftoaBenches = []struct {
        {"32Point", 339.7784, 'g', -1, 32},
        {"32Exp", -5.09e25, 'g', -1, 32},
        {"32NegExp", -5.11e-25, 'g', -1, 32},
+       {"32Shortest", 1.234567e-8, 'g', -1, 32},
+       {"32Fixed8Hard", math.Ldexp(15961084, -125), 'e', 8, 32},
+       {"32Fixed9Hard", math.Ldexp(14855922, -83), 'e', 9, 32},
 
        {"64Fixed1", 123456, 'e', 3, 64},
        {"64Fixed2", 123.456, 'e', 3, 64},
        {"64Fixed3", 1.23456e+78, 'e', 3, 64},
        {"64Fixed4", 1.23456e-78, 'e', 3, 64},
+       {"64Fixed12", 1.23456e-78, 'e', 12, 64},
+       {"64Fixed16", 1.23456e-78, 'e', 16, 64},
+       // From testdata/testfp.txt
+       {"64Fixed12Hard", math.Ldexp(6965949469487146, -249), 'e', 12, 64},
+       {"64Fixed17Hard", math.Ldexp(8887055249355788, 665), 'e', 17, 64},
+       {"64Fixed18Hard", math.Ldexp(6994187472632449, 690), 'e', 18, 64},
 
        // Trigger slow path (see issue #15672).
-       {"Slowpath64", 622666234635.3213e-320, 'e', -1, 64},
+       // The shortest is: 8.034137530808823e+43
+       {"Slowpath64", 8.03413753080882349e+43, 'e', -1, 64},
+       // This denormal is pathological because the lower/upper
+       // halfways to neighboring floats are:
+       // 622666234635.321003e-320 ~= 622666234635.321e-320
+       // 622666234635.321497e-320 ~= 622666234635.3215e-320
+       // making it hard to find the 3rd digit
+       {"SlowpathDenormal64", 622666234635.3213e-320, 'e', -1, 64},
 }
 
 func BenchmarkFormatFloat(b *testing.B) {
diff --git a/libgo/go/strconv/ftoaryu.go b/libgo/go/strconv/ftoaryu.go
new file mode 100644 (file)
index 0000000..1c61288
--- /dev/null
@@ -0,0 +1,567 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package strconv
+
+import (
+       "math/bits"
+)
+
+// binary to decimal conversion using the Ryū algorithm.
+//
+// See Ulf Adams, "Ryū: Fast Float-to-String Conversion" (doi:10.1145/3192366.3192369)
+//
+// Fixed precision formatting is a variant of the original paper's
+// algorithm, where a single multiplication by 10^k is required,
+// sharing the same rounding guarantees.
+
+// ryuFtoaFixed32 formats mant*(2^exp) with prec decimal digits.
+func ryuFtoaFixed32(d *decimalSlice, mant uint32, exp int, prec int) {
+       if prec < 0 {
+               panic("ryuFtoaFixed32 called with negative prec")
+       }
+       if prec > 9 {
+               panic("ryuFtoaFixed32 called with prec > 9")
+       }
+       // Zero input.
+       if mant == 0 {
+               d.nd, d.dp = 0, 0
+               return
+       }
+       // Renormalize to a 25-bit mantissa.
+       e2 := exp
+       if b := bits.Len32(mant); b < 25 {
+               mant <<= uint(25 - b)
+               e2 += int(b) - 25
+       }
+       // Choose an exponent such that rounded mant*(2^e2)*(10^q) has
+       // at least prec decimal digits, i.e
+       //     mant*(2^e2)*(10^q) >= 10^(prec-1)
+       // Because mant >= 2^24, it is enough to choose:
+       //     2^(e2+24) >= 10^(-q+prec-1)
+       // or q = -mulByLog2Log10(e2+24) + prec - 1
+       q := -mulByLog2Log10(e2+24) + prec - 1
+
+       // Now compute mant*(2^e2)*(10^q).
+       // Is it an exact computation?
+       // Only small positive powers of 10 are exact (5^28 has 66 bits).
+       exact := q <= 27 && q >= 0
+
+       di, dexp2, d0 := mult64bitPow10(mant, e2, q)
+       if dexp2 >= 0 {
+               panic("not enough significant bits after mult64bitPow10")
+       }
+       // As a special case, computation might still be exact, if exponent
+       // was negative and if it amounts to computing an exact division.
+       // In that case, we ignore all lower bits.
+       // Note that division by 10^11 cannot be exact as 5^11 has 26 bits.
+       if q < 0 && q >= -10 && divisibleByPower5(uint64(mant), -q) {
+               exact = true
+               d0 = true
+       }
+       // Remove extra lower bits and keep rounding info.
+       extra := uint(-dexp2)
+       extraMask := uint32(1<<extra - 1)
+
+       di, dfrac := di>>extra, di&extraMask
+       roundUp := false
+       if exact {
+               // If we computed an exact product, d + 1/2
+               // should round to d+1 if 'd' is odd.
+               roundUp = dfrac > 1<<(extra-1) ||
+                       (dfrac == 1<<(extra-1) && !d0) ||
+                       (dfrac == 1<<(extra-1) && d0 && di&1 == 1)
+       } else {
+               // otherwise, d+1/2 always rounds up because
+               // we truncated below.
+               roundUp = dfrac>>(extra-1) == 1
+       }
+       if dfrac != 0 {
+               d0 = false
+       }
+       // Proceed to the requested number of digits
+       formatDecimal(d, uint64(di), !d0, roundUp, prec)
+       // Adjust exponent
+       d.dp -= q
+}
+
+// ryuFtoaFixed64 formats mant*(2^exp) with prec decimal digits.
+func ryuFtoaFixed64(d *decimalSlice, mant uint64, exp int, prec int) {
+       if prec > 18 {
+               panic("ryuFtoaFixed64 called with prec > 18")
+       }
+       // Zero input.
+       if mant == 0 {
+               d.nd, d.dp = 0, 0
+               return
+       }
+       // Renormalize to a 55-bit mantissa.
+       e2 := exp
+       if b := bits.Len64(mant); b < 55 {
+               mant = mant << uint(55-b)
+               e2 += int(b) - 55
+       }
+       // Choose an exponent such that rounded mant*(2^e2)*(10^q) has
+       // at least prec decimal digits, i.e
+       //     mant*(2^e2)*(10^q) >= 10^(prec-1)
+       // Because mant >= 2^54, it is enough to choose:
+       //     2^(e2+54) >= 10^(-q+prec-1)
+       // or q = -mulByLog2Log10(e2+54) + prec - 1
+       //
+       // The minimal required exponent is -mulByLog2Log10(1025)+18 = -291
+       // The maximal required exponent is mulByLog2Log10(1074)+18 = 342
+       q := -mulByLog2Log10(e2+54) + prec - 1
+
+       // Now compute mant*(2^e2)*(10^q).
+       // Is it an exact computation?
+       // Only small positive powers of 10 are exact (5^55 has 128 bits).
+       exact := q <= 55 && q >= 0
+
+       di, dexp2, d0 := mult128bitPow10(mant, e2, q)
+       if dexp2 >= 0 {
+               panic("not enough significant bits after mult128bitPow10")
+       }
+       // As a special case, computation might still be exact, if exponent
+       // was negative and if it amounts to computing an exact division.
+       // In that case, we ignore all lower bits.
+       // Note that division by 10^23 cannot be exact as 5^23 has 54 bits.
+       if q < 0 && q >= -22 && divisibleByPower5(mant, -q) {
+               exact = true
+               d0 = true
+       }
+       // Remove extra lower bits and keep rounding info.
+       extra := uint(-dexp2)
+       extraMask := uint64(1<<extra - 1)
+
+       di, dfrac := di>>extra, di&extraMask
+       roundUp := false
+       if exact {
+               // If we computed an exact product, d + 1/2
+               // should round to d+1 if 'd' is odd.
+               roundUp = dfrac > 1<<(extra-1) ||
+                       (dfrac == 1<<(extra-1) && !d0) ||
+                       (dfrac == 1<<(extra-1) && d0 && di&1 == 1)
+       } else {
+               // otherwise, d+1/2 always rounds up because
+               // we truncated below.
+               roundUp = dfrac>>(extra-1) == 1
+       }
+       if dfrac != 0 {
+               d0 = false
+       }
+       // Proceed to the requested number of digits
+       formatDecimal(d, di, !d0, roundUp, prec)
+       // Adjust exponent
+       d.dp -= q
+}
+
+var uint64pow10 = [...]uint64{
+       1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+       1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+}
+
+// formatDecimal fills d with at most prec decimal digits
+// of mantissa m. The boolean trunc indicates whether m
+// is truncated compared to the original number being formatted.
+func formatDecimal(d *decimalSlice, m uint64, trunc bool, roundUp bool, prec int) {
+       max := uint64pow10[prec]
+       trimmed := 0
+       for m >= max {
+               a, b := m/10, m%10
+               m = a
+               trimmed++
+               if b > 5 {
+                       roundUp = true
+               } else if b < 5 {
+                       roundUp = false
+               } else { // b == 5
+                       // round up if there are trailing digits,
+                       // or if the new value of m is odd (round-to-even convention)
+                       roundUp = trunc || m&1 == 1
+               }
+               if b != 0 {
+                       trunc = true
+               }
+       }
+       if roundUp {
+               m++
+       }
+       if m >= max {
+               // Happens if di was originally 99999....xx
+               m /= 10
+               trimmed++
+       }
+       // render digits (similar to formatBits)
+       n := uint(prec)
+       d.nd = int(prec)
+       v := m
+       for v >= 100 {
+               var v1, v2 uint64
+               if v>>32 == 0 {
+                       v1, v2 = uint64(uint32(v)/100), uint64(uint32(v)%100)
+               } else {
+                       v1, v2 = v/100, v%100
+               }
+               n -= 2
+               d.d[n+1] = smallsString[2*v2+1]
+               d.d[n+0] = smallsString[2*v2+0]
+               v = v1
+       }
+       if v > 0 {
+               n--
+               d.d[n] = smallsString[2*v+1]
+       }
+       if v >= 10 {
+               n--
+               d.d[n] = smallsString[2*v]
+       }
+       for d.d[d.nd-1] == '0' {
+               d.nd--
+               trimmed++
+       }
+       d.dp = d.nd + trimmed
+}
+
+// ryuFtoaShortest formats mant*2^exp with prec decimal digits.
+func ryuFtoaShortest(d *decimalSlice, mant uint64, exp int, flt *floatInfo) {
+       if mant == 0 {
+               d.nd, d.dp = 0, 0
+               return
+       }
+       // If input is an exact integer with fewer bits than the mantissa,
+       // the previous and next integer are not admissible representations.
+       if exp <= 0 && bits.TrailingZeros64(mant) >= -exp {
+               mant >>= uint(-exp)
+               ryuDigits(d, mant, mant, mant, true, false)
+               return
+       }
+       ml, mc, mu, e2 := computeBounds(mant, exp, flt)
+       if e2 == 0 {
+               ryuDigits(d, ml, mc, mu, true, false)
+               return
+       }
+       // Find 10^q *larger* than 2^-e2
+       q := mulByLog2Log10(-e2) + 1
+
+       // We are going to multiply by 10^q using 128-bit arithmetic.
+       // The exponent is the same for all 3 numbers.
+       var dl, dc, du uint64
+       var dl0, dc0, du0 bool
+       if flt == &float32info {
+               var dl32, dc32, du32 uint32
+               dl32, _, dl0 = mult64bitPow10(uint32(ml), e2, q)
+               dc32, _, dc0 = mult64bitPow10(uint32(mc), e2, q)
+               du32, e2, du0 = mult64bitPow10(uint32(mu), e2, q)
+               dl, dc, du = uint64(dl32), uint64(dc32), uint64(du32)
+       } else {
+               dl, _, dl0 = mult128bitPow10(ml, e2, q)
+               dc, _, dc0 = mult128bitPow10(mc, e2, q)
+               du, e2, du0 = mult128bitPow10(mu, e2, q)
+       }
+       if e2 >= 0 {
+               panic("not enough significant bits after mult128bitPow10")
+       }
+       // Is it an exact computation?
+       if q > 55 {
+               // Large positive powers of ten are not exact
+               dl0, dc0, du0 = false, false, false
+       }
+       if q < 0 && q >= -24 {
+               // Division by a power of ten may be exact.
+               // (note that 5^25 is a 59-bit number so division by 5^25 is never exact).
+               if divisibleByPower5(ml, -q) {
+                       dl0 = true
+               }
+               if divisibleByPower5(mc, -q) {
+                       dc0 = true
+               }
+               if divisibleByPower5(mu, -q) {
+                       du0 = true
+               }
+       }
+       // Express the results (dl, dc, du)*2^e2 as integers.
+       // Extra bits must be removed and rounding hints computed.
+       extra := uint(-e2)
+       extraMask := uint64(1<<extra - 1)
+       // Now compute the floored, integral base 10 mantissas.
+       dl, fracl := dl>>extra, dl&extraMask
+       dc, fracc := dc>>extra, dc&extraMask
+       du, fracu := du>>extra, du&extraMask
+       // Is it allowed to use 'du' as a result?
+       // It is always allowed when it is truncated, but also
+       // if it is exact and the original binary mantissa is even
+       // When disallowed, we can substract 1.
+       uok := !du0 || fracu > 0
+       if du0 && fracu == 0 {
+               uok = mant&1 == 0
+       }
+       if !uok {
+               du--
+       }
+       // Is 'dc' the correctly rounded base 10 mantissa?
+       // The correct rounding might be dc+1
+       cup := false // don't round up.
+       if dc0 {
+               // If we computed an exact product, the half integer
+               // should round to next (even) integer if 'dc' is odd.
+               cup = fracc > 1<<(extra-1) ||
+                       (fracc == 1<<(extra-1) && dc&1 == 1)
+       } else {
+               // otherwise, the result is a lower truncation of the ideal
+               // result.
+               cup = fracc>>(extra-1) == 1
+       }
+       // Is 'dl' an allowed representation?
+       // Only if it is an exact value, and if the original binary mantissa
+       // was even.
+       lok := dl0 && fracl == 0 && (mant&1 == 0)
+       if !lok {
+               dl++
+       }
+       // We need to remember whether the trimmed digits of 'dc' are zero.
+       c0 := dc0 && fracc == 0
+       // render digits
+       ryuDigits(d, dl, dc, du, c0, cup)
+       d.dp -= q
+}
+
+// mulByLog2Log10 returns math.Floor(x * log(2)/log(10)) for an integer x in
+// the range -1600 <= x && x <= +1600.
+//
+// The range restriction lets us work in faster integer arithmetic instead of
+// slower floating point arithmetic. Correctness is verified by unit tests.
+func mulByLog2Log10(x int) int {
+       // log(2)/log(10) ≈ 0.30102999566 ≈ 78913 / 2^18
+       return (x * 78913) >> 18
+}
+
+// mulByLog10Log2 returns math.Floor(x * log(10)/log(2)) for an integer x in
+// the range -500 <= x && x <= +500.
+//
+// The range restriction lets us work in faster integer arithmetic instead of
+// slower floating point arithmetic. Correctness is verified by unit tests.
+func mulByLog10Log2(x int) int {
+       // log(10)/log(2) ≈ 3.32192809489 ≈ 108853 / 2^15
+       return (x * 108853) >> 15
+}
+
+// computeBounds returns a floating-point vector (l, c, u)×2^e2
+// where the mantissas are 55-bit (or 26-bit) integers, describing the interval
+// represented by the input float64 or float32.
+func computeBounds(mant uint64, exp int, flt *floatInfo) (lower, central, upper uint64, e2 int) {
+       if mant != 1<<flt.mantbits || exp == flt.bias+1-int(flt.mantbits) {
+               // regular case (or denormals)
+               lower, central, upper = 2*mant-1, 2*mant, 2*mant+1
+               e2 = exp - 1
+               return
+       } else {
+               // border of an exponent
+               lower, central, upper = 4*mant-1, 4*mant, 4*mant+2
+               e2 = exp - 2
+               return
+       }
+}
+
+func ryuDigits(d *decimalSlice, lower, central, upper uint64,
+       c0, cup bool) {
+       lhi, llo := divmod1e9(lower)
+       chi, clo := divmod1e9(central)
+       uhi, ulo := divmod1e9(upper)
+       if uhi == 0 {
+               // only low digits (for denormals)
+               ryuDigits32(d, llo, clo, ulo, c0, cup, 8)
+       } else if lhi < uhi {
+               // truncate 9 digits at once.
+               if llo != 0 {
+                       lhi++
+               }
+               c0 = c0 && clo == 0
+               cup = (clo > 5e8) || (clo == 5e8 && cup)
+               ryuDigits32(d, lhi, chi, uhi, c0, cup, 8)
+               d.dp += 9
+       } else {
+               d.nd = 0
+               // emit high part
+               n := uint(9)
+               for v := chi; v > 0; {
+                       v1, v2 := v/10, v%10
+                       v = v1
+                       n--
+                       d.d[n] = byte(v2 + '0')
+               }
+               d.d = d.d[n:]
+               d.nd = int(9 - n)
+               // emit low part
+               ryuDigits32(d, llo, clo, ulo,
+                       c0, cup, d.nd+8)
+       }
+       // trim trailing zeros
+       for d.nd > 0 && d.d[d.nd-1] == '0' {
+               d.nd--
+       }
+       // trim initial zeros
+       for d.nd > 0 && d.d[0] == '0' {
+               d.nd--
+               d.dp--
+               d.d = d.d[1:]
+       }
+}
+
+// ryuDigits32 emits decimal digits for a number less than 1e9.
+func ryuDigits32(d *decimalSlice, lower, central, upper uint32,
+       c0, cup bool, endindex int) {
+       if upper == 0 {
+               d.dp = endindex + 1
+               return
+       }
+       trimmed := 0
+       // Remember last trimmed digit to check for round-up.
+       // c0 will be used to remember zeroness of following digits.
+       cNextDigit := 0
+       for upper > 0 {
+               // Repeatedly compute:
+               // l = Ceil(lower / 10^k)
+               // c = Round(central / 10^k)
+               // u = Floor(upper / 10^k)
+               // and stop when c goes out of the (l, u) interval.
+               l := (lower + 9) / 10
+               c, cdigit := central/10, central%10
+               u := upper / 10
+               if l > u {
+                       // don't trim the last digit as it is forbidden to go below l
+                       // other, trim and exit now.
+                       break
+               }
+               // Check that we didn't cross the lower boundary.
+               // The case where l < u but c == l-1 is essentially impossible,
+               // but may happen if:
+               //    lower   = ..11
+               //    central = ..19
+               //    upper   = ..31
+               // and means that 'central' is very close but less than
+               // an integer ending with many zeros, and usually
+               // the "round-up" logic hides the problem.
+               if l == c+1 && c < u {
+                       c++
+                       cdigit = 0
+                       cup = false
+               }
+               trimmed++
+               // Remember trimmed digits of c
+               c0 = c0 && cNextDigit == 0
+               cNextDigit = int(cdigit)
+               lower, central, upper = l, c, u
+       }
+       // should we round up?
+       if trimmed > 0 {
+               cup = cNextDigit > 5 ||
+                       (cNextDigit == 5 && !c0) ||
+                       (cNextDigit == 5 && c0 && central&1 == 1)
+       }
+       if central < upper && cup {
+               central++
+       }
+       // We know where the number ends, fill directly
+       endindex -= trimmed
+       v := central
+       n := endindex
+       for n > d.nd {
+               v1, v2 := v/100, v%100
+               d.d[n] = smallsString[2*v2+1]
+               d.d[n-1] = smallsString[2*v2+0]
+               n -= 2
+               v = v1
+       }
+       if n == d.nd {
+               d.d[n] = byte(v + '0')
+       }
+       d.nd = endindex + 1
+       d.dp = d.nd + trimmed
+}
+
+// mult64bitPow10 takes a floating-point input with a 25-bit
+// mantissa and multiplies it with 10^q. The resulting mantissa
+// is m*P >> 57 where P is a 64-bit element of the detailedPowersOfTen tables.
+// It is typically 31 or 32-bit wide.
+// The returned boolean is true if all trimmed bits were zero.
+//
+// That is:
+//     m*2^e2 * round(10^q) = resM * 2^resE + ε
+//     exact = ε == 0
+func mult64bitPow10(m uint32, e2, q int) (resM uint32, resE int, exact bool) {
+       if q == 0 {
+               // P == 1<<63
+               return m << 6, e2 - 6, true
+       }
+       if q < detailedPowersOfTenMinExp10 || detailedPowersOfTenMaxExp10 < q {
+               // This never happens due to the range of float32/float64 exponent
+               panic("mult64bitPow10: power of 10 is out of range")
+       }
+       pow := detailedPowersOfTen[q-detailedPowersOfTenMinExp10][1]
+       if q < 0 {
+               // Inverse powers of ten must be rounded up.
+               pow += 1
+       }
+       hi, lo := bits.Mul64(uint64(m), pow)
+       e2 += mulByLog10Log2(q) - 63 + 57
+       return uint32(hi<<7 | lo>>57), e2, lo<<7 == 0
+}
+
+// mult128bitPow10 takes a floating-point input with a 55-bit
+// mantissa and multiplies it with 10^q. The resulting mantissa
+// is m*P >> 119 where P is a 128-bit element of the detailedPowersOfTen tables.
+// It is typically 63 or 64-bit wide.
+// The returned boolean is true is all trimmed bits were zero.
+//
+// That is:
+//     m*2^e2 * round(10^q) = resM * 2^resE + ε
+//     exact = ε == 0
+func mult128bitPow10(m uint64, e2, q int) (resM uint64, resE int, exact bool) {
+       if q == 0 {
+               // P == 1<<127
+               return m << 8, e2 - 8, true
+       }
+       if q < detailedPowersOfTenMinExp10 || detailedPowersOfTenMaxExp10 < q {
+               // This never happens due to the range of float32/float64 exponent
+               panic("mult128bitPow10: power of 10 is out of range")
+       }
+       pow := detailedPowersOfTen[q-detailedPowersOfTenMinExp10]
+       if q < 0 {
+               // Inverse powers of ten must be rounded up.
+               pow[0] += 1
+       }
+       e2 += mulByLog10Log2(q) - 127 + 119
+
+       // long multiplication
+       l1, l0 := bits.Mul64(m, pow[0])
+       h1, h0 := bits.Mul64(m, pow[1])
+       mid, carry := bits.Add64(l1, h0, 0)
+       h1 += carry
+       return h1<<9 | mid>>55, e2, mid<<9 == 0 && l0 == 0
+}
+
+func divisibleByPower5(m uint64, k int) bool {
+       if m == 0 {
+               return true
+       }
+       for i := 0; i < k; i++ {
+               if m%5 != 0 {
+                       return false
+               }
+               m /= 5
+       }
+       return true
+}
+
+// divmod1e9 computes quotient and remainder of division by 1e9,
+// avoiding runtime uint64 division on 32-bit platforms.
+func divmod1e9(x uint64) (uint32, uint32) {
+       if !host32bit {
+               return uint32(x / 1e9), uint32(x % 1e9)
+       }
+       // Use the same sequence of operations as the amd64 compiler.
+       hi, _ := bits.Mul64(x>>1, 0x89705f4136b4a598) // binary digits of 1e-9
+       q := hi >> 28
+       return uint32(q), uint32(x - q*1e9)
+}
diff --git a/libgo/go/strconv/ftoaryu_test.go b/libgo/go/strconv/ftoaryu_test.go
new file mode 100644 (file)
index 0000000..9758619
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package strconv_test
+
+import (
+       "math"
+       . "strconv"
+       "testing"
+)
+
+func TestMulByLog2Log10(t *testing.T) {
+       for x := -1600; x <= +1600; x++ {
+               iMath := MulByLog2Log10(x)
+               fMath := int(math.Floor(float64(x) * math.Ln2 / math.Ln10))
+               if iMath != fMath {
+                       t.Errorf("mulByLog2Log10(%d) failed: %d vs %d\n", x, iMath, fMath)
+               }
+       }
+}
+
+func TestMulByLog10Log2(t *testing.T) {
+       for x := -500; x <= +500; x++ {
+               iMath := MulByLog10Log2(x)
+               fMath := int(math.Floor(float64(x) * math.Ln10 / math.Ln2))
+               if iMath != fMath {
+                       t.Errorf("mulByLog10Log2(%d) failed: %d vs %d\n", x, iMath, fMath)
+               }
+       }
+}
index bb4a418b30f961e0c178c6045c95923a007816de..f2cceff20eb261e1b0fe4a8c7af83b9319dad89c 100644 (file)
@@ -21,3 +21,11 @@ func SetOptimize(b bool) bool {
 func ParseFloatPrefix(s string, bitSize int) (float64, int, error) {
        return parseFloatPrefix(s, bitSize)
 }
+
+func MulByLog2Log10(x int) int {
+       return mulByLog2Log10(x)
+}
+
+func MulByLog10Log2(x int) int {
+       return mulByLog10Log2(x)
+}
index 0e6e90a6c66e0b80dc9ad09050fe1aaea50aa0e8..909f9e47878b58f17362aea6f6646758e9f974fe 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 //
@@ -36,7 +37,7 @@ var (
 func bsearch16(a []uint16, x uint16) int {
        i, j := 0, len(a)
        for i < j {
-               h := i + (j-i)/2
+               h := i + (j-i)>>1
                if a[h] < x {
                        i = h + 1
                } else {
@@ -51,7 +52,7 @@ func bsearch16(a []uint16, x uint16) int {
 func bsearch32(a []uint32, x uint32) int {
        i, j := 0, len(a)
        for i < j {
-               h := i + (j-i)/2
+               h := i + (j-i)>>1
                if a[h] < x {
                        i = h + 1
                } else {
index bcbdbc514d21a8b72f8f83fecd5cc8cb5b9d4c49..b3bbb1612b9f634e930fc169bc329e87d1c8858d 100644 (file)
@@ -7,7 +7,6 @@
 package strconv
 
 import (
-       "internal/bytealg"
        "unicode/utf8"
 )
 
@@ -16,6 +15,11 @@ const (
        upperhex = "0123456789ABCDEF"
 )
 
+// contains reports whether the string contains the byte c.
+func contains(s string, c byte) bool {
+       return index(s, c) != -1
+}
+
 func quoteWith(s string, quote byte, ASCIIonly, graphicOnly bool) string {
        return string(appendQuotedWith(make([]byte, 0, 3*len(s)/2), s, quote, ASCIIonly, graphicOnly))
 }
@@ -360,85 +364,132 @@ func UnquoteChar(s string, quote byte) (value rune, multibyte bool, tail string,
        return
 }
 
+// QuotedPrefix returns the quoted string (as understood by Unquote) at the prefix of s.
+// If s does not start with a valid quoted string, QuotedPrefix returns an error.
+func QuotedPrefix(s string) (string, error) {
+       out, _, err := unquote(s, false)
+       return out, err
+}
+
 // Unquote interprets s as a single-quoted, double-quoted,
 // or backquoted Go string literal, returning the string value
 // that s quotes.  (If s is single-quoted, it would be a Go
 // character literal; Unquote returns the corresponding
 // one-character string.)
 func Unquote(s string) (string, error) {
-       n := len(s)
-       if n < 2 {
+       out, rem, err := unquote(s, true)
+       if len(rem) > 0 {
                return "", ErrSyntax
        }
-       quote := s[0]
-       if quote != s[n-1] {
-               return "", ErrSyntax
+       return out, err
+}
+
+// unquote parses a quoted string at the start of the input,
+// returning the parsed prefix, the remaining suffix, and any parse errors.
+// If unescape is true, the parsed prefix is unescaped,
+// otherwise the input prefix is provided verbatim.
+func unquote(in string, unescape bool) (out, rem string, err error) {
+       // Determine the quote form and optimistically find the terminating quote.
+       if len(in) < 2 {
+               return "", in, ErrSyntax
        }
-       s = s[1 : n-1]
+       quote := in[0]
+       end := index(in[1:], quote)
+       if end < 0 {
+               return "", in, ErrSyntax
+       }
+       end += 2 // position after terminating quote; may be wrong if escape sequences are present
 
-       if quote == '`' {
-               if contains(s, '`') {
-                       return "", ErrSyntax
+       switch quote {
+       case '`':
+               switch {
+               case !unescape:
+                       out = in[:end] // include quotes
+               case !contains(in[:end], '\r'):
+                       out = in[len("`") : end-len("`")] // exclude quotes
+               default:
+                       // Carriage return characters ('\r') inside raw string literals
+                       // are discarded from the raw string value.
+                       buf := make([]byte, 0, end-len("`")-len("\r")-len("`"))
+                       for i := len("`"); i < end-len("`"); i++ {
+                               if in[i] != '\r' {
+                                       buf = append(buf, in[i])
+                               }
+                       }
+                       out = string(buf)
                }
-               if contains(s, '\r') {
-                       // -1 because we know there is at least one \r to remove.
-                       buf := make([]byte, 0, len(s)-1)
-                       for i := 0; i < len(s); i++ {
-                               if s[i] != '\r' {
-                                       buf = append(buf, s[i])
+               // NOTE: Prior implementations did not verify that raw strings consist
+               // of valid UTF-8 characters and we continue to not verify it as such.
+               // The Go specification does not explicitly require valid UTF-8,
+               // but only mention that it is implicitly valid for Go source code
+               // (which must be valid UTF-8).
+               return out, in[end:], nil
+       case '"', '\'':
+               // Handle quoted strings without any escape sequences.
+               if !contains(in[:end], '\\') && !contains(in[:end], '\n') {
+                       var valid bool
+                       switch quote {
+                       case '"':
+                               valid = utf8.ValidString(in[len(`"`) : end-len(`"`)])
+                       case '\'':
+                               r, n := utf8.DecodeRuneInString(in[len("'") : end-len("'")])
+                               valid = len("'")+n+len("'") == end && (r != utf8.RuneError || n != 1)
+                       }
+                       if valid {
+                               out = in[:end]
+                               if unescape {
+                                       out = out[1 : end-1] // exclude quotes
                                }
+                               return out, in[end:], nil
                        }
-                       return string(buf), nil
                }
-               return s, nil
-       }
-       if quote != '"' && quote != '\'' {
-               return "", ErrSyntax
-       }
-       if contains(s, '\n') {
-               return "", ErrSyntax
-       }
 
-       // Is it trivial? Avoid allocation.
-       if !contains(s, '\\') && !contains(s, quote) {
-               switch quote {
-               case '"':
-                       if utf8.ValidString(s) {
-                               return s, nil
+               // Handle quoted strings with escape sequences.
+               var buf []byte
+               in0 := in
+               in = in[1:] // skip starting quote
+               if unescape {
+                       buf = make([]byte, 0, 3*end/2) // try to avoid more allocations
+               }
+               for len(in) > 0 && in[0] != quote {
+                       // Process the next character,
+                       // rejecting any unescaped newline characters which are invalid.
+                       r, multibyte, rem, err := UnquoteChar(in, quote)
+                       if in[0] == '\n' || err != nil {
+                               return "", in0, ErrSyntax
                        }
-               case '\'':
-                       r, size := utf8.DecodeRuneInString(s)
-                       if size == len(s) && (r != utf8.RuneError || size != 1) {
-                               return s, nil
+                       in = rem
+
+                       // Append the character if unescaping the input.
+                       if unescape {
+                               if r < utf8.RuneSelf || !multibyte {
+                                       buf = append(buf, byte(r))
+                               } else {
+                                       var arr [utf8.UTFMax]byte
+                                       n := utf8.EncodeRune(arr[:], r)
+                                       buf = append(buf, arr[:n]...)
+                               }
                        }
-               }
-       }
 
-       var runeTmp [utf8.UTFMax]byte
-       buf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations.
-       for len(s) > 0 {
-               c, multibyte, ss, err := UnquoteChar(s, quote)
-               if err != nil {
-                       return "", err
+                       // Single quoted strings must be a single character.
+                       if quote == '\'' {
+                               break
+                       }
                }
-               s = ss
-               if c < utf8.RuneSelf || !multibyte {
-                       buf = append(buf, byte(c))
-               } else {
-                       n := utf8.EncodeRune(runeTmp[:], c)
-                       buf = append(buf, runeTmp[:n]...)
+
+               // Verify that the string ends with a terminating quote.
+               if !(len(in) > 0 && in[0] == quote) {
+                       return "", in0, ErrSyntax
                }
-               if quote == '\'' && len(s) != 0 {
-                       // single-quoted must be single character
-                       return "", ErrSyntax
+               in = in[1:] // skip terminating quote
+
+               if unescape {
+                       return string(buf), in, nil
                }
+               return in0[:len(in0)-len(in)], in, nil
+       default:
+               return "", in, ErrSyntax
        }
-       return string(buf), nil
-}
-
-// contains reports whether the string contains the byte c.
-func contains(s string, c byte) bool {
-       return bytealg.IndexByteString(s, c) != -1
 }
 
 // bsearch16 returns the smallest i such that a[i] >= x.
@@ -446,7 +497,7 @@ func contains(s string, c byte) bool {
 func bsearch16(a []uint16, x uint16) int {
        i, j := 0, len(a)
        for i < j {
-               h := i + (j-i)/2
+               h := i + (j-i)>>1
                if a[h] < x {
                        i = h + 1
                } else {
@@ -461,7 +512,7 @@ func bsearch16(a []uint16, x uint16) int {
 func bsearch32(a []uint32, x uint32) int {
        i, j := 0, len(a)
        for i < j {
-               h := i + (j-i)/2
+               h := i + (j-i)>>1
                if a[h] < x {
                        i = h + 1
                } else {
index f1faf137bdae4b2ded73983370a3e253f8342d02..4750be27408a65dfd4c2f51864abda3862d60250 100644 (file)
@@ -6,6 +6,7 @@ package strconv_test
 
 import (
        . "strconv"
+       "strings"
        "testing"
        "unicode"
 )
@@ -297,6 +298,7 @@ var misquoted = []string{
        `"\z"`,
        "`",
        "`xxx",
+       "``x\r",
        "`\"",
        `"\'"`,
        `'\"'`,
@@ -307,22 +309,13 @@ var misquoted = []string{
 
 func TestUnquote(t *testing.T) {
        for _, tt := range unquotetests {
-               if out, err := Unquote(tt.in); err != nil || out != tt.out {
-                       t.Errorf("Unquote(%#q) = %q, %v want %q, nil", tt.in, out, err, tt.out)
-               }
+               testUnquote(t, tt.in, tt.out, nil)
        }
-
-       // run the quote tests too, backward
        for _, tt := range quotetests {
-               if in, err := Unquote(tt.out); in != tt.in {
-                       t.Errorf("Unquote(%#q) = %q, %v, want %q, nil", tt.out, in, err, tt.in)
-               }
+               testUnquote(t, tt.out, tt.in, nil)
        }
-
        for _, s := range misquoted {
-               if out, err := Unquote(s); out != "" || err != ErrSyntax {
-                       t.Errorf("Unquote(%#q) = %q, %v want %q, %v", s, out, err, "", ErrSyntax)
-               }
+               testUnquote(t, s, "", ErrSyntax)
        }
 }
 
@@ -333,26 +326,44 @@ func TestUnquoteInvalidUTF8(t *testing.T) {
 
                // one of:
                want    string
-               wantErr string
+               wantErr error
        }{
                {in: `"foo"`, want: "foo"},
-               {in: `"foo`, wantErr: "invalid syntax"},
+               {in: `"foo`, wantErr: ErrSyntax},
                {in: `"` + "\xc0" + `"`, want: "\xef\xbf\xbd"},
                {in: `"a` + "\xc0" + `"`, want: "a\xef\xbf\xbd"},
                {in: `"\t` + "\xc0" + `"`, want: "\t\xef\xbf\xbd"},
        }
-       for i, tt := range tests {
-               got, err := Unquote(tt.in)
-               var gotErr string
-               if err != nil {
-                       gotErr = err.Error()
-               }
-               if gotErr != tt.wantErr {
-                       t.Errorf("%d. Unquote(%q) = err %v; want %q", i, tt.in, err, tt.wantErr)
-               }
-               if tt.wantErr == "" && err == nil && got != tt.want {
-                       t.Errorf("%d. Unquote(%q) = %02x; want %02x", i, tt.in, []byte(got), []byte(tt.want))
-               }
+       for _, tt := range tests {
+               testUnquote(t, tt.in, tt.want, tt.wantErr)
+       }
+}
+
+func testUnquote(t *testing.T, in, want string, wantErr error) {
+       // Test Unquote.
+       got, gotErr := Unquote(in)
+       if got != want || gotErr != wantErr {
+               t.Errorf("Unquote(%q) = (%q, %v), want (%q, %v)", in, got, gotErr, want, wantErr)
+       }
+
+       // Test QuotedPrefix.
+       // Adding an arbitrary suffix should not change the result of QuotedPrefix
+       // assume that the suffix doesn't accidentally terminate a truncated input.
+       if gotErr == nil {
+               want = in
+       }
+       suffix := "\n\r\\\"`'" // special characters for quoted strings
+       if len(in) > 0 {
+               suffix = strings.ReplaceAll(suffix, in[:1], "")
+       }
+       in += suffix
+       got, gotErr = QuotedPrefix(in)
+       if gotErr == nil && wantErr != nil {
+               _, wantErr = Unquote(got) // original input had trailing junk, reparse with only valid prefix
+               want = got
+       }
+       if got != want || gotErr != wantErr {
+               t.Errorf("QuotedPrefix(%q) = (%q, %v), want (%q, %v)", in, got, gotErr, want, wantErr)
        }
 }
 
index 6ff151d74b2e87e1be45ad178b00383f4e9891bc..547e52e84dde0340e173f9e34b0c54f545c15d48 100644 (file)
@@ -103,7 +103,8 @@ func (b *Builder) WriteByte(c byte) error {
 // It returns the length of r and a nil error.
 func (b *Builder) WriteRune(r rune) (int, error) {
        b.copyCheck()
-       if r < utf8.RuneSelf {
+       // Compare as uint32 to correctly handle negative runes.
+       if uint32(r) < utf8.RuneSelf {
                b.buf = append(b.buf, byte(r))
                return 1, nil
        }
index fbf6617e1e37eb9912c3c9f984e46afe7117ece4..61c0cf40d51d484de8044f4664e39291f09e3824 100644 (file)
@@ -9,6 +9,7 @@ import (
        "runtime"
        . "strings"
        "testing"
+       "unicode/utf8"
 )
 
 func check(t *testing.T, b *Builder, want string) {
@@ -308,6 +309,16 @@ func TestBuilderCopyPanic(t *testing.T) {
        }
 }
 
+func TestBuilderWriteInvalidRune(t *testing.T) {
+       // Invalid runes, including negative ones, should be written as
+       // utf8.RuneError.
+       for _, r := range []rune{-1, utf8.MaxRune + 1} {
+               var b Builder
+               b.WriteRune(r)
+               check(t, &b, "\uFFFD")
+       }
+}
+
 var someBytes = []byte("some bytes sdljlk jsklj3lkjlk djlkjw")
 
 var sinkS string
index eab7e70c9b0f3ed5155cbf3c6a9e73cb4154c2c8..61f81d8fd377b06e49e49b70bf88918589766998 100644 (file)
@@ -25,7 +25,7 @@ type ifaceWords struct {
 
 // Load returns the value set by the most recent Store.
 // It returns nil if there has been no call to Store for this Value.
-func (v *Value) Load() (x interface{}) {
+func (v *Value) Load() (val interface{}) {
        vp := (*ifaceWords)(unsafe.Pointer(v))
        typ := LoadPointer(&vp.typ)
        if typ == nil || uintptr(typ) == ^uintptr(0) {
@@ -33,21 +33,21 @@ func (v *Value) Load() (x interface{}) {
                return nil
        }
        data := LoadPointer(&vp.data)
-       xp := (*ifaceWords)(unsafe.Pointer(&x))
-       xp.typ = typ
-       xp.data = data
+       vlp := (*ifaceWords)(unsafe.Pointer(&val))
+       vlp.typ = typ
+       vlp.data = data
        return
 }
 
 // Store sets the value of the Value to x.
 // All calls to Store for a given Value must use values of the same concrete type.
 // Store of an inconsistent type panics, as does Store(nil).
-func (v *Value) Store(x interface{}) {
-       if x == nil {
+func (v *Value) Store(val interface{}) {
+       if val == nil {
                panic("sync/atomic: store of nil value into Value")
        }
        vp := (*ifaceWords)(unsafe.Pointer(v))
-       xp := (*ifaceWords)(unsafe.Pointer(&x))
+       vlp := (*ifaceWords)(unsafe.Pointer(&val))
        for {
                typ := LoadPointer(&vp.typ)
                if typ == nil {
@@ -61,8 +61,8 @@ func (v *Value) Store(x interface{}) {
                                continue
                        }
                        // Complete first store.
-                       StorePointer(&vp.data, xp.data)
-                       StorePointer(&vp.typ, xp.typ)
+                       StorePointer(&vp.data, vlp.data)
+                       StorePointer(&vp.typ, vlp.typ)
                        runtime_procUnpin()
                        return
                }
@@ -73,14 +73,121 @@ func (v *Value) Store(x interface{}) {
                        continue
                }
                // First store completed. Check type and overwrite data.
-               if typ != xp.typ {
+               if typ != vlp.typ {
                        panic("sync/atomic: store of inconsistently typed value into Value")
                }
-               StorePointer(&vp.data, xp.data)
+               StorePointer(&vp.data, vlp.data)
                return
        }
 }
 
+// Swap stores new into Value and returns the previous value. It returns nil if
+// the Value is empty.
+//
+// All calls to Swap for a given Value must use values of the same concrete
+// type. Swap of an inconsistent type panics, as does Swap(nil).
+func (v *Value) Swap(new interface{}) (old interface{}) {
+       if new == nil {
+               panic("sync/atomic: swap of nil value into Value")
+       }
+       vp := (*ifaceWords)(unsafe.Pointer(v))
+       np := (*ifaceWords)(unsafe.Pointer(&new))
+       for {
+               typ := LoadPointer(&vp.typ)
+               if typ == nil {
+                       // Attempt to start first store.
+                       // Disable preemption so that other goroutines can use
+                       // active spin wait to wait for completion; and so that
+                       // GC does not see the fake type accidentally.
+                       runtime_procPin()
+                       if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(^uintptr(0))) {
+                               runtime_procUnpin()
+                               continue
+                       }
+                       // Complete first store.
+                       StorePointer(&vp.data, np.data)
+                       StorePointer(&vp.typ, np.typ)
+                       runtime_procUnpin()
+                       return nil
+               }
+               if uintptr(typ) == ^uintptr(0) {
+                       // First store in progress. Wait.
+                       // Since we disable preemption around the first store,
+                       // we can wait with active spinning.
+                       continue
+               }
+               // First store completed. Check type and overwrite data.
+               if typ != np.typ {
+                       panic("sync/atomic: swap of inconsistently typed value into Value")
+               }
+               op := (*ifaceWords)(unsafe.Pointer(&old))
+               op.typ, op.data = np.typ, SwapPointer(&vp.data, np.data)
+               return old
+       }
+}
+
+// CompareAndSwapPointer executes the compare-and-swap operation for the Value.
+//
+// All calls to CompareAndSwap for a given Value must use values of the same
+// concrete type. CompareAndSwap of an inconsistent type panics, as does
+// CompareAndSwap(old, nil).
+func (v *Value) CompareAndSwap(old, new interface{}) (swapped bool) {
+       if new == nil {
+               panic("sync/atomic: compare and swap of nil value into Value")
+       }
+       vp := (*ifaceWords)(unsafe.Pointer(v))
+       np := (*ifaceWords)(unsafe.Pointer(&new))
+       op := (*ifaceWords)(unsafe.Pointer(&old))
+       if op.typ != nil && np.typ != op.typ {
+               panic("sync/atomic: compare and swap of inconsistently typed values")
+       }
+       for {
+               typ := LoadPointer(&vp.typ)
+               if typ == nil {
+                       if old != nil {
+                               return false
+                       }
+                       // Attempt to start first store.
+                       // Disable preemption so that other goroutines can use
+                       // active spin wait to wait for completion; and so that
+                       // GC does not see the fake type accidentally.
+                       runtime_procPin()
+                       if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(^uintptr(0))) {
+                               runtime_procUnpin()
+                               continue
+                       }
+                       // Complete first store.
+                       StorePointer(&vp.data, np.data)
+                       StorePointer(&vp.typ, np.typ)
+                       runtime_procUnpin()
+                       return true
+               }
+               if uintptr(typ) == ^uintptr(0) {
+                       // First store in progress. Wait.
+                       // Since we disable preemption around the first store,
+                       // we can wait with active spinning.
+                       continue
+               }
+               // First store completed. Check type and overwrite data.
+               if typ != np.typ {
+                       panic("sync/atomic: compare and swap of inconsistently typed value into Value")
+               }
+               // Compare old and current via runtime equality check.
+               // This allows value types to be compared, something
+               // not offered by the package functions.
+               // CompareAndSwapPointer below only ensures vp.data
+               // has not changed since LoadPointer.
+               data := LoadPointer(&vp.data)
+               var i interface{}
+               (*ifaceWords)(unsafe.Pointer(&i)).typ = typ
+               (*ifaceWords)(unsafe.Pointer(&i)).data = data
+               if i != old {
+                       return false
+               }
+               return CompareAndSwapPointer(&vp.data, data, np.data)
+       }
+}
+
 // Disable/enable preemption, implemented in runtime.
 func runtime_procPin()
 func runtime_procUnpin()
index f289766340416a388dab8a5d8ee0277258988197..a5e717d6e0ccd1e3e5ff0c2165e54716df6a1c0d 100644 (file)
@@ -7,6 +7,9 @@ package atomic_test
 import (
        "math/rand"
        "runtime"
+       "strconv"
+       "sync"
+       "sync/atomic"
        . "sync/atomic"
        "testing"
 )
@@ -133,3 +136,139 @@ func BenchmarkValueRead(b *testing.B) {
                }
        })
 }
+
+var Value_SwapTests = []struct {
+       init interface{}
+       new  interface{}
+       want interface{}
+       err  interface{}
+}{
+       {init: nil, new: nil, err: "sync/atomic: swap of nil value into Value"},
+       {init: nil, new: true, want: nil, err: nil},
+       {init: true, new: "", err: "sync/atomic: swap of inconsistently typed value into Value"},
+       {init: true, new: false, want: true, err: nil},
+}
+
+func TestValue_Swap(t *testing.T) {
+       for i, tt := range Value_SwapTests {
+               t.Run(strconv.Itoa(i), func(t *testing.T) {
+                       var v Value
+                       if tt.init != nil {
+                               v.Store(tt.init)
+                       }
+                       defer func() {
+                               err := recover()
+                               switch {
+                               case tt.err == nil && err != nil:
+                                       t.Errorf("should not panic, got %v", err)
+                               case tt.err != nil && err == nil:
+                                       t.Errorf("should panic %v, got <nil>", tt.err)
+                               }
+                       }()
+                       if got := v.Swap(tt.new); got != tt.want {
+                               t.Errorf("got %v, want %v", got, tt.want)
+                       }
+                       if got := v.Load(); got != tt.new {
+                               t.Errorf("got %v, want %v", got, tt.new)
+                       }
+               })
+       }
+}
+
+func TestValueSwapConcurrent(t *testing.T) {
+       var v Value
+       var count uint64
+       var g sync.WaitGroup
+       var m, n uint64 = 10000, 10000
+       if testing.Short() {
+               m = 1000
+               n = 1000
+       }
+       for i := uint64(0); i < m*n; i += n {
+               i := i
+               g.Add(1)
+               go func() {
+                       var c uint64
+                       for new := i; new < i+n; new++ {
+                               if old := v.Swap(new); old != nil {
+                                       c += old.(uint64)
+                               }
+                       }
+                       atomic.AddUint64(&count, c)
+                       g.Done()
+               }()
+       }
+       g.Wait()
+       if want, got := (m*n-1)*(m*n)/2, count+v.Load().(uint64); got != want {
+               t.Errorf("sum from 0 to %d was %d, want %v", m*n-1, got, want)
+       }
+}
+
+var heapA, heapB = struct{ uint }{0}, struct{ uint }{0}
+
+var Value_CompareAndSwapTests = []struct {
+       init interface{}
+       new  interface{}
+       old  interface{}
+       want bool
+       err  interface{}
+}{
+       {init: nil, new: nil, old: nil, err: "sync/atomic: compare and swap of nil value into Value"},
+       {init: nil, new: true, old: "", err: "sync/atomic: compare and swap of inconsistently typed values into Value"},
+       {init: nil, new: true, old: true, want: false, err: nil},
+       {init: nil, new: true, old: nil, want: true, err: nil},
+       {init: true, new: "", err: "sync/atomic: compare and swap of inconsistently typed value into Value"},
+       {init: true, new: true, old: false, want: false, err: nil},
+       {init: true, new: true, old: true, want: true, err: nil},
+       {init: heapA, new: struct{ uint }{1}, old: heapB, want: true, err: nil},
+}
+
+func TestValue_CompareAndSwap(t *testing.T) {
+       for i, tt := range Value_CompareAndSwapTests {
+               t.Run(strconv.Itoa(i), func(t *testing.T) {
+                       var v Value
+                       if tt.init != nil {
+                               v.Store(tt.init)
+                       }
+                       defer func() {
+                               err := recover()
+                               switch {
+                               case tt.err == nil && err != nil:
+                                       t.Errorf("got %v, wanted no panic", err)
+                               case tt.err != nil && err == nil:
+                                       t.Errorf("did not panic, want %v", tt.err)
+                               }
+                       }()
+                       if got := v.CompareAndSwap(tt.old, tt.new); got != tt.want {
+                               t.Errorf("got %v, want %v", got, tt.want)
+                       }
+               })
+       }
+}
+
+func TestValueCompareAndSwapConcurrent(t *testing.T) {
+       var v Value
+       var w sync.WaitGroup
+       v.Store(0)
+       m, n := 1000, 100
+       if testing.Short() {
+               m = 100
+               n = 100
+       }
+       for i := 0; i < m; i++ {
+               i := i
+               w.Add(1)
+               go func() {
+                       for j := i; j < m*n; runtime.Gosched() {
+                               if v.CompareAndSwap(j, j+1) {
+                                       j += m
+                               }
+                       }
+                       w.Done()
+               }()
+       }
+       w.Wait()
+       if stop := v.Load().(int); stop != m*n {
+               t.Errorf("did not get to %v, stopped at %v", m*n, stop)
+       }
+}
index 9ad25353ff48cef7c541de24e3382c346dc44f61..dfb62dd3e801cc8717ab7791b0a0e31f4ec43a1c 100644 (file)
@@ -73,7 +73,8 @@ var expunged = unsafe.Pointer(new(interface{}))
 type entry struct {
        // p points to the interface{} value stored for the entry.
        //
-       // If p == nil, the entry has been deleted and m.dirty == nil.
+       // If p == nil, the entry has been deleted, and either m.dirty == nil or
+       // m.dirty[key] is e.
        //
        // If p == expunged, the entry has been deleted, m.dirty != nil, and the entry
        // is missing from m.dirty.
index c67bd8c4e8c314733507ffcfe598983abeff9aed..937164428431daec2b3aab80928a0e253c11c40c 100644 (file)
@@ -3,6 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // Pool is no-op under race detector, so all these tests do not work.
+//go:build !race
 // +build !race
 
 package sync_test
index f10c4e8e0ef3e7e9ee4aefa27825f6a0b7e47296..c4b44893f0e7659f197834b804fd967c6f888560 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !goexperiment.staticlockranking
 // +build !goexperiment.staticlockranking
 
 package sync
index aaa1c276261e29a7e34cc014467301cc9d2d226a..e91fdb6c1ff46d95036740f6a7dea6cfaa2eec48 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build goexperiment.staticlockranking
 // +build goexperiment.staticlockranking
 
 package sync
index f67ee6064bf73edf075ff1d32d066c58a5af20a9..452d4cf14b6b13b52c55ef235d6ea1b2b0b60f9f 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build dragonfly || freebsd || netbsd || openbsd
 // +build dragonfly freebsd netbsd openbsd
 
 // Berkeley packet filter for BSD variants
index 524689ae2d233902018914c4bbb510ba08aa0105..c1a8b516e81a408c6313afa7c7d47caf835a789c 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build linux
 // +build linux
 
 package syscall_test
@@ -37,16 +38,19 @@ func TestSCMCredentials(t *testing.T) {
                if err != nil {
                        t.Fatalf("Socketpair: %v", err)
                }
-               defer syscall.Close(fds[0])
-               defer syscall.Close(fds[1])
 
                err = syscall.SetsockoptInt(fds[0], syscall.SOL_SOCKET, syscall.SO_PASSCRED, 1)
                if err != nil {
+                       syscall.Close(fds[0])
+                       syscall.Close(fds[1])
                        t.Fatalf("SetsockoptInt: %v", err)
                }
 
                srvFile := os.NewFile(uintptr(fds[0]), "server")
+               cliFile := os.NewFile(uintptr(fds[1]), "client")
                defer srvFile.Close()
+               defer cliFile.Close()
+
                srv, err := net.FileConn(srvFile)
                if err != nil {
                        t.Errorf("FileConn: %v", err)
@@ -54,8 +58,6 @@ func TestSCMCredentials(t *testing.T) {
                }
                defer srv.Close()
 
-               cliFile := os.NewFile(uintptr(fds[1]), "client")
-               defer cliFile.Close()
                cli, err := net.FileConn(cliFile)
                if err != nil {
                        t.Errorf("FileConn: %v", err)
@@ -103,8 +105,8 @@ func TestSCMCredentials(t *testing.T) {
                if err != nil {
                        t.Fatalf("ReadMsgUnix: %v", err)
                }
-               if flags != 0 {
-                       t.Fatalf("ReadMsgUnix flags = 0x%x, want 0", flags)
+               if flags != syscall.MSG_CMSG_CLOEXEC {
+                       t.Fatalf("ReadMsgUnix flags = %#x, want %#x (MSG_CMSG_CLOEXEC)", flags, syscall.MSG_CMSG_CLOEXEC)
                }
                if n != tt.dataLen {
                        t.Fatalf("ReadMsgUnix n = %d, want %d", n, tt.dataLen)
index 57264493163b7b15da86a8495591ac5b58d2671d..1e959463cbc76ff785422c88e8cda9508cffeac8 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris
 
 package syscall
index 7dac98ff4b960ed572e77e1ccb31a41b83494a50..71b445ba9b533b49022a80cea9b88aba4298d750 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
 
 package syscall_test
@@ -26,16 +27,12 @@ func TestDirent(t *testing.T) {
                filenameMinSize = 11
        )
 
-       d, err := os.MkdirTemp("", "dirent-test")
-       if err != nil {
-               t.Fatalf("tempdir: %v", err)
-       }
-       defer os.RemoveAll(d)
+       d := t.TempDir()
        t.Logf("tmpdir: %s", d)
 
        for i, c := range []byte("0123456789") {
                name := string(bytes.Repeat([]byte{c}, filenameMinSize+i))
-               err = os.WriteFile(filepath.Join(d, name), nil, 0644)
+               err := os.WriteFile(filepath.Join(d, name), nil, 0644)
                if err != nil {
                        t.Fatalf("writefile: %v", err)
                }
@@ -92,18 +89,14 @@ func TestDirentRepeat(t *testing.T) {
        }
 
        // Make a directory containing N files
-       d, err := os.MkdirTemp("", "direntRepeat-test")
-       if err != nil {
-               t.Fatalf("tempdir: %v", err)
-       }
-       defer os.RemoveAll(d)
+       d := t.TempDir()
 
        var files []string
        for i := 0; i < N; i++ {
                files = append(files, fmt.Sprintf("file%d", i))
        }
        for _, file := range files {
-               err = os.WriteFile(filepath.Join(d, file), []byte("contents"), 0644)
+               err := os.WriteFile(filepath.Join(d, file), []byte("contents"), 0644)
                if err != nil {
                        t.Fatalf("writefile: %v", err)
                }
index 24a4d1df2409adde7dd9af9388c979635c35179d..a38e9c6496ddefaf3679b22b2673a88220aa33d7 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 //
+//go:build ppc64 || s390x || mips || mips64 || armbe || arm64be || m68k || ppc || mips64p32 || s390 || shbe || sparc || sparc64
 // +build ppc64 s390x mips mips64 armbe arm64be m68k ppc mips64p32 s390 shbe sparc sparc64
 
 package syscall
index 22cac17ef117cfe1481c4c881775f4c024b24391..2332fa39b585902424fe1515748b7db1f49c2eae 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 //
-// +build 386 alpha amd64 amd64p32 arm arm64 ia64 mips64le mipsle mips64p32le nios2 ppc64le riscv riscv64 sh wasm
+//go:build 386 || alpha || amd64 || amd64p32 || arm || arm64 || ia64 || ppc64le || mips64le || mipsle || mips64p32le || nios2 || riscv || riscv64 || sh || wasm
+// +build 386 alpha amd64 amd64p32 arm arm64 ia64 ppc64le mips64le mipsle mips64p32le nios2 riscv riscv64 sh wasm
 
 package syscall
 
index c56b6b8a1c599601d61a1d80a6c5fa2dbefc8f13..0d95c55cbae0e2a4fb7c61a49a8944b29abacd03 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || plan9
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris plan9
 
 // Unix environment variables.
index ca7fdc0825e7a66e0bf222d96b61ce2ec9056f18..a081c096fead9d3dcb7be2798d747c84f044f357 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build aix darwin dragonfly freebsd hurd netbsd openbsd solaris
+//go:build dragonfly || freebsd || hurd || netbsd || (openbsd && mips64)
+// +build dragonfly freebsd hurd netbsd openbsd,mips64
 
 package syscall
 
@@ -89,8 +90,6 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
 
        // Fork succeeded, now in child.
 
-       runtime_AfterForkInChild()
-
        // Enable tracing if requested.
        if sys.Ptrace {
                err1 = raw_ptrace(_PTRACE_TRACEME, 0, 0, 0)
@@ -129,6 +128,10 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
                }
        }
 
+       // Restore the signal mask. We do this after TIOCSPGRP to avoid
+       // having the kernel send a SIGTTOU signal to the process group.
+       runtime_AfterForkInChild()
+
        // Chroot
        if chroot != nil {
                err1 = raw_chroot(chroot)
index 0da6c9649668819193798af3c692458f25858bbd..c9be86bc823607efab879bce54b48e61b9f2e8bd 100644 (file)
@@ -2,11 +2,13 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build linux
 // +build linux
 
 package syscall
 
 import (
+       "internal/itoa"
        "unsafe"
 )
 
@@ -244,8 +246,6 @@ func forkAndExecInChild1(argv0 *byte, argv, envv []*byte, chroot, dir *byte, att
 
        // Fork succeeded, now in child.
 
-       runtime_AfterForkInChild()
-
        // Enable the "keep capabilities" flag to set ambient capabilities later.
        if len(sys.AmbientCaps) > 0 {
                _, err1 = raw_prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)
@@ -303,6 +303,10 @@ func forkAndExecInChild1(argv0 *byte, argv, envv []*byte, chroot, dir *byte, att
                }
        }
 
+       // Restore the signal mask. We do this after TIOCSPGRP to avoid
+       // having the kernel send a SIGTTOU signal to the process group.
+       runtime_AfterForkInChild()
+
        // Unshare
        if sys.Unshareflags != 0 {
                err1 = rawUnshare(int(sys.Unshareflags))
@@ -575,7 +579,7 @@ func forkExecPipe(p []int) (err error) {
 func formatIDMappings(idMap []SysProcIDMap) []byte {
        var data []byte
        for _, im := range idMap {
-               data = append(data, []byte(itoa(im.ContainerID)+" "+itoa(im.HostID)+" "+itoa(im.Size)+"\n")...)
+               data = append(data, []byte(itoa.Itoa(im.ContainerID)+" "+itoa.Itoa(im.HostID)+" "+itoa.Itoa(im.Size)+"\n")...)
        }
        return data
 }
@@ -604,7 +608,7 @@ func writeIDMappings(path string, idMap []SysProcIDMap) error {
 // This is needed since kernel 3.19, because you can't write gid_map without
 // disabling setgroups() system call.
 func writeSetgroups(pid int, enable bool) error {
-       sgf := "/proc/" + itoa(pid) + "/setgroups"
+       sgf := "/proc/" + itoa.Itoa(pid) + "/setgroups"
        fd, err := Open(sgf, O_RDWR, 0)
        if err != nil {
                return err
@@ -629,7 +633,7 @@ func writeSetgroups(pid int, enable bool) error {
 // for a process and it is called from the parent process.
 func writeUidGidMappings(pid int, sys *SysProcAttr) error {
        if sys.UidMappings != nil {
-               uidf := "/proc/" + itoa(pid) + "/uid_map"
+               uidf := "/proc/" + itoa.Itoa(pid) + "/uid_map"
                if err := writeIDMappings(uidf, sys.UidMappings); err != nil {
                        return err
                }
@@ -640,7 +644,7 @@ func writeUidGidMappings(pid int, sys *SysProcAttr) error {
                if err := writeSetgroups(pid, sys.GidMappingsEnableSetgroups); err != nil && err != ENOENT {
                        return err
                }
-               gidf := "/proc/" + itoa(pid) + "/gid_map"
+               gidf := "/proc/" + itoa.Itoa(pid) + "/gid_map"
                if err := writeIDMappings(gidf, sys.GidMappings); err != nil {
                        return err
                }
index bbab36d210d8b9d59c56564e380e66bd298510a4..ec0a4c0bc8a0f53a17931ba26c07a4dd56d2acbf 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build linux
 // +build linux
 
 package syscall_test
@@ -317,6 +318,7 @@ func TestGroupCleanupUserNamespace(t *testing.T) {
                "uid=0(root) gid=0(root) groups=0(root),65534",
                "uid=0(root) gid=0(root) groups=0(root),65534(nobody),65534(nobody),65534(nobody),65534(nobody),65534(nobody),65534(nobody),65534(nobody),65534(nobody),65534(nobody),65534(nobody)", // Alpine; see https://golang.org/issue/19938
                "uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023",                                                                               // CentOS with SELinux context, see https://golang.org/issue/34547
+               "uid=0(root) gid=0(root) groups=0(root),65534(nobody) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023",                                                                 // Fedora with SElinux context, see https://golang.org/issue/46752
        }
        for _, e := range expected {
                if strOut == e {
index d89bf3867660fc0c8f8d71d0970f4013d03aab09..7e01648ee89d74027b58c2f825c8f3535fa4ba6a 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 // Fork, exec, wait, etc.
@@ -353,7 +354,7 @@ func Exec(argv0 string, argv []string, envv []string) (err error) {
        } else if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
                // Similarly on Darwin.
                err1 = execveDarwin(argv0p, &argvp[0], &envvp[0])
-       } else if runtime.GOOS == "openbsd" && runtime.GOARCH == "amd64" {
+       } else if runtime.GOOS == "openbsd" && (runtime.GOARCH == "386" || runtime.GOARCH == "amd64" || runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
                // Similarly on OpenBSD.
                err1 = execveOpenBSD(argv0p, &argvp[0], &envvp[0])
        } else {
index 13991491c2fa6edc5e705ec8c8fa46ac84cd2029..859572256929408f9118611c382a0b6e34d7506e 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package syscall_test
@@ -169,11 +170,13 @@ func TestForeground(t *testing.T) {
                t.Skip("skipping; TestForeground: fails on GNU/Hurd")
        }
        signal.Ignore(syscall.SIGTTIN, syscall.SIGTTOU)
+       defer signal.Reset()
 
        tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
        if err != nil {
                t.Skipf("Can't test Foreground. Couldn't open /dev/tty: %s", err)
        }
+       defer tty.Close()
 
        fpgrp := syscall.Pid_t(0)
 
@@ -212,12 +215,68 @@ func TestForeground(t *testing.T) {
 
        cmd.Stop()
 
-       errno = syscall.Ioctl(tty.Fd(), syscall.TIOCSPGRP, uintptr(unsafe.Pointer(&fpgrp)))
+       // This call fails on darwin/arm64. The failure doesn't matter, though.
+       // This is just best effort.
+       syscall.Ioctl(tty.Fd(), syscall.TIOCSPGRP, uintptr(unsafe.Pointer(&fpgrp)))
+}
+
+func TestForegroundSignal(t *testing.T) {
+       tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
+       if err != nil {
+               t.Skipf("couldn't open /dev/tty: %s", err)
+       }
+       defer tty.Close()
+
+       // This should really be pid_t, however _C_int (aka int32) is generally
+       // equivalent.
+       fpgrp := int32(0)
+
+       errno := syscall.Ioctl(tty.Fd(), syscall.TIOCGPGRP, uintptr(unsafe.Pointer(&fpgrp)))
        if errno != 0 {
-               t.Fatalf("TIOCSPGRP failed with error code: %s", errno)
+               t.Fatalf("TIOCGPGRP failed with error code: %s", errno)
        }
 
-       signal.Reset()
+       if fpgrp == 0 {
+               t.Fatalf("Foreground process group is zero")
+       }
+
+       defer func() {
+               signal.Ignore(syscall.SIGTTIN, syscall.SIGTTOU)
+               syscall.Ioctl(tty.Fd(), syscall.TIOCSPGRP, uintptr(unsafe.Pointer(&fpgrp)))
+               signal.Reset()
+       }()
+
+       ch1 := make(chan os.Signal, 1)
+       ch2 := make(chan bool)
+
+       signal.Notify(ch1, syscall.SIGTTIN, syscall.SIGTTOU)
+       defer signal.Stop(ch1)
+
+       cmd := create(t)
+
+       go func() {
+               cmd.proc.SysProcAttr = &syscall.SysProcAttr{
+                       Ctty:       int(tty.Fd()),
+                       Foreground: true,
+               }
+               cmd.Start()
+               cmd.Stop()
+               close(ch2)
+       }()
+
+       timer := time.NewTimer(30 * time.Second)
+       defer timer.Stop()
+       for {
+               select {
+               case sig := <-ch1:
+                       t.Errorf("unexpected signal %v", sig)
+               case <-ch2:
+                       // Success.
+                       return
+               case <-timer.C:
+                       t.Fatal("timed out waiting for child process")
+               }
+       }
 }
 
 // Test a couple of cases that SysProcAttr can't handle. Issue 29458.
index 46cbd7567dd5607f3fc853267de7cfcbd71747b0..18d15028c3d3bba9812e58ea0555f618f6e5a07c 100644 (file)
@@ -7,6 +7,7 @@
 package syscall
 
 import (
+       "runtime"
        "sync"
        "unicode/utf16"
        "unsafe"
@@ -235,13 +236,15 @@ type ProcAttr struct {
 }
 
 type SysProcAttr struct {
-       HideWindow        bool
-       CmdLine           string // used if non-empty, else the windows command line is built by escaping the arguments passed to StartProcess
-       CreationFlags     uint32
-       Token             Token               // if set, runs new process in the security context represented by the token
-       ProcessAttributes *SecurityAttributes // if set, applies these security attributes as the descriptor for the new process
-       ThreadAttributes  *SecurityAttributes // if set, applies these security attributes as the descriptor for the main thread of the new process
-       NoInheritHandles  bool                // if set, each inheritable handle in the calling process is not inherited by the new process
+       HideWindow                 bool
+       CmdLine                    string // used if non-empty, else the windows command line is built by escaping the arguments passed to StartProcess
+       CreationFlags              uint32
+       Token                      Token               // if set, runs new process in the security context represented by the token
+       ProcessAttributes          *SecurityAttributes // if set, applies these security attributes as the descriptor for the new process
+       ThreadAttributes           *SecurityAttributes // if set, applies these security attributes as the descriptor for the main thread of the new process
+       NoInheritHandles           bool                // if set, each inheritable handle in the calling process is not inherited by the new process
+       AdditionalInheritedHandles []Handle            // a list of additional handles, already marked as inheritable, that will be inherited by the new process
+       ParentProcess              Handle              // if non-zero, the new process regards the process given by this handle as its parent process, and AdditionalInheritedHandles, if set, should exist in this parent process
 }
 
 var zeroProcAttr ProcAttr
@@ -310,46 +313,104 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
                }
        }
 
-       // Acquire the fork lock so that no other threads
-       // create new fds that are not yet close-on-exec
-       // before we fork.
-       ForkLock.Lock()
-       defer ForkLock.Unlock()
+       var maj, min, build uint32
+       rtlGetNtVersionNumbers(&maj, &min, &build)
+       isWin7 := maj < 6 || (maj == 6 && min <= 1)
+       // NT kernel handles are divisible by 4, with the bottom 3 bits left as
+       // a tag. The fully set tag correlates with the types of handles we're
+       // concerned about here.  Except, the kernel will interpret some
+       // special handle values, like -1, -2, and so forth, so kernelbase.dll
+       // checks to see that those bottom three bits are checked, but that top
+       // bit is not checked.
+       isLegacyWin7ConsoleHandle := func(handle Handle) bool { return isWin7 && handle&0x10000003 == 3 }
 
        p, _ := GetCurrentProcess()
+       parentProcess := p
+       if sys.ParentProcess != 0 {
+               parentProcess = sys.ParentProcess
+       }
        fd := make([]Handle, len(attr.Files))
        for i := range attr.Files {
                if attr.Files[i] > 0 {
-                       err := DuplicateHandle(p, Handle(attr.Files[i]), p, &fd[i], 0, true, DUPLICATE_SAME_ACCESS)
+                       destinationProcessHandle := parentProcess
+
+                       // On Windows 7, console handles aren't real handles, and can only be duplicated
+                       // into the current process, not a parent one, which amounts to the same thing.
+                       if parentProcess != p && isLegacyWin7ConsoleHandle(Handle(attr.Files[i])) {
+                               destinationProcessHandle = p
+                       }
+
+                       err := DuplicateHandle(p, Handle(attr.Files[i]), destinationProcessHandle, &fd[i], 0, true, DUPLICATE_SAME_ACCESS)
                        if err != nil {
                                return 0, 0, err
                        }
-                       defer CloseHandle(Handle(fd[i]))
+                       defer DuplicateHandle(parentProcess, fd[i], 0, nil, 0, false, DUPLICATE_CLOSE_SOURCE)
                }
        }
-       si := new(StartupInfo)
+       si := new(_STARTUPINFOEXW)
+       si.ProcThreadAttributeList, err = newProcThreadAttributeList(2)
+       if err != nil {
+               return 0, 0, err
+       }
+       defer deleteProcThreadAttributeList(si.ProcThreadAttributeList)
        si.Cb = uint32(unsafe.Sizeof(*si))
        si.Flags = STARTF_USESTDHANDLES
        if sys.HideWindow {
                si.Flags |= STARTF_USESHOWWINDOW
                si.ShowWindow = SW_HIDE
        }
+       if sys.ParentProcess != 0 {
+               err = updateProcThreadAttribute(si.ProcThreadAttributeList, 0, _PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, unsafe.Pointer(&sys.ParentProcess), unsafe.Sizeof(sys.ParentProcess), nil, nil)
+               if err != nil {
+                       return 0, 0, err
+               }
+       }
        si.StdInput = fd[0]
        si.StdOutput = fd[1]
        si.StdErr = fd[2]
 
-       pi := new(ProcessInformation)
+       fd = append(fd, sys.AdditionalInheritedHandles...)
 
-       flags := sys.CreationFlags | CREATE_UNICODE_ENVIRONMENT
+       // On Windows 7, console handles aren't real handles, so don't pass them
+       // through to PROC_THREAD_ATTRIBUTE_HANDLE_LIST.
+       for i := range fd {
+               if isLegacyWin7ConsoleHandle(fd[i]) {
+                       fd[i] = 0
+               }
+       }
+
+       // The presence of a NULL handle in the list is enough to cause PROC_THREAD_ATTRIBUTE_HANDLE_LIST
+       // to treat the entire list as empty, so remove NULL handles.
+       j := 0
+       for i := range fd {
+               if fd[i] != 0 {
+                       fd[j] = fd[i]
+                       j++
+               }
+       }
+       fd = fd[:j]
+
+       // Do not accidentally inherit more than these handles.
+       if len(fd) > 0 {
+               err = updateProcThreadAttribute(si.ProcThreadAttributeList, 0, _PROC_THREAD_ATTRIBUTE_HANDLE_LIST, unsafe.Pointer(&fd[0]), uintptr(len(fd))*unsafe.Sizeof(fd[0]), nil, nil)
+               if err != nil {
+                       return 0, 0, err
+               }
+       }
+
+       pi := new(ProcessInformation)
+       flags := sys.CreationFlags | CREATE_UNICODE_ENVIRONMENT | _EXTENDED_STARTUPINFO_PRESENT
        if sys.Token != 0 {
-               err = CreateProcessAsUser(sys.Token, argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, !sys.NoInheritHandles, flags, createEnvBlock(attr.Env), dirp, si, pi)
+               err = CreateProcessAsUser(sys.Token, argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, len(fd) > 0 && !sys.NoInheritHandles, flags, createEnvBlock(attr.Env), dirp, &si.StartupInfo, pi)
        } else {
-               err = CreateProcess(argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, !sys.NoInheritHandles, flags, createEnvBlock(attr.Env), dirp, si, pi)
+               err = CreateProcess(argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, len(fd) > 0 && !sys.NoInheritHandles, flags, createEnvBlock(attr.Env), dirp, &si.StartupInfo, pi)
        }
        if err != nil {
                return 0, 0, err
        }
        defer CloseHandle(Handle(pi.Thread))
+       runtime.KeepAlive(fd)
+       runtime.KeepAlive(sys)
 
        return int(pi.ProcessId), uintptr(pi.Process), nil
 }
index eda1d3687780527ace85845bf348658a444572c4..8b8f330e9910a515bb832e529b5b4dcce2c27dcd 100644 (file)
@@ -5,8 +5,13 @@
 package syscall_test
 
 import (
+       "fmt"
+       "os"
+       "os/exec"
+       "path/filepath"
        "syscall"
        "testing"
+       "time"
 )
 
 func TestEscapeArg(t *testing.T) {
@@ -41,3 +46,70 @@ func TestEscapeArg(t *testing.T) {
                }
        }
 }
+
+func TestChangingProcessParent(t *testing.T) {
+       if os.Getenv("GO_WANT_HELPER_PROCESS") == "parent" {
+               // in parent process
+
+               // Parent does nothing. It is just used as a parent of a child process.
+               time.Sleep(time.Minute)
+               os.Exit(0)
+       }
+
+       if os.Getenv("GO_WANT_HELPER_PROCESS") == "child" {
+               // in child process
+               dumpPath := os.Getenv("GO_WANT_HELPER_PROCESS_FILE")
+               if dumpPath == "" {
+                       fmt.Fprintf(os.Stderr, "Dump file path cannot be blank.")
+                       os.Exit(1)
+               }
+               err := os.WriteFile(dumpPath, []byte(fmt.Sprintf("%d", os.Getppid())), 0644)
+               if err != nil {
+                       fmt.Fprintf(os.Stderr, "Error writing dump file: %v", err)
+                       os.Exit(2)
+               }
+               os.Exit(0)
+       }
+
+       // run parent process
+
+       parent := exec.Command(os.Args[0], "-test.run=TestChangingProcessParent")
+       parent.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=parent")
+       err := parent.Start()
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer func() {
+               parent.Process.Kill()
+               parent.Wait()
+       }()
+
+       // run child process
+
+       const _PROCESS_CREATE_PROCESS = 0x0080
+       const _PROCESS_DUP_HANDLE = 0x0040
+       childDumpPath := filepath.Join(t.TempDir(), "ppid.txt")
+       ph, err := syscall.OpenProcess(_PROCESS_CREATE_PROCESS|_PROCESS_DUP_HANDLE|syscall.PROCESS_QUERY_INFORMATION,
+               false, uint32(parent.Process.Pid))
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer syscall.CloseHandle(ph)
+
+       child := exec.Command(os.Args[0], "-test.run=TestChangingProcessParent")
+       child.Env = append(os.Environ(),
+               "GO_WANT_HELPER_PROCESS=child",
+               "GO_WANT_HELPER_PROCESS_FILE="+childDumpPath)
+       child.SysProcAttr = &syscall.SysProcAttr{ParentProcess: ph}
+       childOutput, err := child.CombinedOutput()
+       if err != nil {
+               t.Errorf("child failed: %v: %v", err, string(childOutput))
+       }
+       childOutput, err = os.ReadFile(childDumpPath)
+       if err != nil {
+               t.Fatalf("reading child output failed: %v", err)
+       }
+       if got, want := string(childOutput), fmt.Sprintf("%d", parent.Process.Pid); got != want {
+               t.Fatalf("child output: want %q, got %q", want, got)
+       }
+}
index 1b7875695a4247110295718e8b3a293abf43e34f..b051e368d4fc04ebf7a8234d65baf949ea792411 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build dragonfly freebsd hurd linux netbsd openbsd solaris
+//go:build dragonfly || freebsd || hurd || linux || netbsd || openbsd
+// +build dragonfly freebsd hurd linux netbsd openbsd
 
 package syscall
 
diff --git a/libgo/go/syscall/export_windows_test.go b/libgo/go/syscall/export_windows_test.go
new file mode 100644 (file)
index 0000000..a72a1ee
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+var NewProcThreadAttributeList = newProcThreadAttributeList
+var UpdateProcThreadAttribute = updateProcThreadAttribute
+var DeleteProcThreadAttributeList = deleteProcThreadAttributeList
+
+const PROC_THREAD_ATTRIBUTE_HANDLE_LIST = _PROC_THREAD_ATTRIBUTE_HANDLE_LIST
index d9999cb8b860b95327646b32f7fb1a11ec8f1f19..79cbdf4150f5354fb3ccb913019ded8a656ace5e 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build aix darwin dragonfly solaris
+//go:build aix || darwin || solaris
+// +build aix darwin solaris
 
 package syscall
 
index 747afd64be029235887b9815c94c51423eca9646..bdffdcd6f276c3cc9d19458b3d0c071a79034452 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build freebsd hurd netbsd openbsd
+//go:build dragonfly || freebsd || hurd || netbsd || openbsd
+// +build dragonfly freebsd hurd netbsd openbsd
 
 package syscall
 
index 673feea77f24ac9dd8ca5769511d597bbe154f46..0170516201473f85afc8e7ecc49a92ba65194b91 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build js && wasm
 // +build js,wasm
 
 package syscall
index 66bb8acba2ea07507d6654e62e924900d2ce2023..814e656649b8eda0ae780ce63ddbafc682a9205b 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || freebsd || netbsd || openbsd
 // +build darwin freebsd netbsd openbsd
 
 package syscall_test
@@ -28,11 +29,7 @@ func testGetdirentries(t *testing.T, count int) {
        if count > 100 && testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" {
                t.Skip("skipping in -short mode")
        }
-       d, err := os.MkdirTemp("", "getdirentries-test")
-       if err != nil {
-               t.Fatalf("Tempdir: %v", err)
-       }
-       defer os.RemoveAll(d)
+       d := t.TempDir()
        var names []string
        for i := 0; i < count; i++ {
                names = append(names, fmt.Sprintf("file%03d", i))
index a32d6968f24fcb5b057a25b3d37de9796c5778db..f02112390510087fd6afdfe161a2054e85c412ee 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build hurd || linux
 // +build hurd linux
 
 // glibc library calls.
@@ -9,6 +10,7 @@
 package syscall
 
 import (
+       "internal/itoa"
        "internal/race"
        "unsafe"
 )
@@ -28,7 +30,7 @@ func Futimesat(dirfd int, path string, tv []Timeval) (err error) {
 func Futimes(fd int, tv []Timeval) (err error) {
        // Believe it or not, this is the best we can do on GNU/Linux
        // (and is what glibc does).
-       return Utimes("/proc/self/fd/"+itoa(fd), tv)
+       return Utimes("/proc/self/fd/"+itoa.Itoa(fd), tv)
 }
 
 //sys  accept4(fd int, sa *RawSockaddrAny, len *Socklen_t, flags int) (nfd int, err error)
index 2ebaf8d3513e53b2cedb20f85fdcb07cff2c1f17..e0ec46681d14a5ed20f10e713461089d05a4ebae 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 // mkasm.go generates assembly trampolines to call library routines from Go.
index df179c22e01f7af54dba2f138c269edd126dfc75..f4eb54d0ffc93f19ba1632d6f4fa763fa052f4b2 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd
 
 package syscall_test
index ff10be9d25d59c1a801d91033e18af4085bfb11b..85097025a0bdbec1e49eb1b32ed46838dd3ab7a6 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !msan
 // +build !msan
 
 package syscall
index 25f171bda870a5c0c1815ac1d50034cb674906bd..ed462025bbc88c1d3f5e4972e51320ba1c726b25 100644 (file)
@@ -5,6 +5,7 @@
 // js/wasm uses fake networking directly implemented in the net package.
 // This file only exists to make the compiler happy.
 
+//go:build js && wasm
 // +build js,wasm
 
 package syscall
index 0c32594783c2b2e589dd55a77b766a2ba0aad0f8..0dc5fc0d0a7237bb0af29a918db2a69596471564 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || netbsd || openbsd
 // +build darwin dragonfly freebsd netbsd openbsd
 
 package syscall
index aed8682237a033f21387cf94d468edfad59b455e..412833a37cb2d5a05f33b41c0c68669eb066e8ce 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build (freebsd && 386) || (freebsd && arm)
 // +build freebsd,386 freebsd,arm
 
 package syscall
index e70ba3df8969077454eea3eafbeb66b9f731ce72..5300bed47173852ac5d7f0f822fb5f32ac739f99 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build (freebsd && amd64) || (freebsd && arm64)
 // +build freebsd,amd64 freebsd,arm64
 
 package syscall
index 1fe7120d1c6abb802971c912f319ce79939eed66..4e657c857c4cdcf4017680b51340caccaf2912ea 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build linux && (386 || arm)
 // +build linux
 // +build 386 arm
 
index 22fa334bfa5e7c163e85ab648a5a87cadab255a5..c15090f03495cf8df29da85a48fdd9d1bdb9c832 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build linux
-// +build !386,!arm
+//go:build linux && !386 && !arm
+// +build linux,!386,!arm
 
 package syscall
 
index 6530bea52363930ca86d7a2f5b9fec803d7f1981..aaeecdb4410d99dc637809eb224fb2e7b0486b8d 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 // Socket control messages
index f5deeb475d370c7592da0036ef46cdc6c717f957..0b75b18afec4bcc6ccf1f967b73fb873614b1354 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin freebsd hurd linux netbsd openbsd solaris
 
 package syscall
diff --git a/libgo/go/syscall/str.go b/libgo/go/syscall/str.go
deleted file mode 100644 (file)
index 2ddf04b..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-func itoa(val int) string { // do it here rather than with fmt to avoid dependency
-       if val < 0 {
-               return "-" + uitoa(uint(-val))
-       }
-       return uitoa(uint(val))
-}
-
-func uitoa(val uint) string {
-       var buf [32]byte // big enough for int64
-       i := len(buf) - 1
-       for val >= 10 {
-               buf[i] = byte(val%10 + '0')
-               i--
-               val /= 10
-       }
-       buf[i] = byte(val + '0')
-       return string(buf[i:])
-}
index 2847d2b8e3ea8b55526807da06872606f2730105..f73216104274f2bbfeafd70438065afd511d61bb 100644 (file)
@@ -4,7 +4,10 @@
 
 package syscall
 
-import "unsafe"
+import (
+       "internal/abi"
+       "unsafe"
+)
 
 func direntIno(buf []byte) (uint64, bool) {
        return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
index 3ccfe5d463f0e8eba5f02aea7e4fd2beaed08e1f..89c7959d0c43ac3e81b0e9d70722fe8c48dc43fe 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build freebsd
 // +build freebsd
 
 package syscall_test
index 0ab8c3fba4c344f207a2ba923f215def5a4ced02..ed70d622842da2c45106474f14ca0a95388eb442 100644 (file)
@@ -2,11 +2,13 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build js && wasm
 // +build js,wasm
 
 package syscall
 
 import (
+       "internal/itoa"
        "internal/oserror"
        "sync"
        "unsafe"
@@ -59,7 +61,7 @@ func (e Errno) Error() string {
                        return s
                }
        }
-       return "errno " + itoa(int(e))
+       return "errno " + itoa.Itoa(int(e))
 }
 
 func (e Errno) Is(target error) bool {
@@ -105,7 +107,7 @@ func (s Signal) String() string {
                        return str
                }
        }
-       return "signal " + itoa(int(s))
+       return "signal " + itoa.Itoa(int(s))
 }
 
 var signals = [...]string{}
index 5a9f6d9155e538b6d5abf83d1f85e5893caacae0..5ad0772fe3cb4f6937d28d4cf9fcead5e7b79122 100644 (file)
@@ -20,6 +20,4 @@ func PtraceSetRegs(pid int, regs *PtraceRegs) (err error) {
        return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs)))
 }
 
-func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno) {
-       panic("not implemented")
-}
+func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno)
index 1a15218e3ea66bda23e8b111babd55a77a84f6ec..1df7a5f13f5cd14b4de48a6179bafe6f2074bb71 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build linux && (mips || mipsle || mips64 || mips64le || mips64p32 || mips64p32le)
 // +build linux
 // +build mips mipsle mips64 mips64le mips64p32 mips64p32le
 
@@ -25,6 +26,4 @@ func PtraceSetRegs(pid int, regs *PtraceRegs) (err error) {
        return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs)))
 }
 
-func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno) {
-       panic("not implemented")
-}
+func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno)
index 28b4eb4f19fa08eace1a4765006bd7f7d933e863..fd826e9a47de8a803117d63ad643b8d645056f41 100644 (file)
@@ -14,6 +14,7 @@ import (
        "os/signal"
        "path/filepath"
        "runtime"
+       "sort"
        "strconv"
        "strings"
        "syscall"
@@ -587,11 +588,23 @@ func compareStatus(filter, expect string) error {
                                // "Pid:\t".
                        }
                        if strings.HasPrefix(line, filter) {
-                               if line != expected {
-                                       return fmt.Errorf("%q got:%q want:%q (bad) [pid=%d file:'%s' %v]\n", tf, line, expected, pid, string(d), expectedProc)
+                               if line == expected {
+                                       foundAThread = true
+                                       break
                                }
-                               foundAThread = true
-                               break
+                               if filter == "Groups:" && strings.HasPrefix(line, "Groups:\t") {
+                                       // https://github.com/golang/go/issues/46145
+                                       // Containers don't reliably output this line in sorted order so manually sort and compare that.
+                                       a := strings.Split(line[8:], " ")
+                                       sort.Strings(a)
+                                       got := strings.Join(a, " ")
+                                       if got == expected[8:] {
+                                               foundAThread = true
+                                               break
+                                       }
+
+                               }
+                               return fmt.Errorf("%q got:%q want:%q (bad) [pid=%d file:'%s' %v]\n", tf, line, expected, pid, string(d), expectedProc)
                        }
                }
        }
index 6b7f54dcfd5c8d3881aad5b57d50187d916dd622..45729d9e8e9698b187aced0e53eb75f79d0bd54c 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd
 // +build darwin dragonfly freebsd linux netbsd openbsd
 
 package syscall_test
index 5390f8aace996bbe364c39fa7891371925d143bb..b2b9463b0ffaaef154fdc56c90e64728a6c3fad1 100644 (file)
@@ -5,7 +5,6 @@
 package syscall_test
 
 import (
-       "fmt"
        "internal/testenv"
        "os"
        "runtime"
@@ -33,22 +32,6 @@ func TestEnv(t *testing.T) {
        testSetGetenv(t, "TESTENV", "")
 }
 
-func TestItoa(t *testing.T) {
-       // Make most negative integer: 0x8000...
-       i := 1
-       for i<<1 != 0 {
-               i <<= 1
-       }
-       if i >= 0 {
-               t.Fatal("bad math")
-       }
-       s := syscall.Itoa(i)
-       f := fmt.Sprint(i)
-       if s != f {
-               t.Fatalf("itoa(%d) = %s, want %s", i, s, f)
-       }
-}
-
 // Check that permuting child process fds doesn't interfere with
 // reporting of fork/exec status. See Issue 14979.
 func TestExecErrPermutedFds(t *testing.T) {
index db6b3aa159149b42395014b50430d1790ca37a71..730cbfa28f772a449a6c734b35c0d042f4275208 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
 
 package syscall
index e4b4171eafa1870710e806c977538b1f4e3092d7..d3d467331869b7b5c5506cc418c5dcb252092376 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
 
 package syscall_test
@@ -80,16 +81,12 @@ func TestFcntlFlock(t *testing.T) {
        }
        if os.Getenv("GO_WANT_HELPER_PROCESS") == "" {
                // parent
-               tempDir, err := os.MkdirTemp("", "TestFcntlFlock")
-               if err != nil {
-                       t.Fatalf("Failed to create temp dir: %v", err)
-               }
+               tempDir := t.TempDir()
                name := filepath.Join(tempDir, "TestFcntlFlock")
                fd, err := syscall.Open(name, syscall.O_CREAT|syscall.O_RDWR|syscall.O_CLOEXEC, 0)
                if err != nil {
                        t.Fatalf("Open failed: %v", err)
                }
-               defer os.RemoveAll(tempDir)
                defer syscall.Close(fd)
                if err := syscall.Ftruncate(fd, 1<<20); err != nil {
                        t.Fatalf("Ftruncate(1<<20) failed: %v", err)
@@ -158,18 +155,12 @@ func TestPassFD(t *testing.T) {
 
        }
 
-       tempDir, err := os.MkdirTemp("", "TestPassFD")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(tempDir)
+       tempDir := t.TempDir()
 
        fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM, 0)
        if err != nil {
                t.Fatalf("Socketpair: %v", err)
        }
-       defer syscall.Close(fds[0])
-       defer syscall.Close(fds[1])
        writeFile := os.NewFile(uintptr(fds[0]), "child-writes")
        readFile := os.NewFile(uintptr(fds[1]), "parent-reads")
        defer writeFile.Close()
index a7c4f8c890fbdb8261129ab820e6790b25a0d417..64d958415d8f8be750a355e1cc40b258270a7070 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build js && wasm
 // +build js,wasm
 
 package syscall
index 5dec57a25acc496d417dae4ef8481156e7305761..cf88aeb921a1621891a01258995357db53022df4 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build faketime
 // +build faketime
 
 package syscall
index c94cef86862b3d722000187f7f777531e2789862..5eaa2daabd3f0537d95b5f759c78e05d4a866d2c 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !faketime
 // +build !faketime
 
 package syscall
index 42a743ef127cff733a296ed9f71e9e657e481077..f22c282ec3a77867ea80f6ce2b9eee802957f739 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris
 
 package syscall
diff --git a/libgo/go/syscall/types_windows_arm64.go b/libgo/go/syscall/types_windows_arm64.go
new file mode 100644 (file)
index 0000000..7d45ddb
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+type WSAData struct {
+       Version      uint16
+       HighVersion  uint16
+       MaxSockets   uint16
+       MaxUdpDg     uint16
+       VendorInfo   *byte
+       Description  [WSADESCRIPTION_LEN + 1]byte
+       SystemStatus [WSASYS_STATUS_LEN + 1]byte
+}
+
+type Servent struct {
+       Name    *byte
+       Aliases **byte
+       Proto   *byte
+       Port    uint16
+}
index a8f75e9712370adb7f87b6825c74af7d9008a118..15b4426c5a544cbc081bde34d7647bd3eb6f9365 100644 (file)
@@ -238,12 +238,15 @@ func (b *B) run1() bool {
        }
        // Only print the output if we know we are not going to proceed.
        // Otherwise it is printed in processBench.
-       if atomic.LoadInt32(&b.hasSub) != 0 || b.finished {
+       b.mu.RLock()
+       finished := b.finished
+       b.mu.RUnlock()
+       if atomic.LoadInt32(&b.hasSub) != 0 || finished {
                tag := "BENCH"
                if b.skipped {
                        tag = "SKIP"
                }
-               if b.chatty != nil && (len(b.output) > 0 || b.finished) {
+               if b.chatty != nil && (len(b.output) > 0 || finished) {
                        b.trimOutput()
                        fmt.Fprintf(b.w, "--- %s: %s\n%s", tag, b.name, b.output)
                }
index 4c1cbd19335b9635168b1feba8874a3dddb695a8..3b1dc8275b5b836ad7252dbd3adae6a96f424d17 100644 (file)
@@ -102,6 +102,30 @@ func TestRunParallelFail(t *testing.T) {
        })
 }
 
+func TestRunParallelFatal(t *testing.T) {
+       testing.Benchmark(func(b *testing.B) {
+               b.RunParallel(func(pb *testing.PB) {
+                       for pb.Next() {
+                               if b.N > 1 {
+                                       b.Fatal("error")
+                               }
+                       }
+               })
+       })
+}
+
+func TestRunParallelSkipNow(t *testing.T) {
+       testing.Benchmark(func(b *testing.B) {
+               b.RunParallel(func(pb *testing.PB) {
+                       for pb.Next() {
+                               if b.N > 1 {
+                                       b.SkipNow()
+                               }
+                       }
+               })
+       })
+}
+
 func ExampleB_RunParallel() {
        // Parallel benchmark for text/template.Template.Execute on a single object.
        testing.Benchmark(func(b *testing.B) {
index a5d4a23faca4c31797858c3fe24f5fa1903ef20a..9fef2f4696ec7944acc891eb3c69e86a3f376139 100644 (file)
@@ -223,12 +223,12 @@ func (d *mapDir) Read(b []byte) (int, error) {
 
 func (d *mapDir) ReadDir(count int) ([]fs.DirEntry, error) {
        n := len(d.entry) - d.offset
-       if count > 0 && n > count {
-               n = count
-       }
        if n == 0 && count > 0 {
                return nil, io.EOF
        }
+       if count > 0 && n > count {
+               n = count
+       }
        list := make([]fs.DirEntry, n)
        for i := range list {
                list[i] = &d.entry[d.offset+i]
index 8fc8acaaf3bf1bb88fda7138002f5678a8266178..5c4f30af168422c75c05b2c272b9fbc430320592 100644 (file)
@@ -10,7 +10,6 @@ import (
        "fmt"
        "io"
        "io/fs"
-       "io/ioutil"
        "path"
        "reflect"
        "sort"
@@ -23,7 +22,7 @@ import (
 // opening and checking that each file behaves correctly.
 // It also checks that the file system contains at least the expected files.
 // As a special case, if no expected files are listed, fsys must be empty.
-// Otherwise, fsys must only contain at least the listed files: it can also contain others.
+// Otherwise, fsys must contain at least the listed files; it can also contain others.
 // The contents of fsys must not change concurrently with TestFS.
 //
 // If TestFS finds any misbehaviors, it returns an error reporting all of them.
@@ -303,7 +302,7 @@ func (t *fsTester) checkGlob(dir string, list []fs.DirEntry) {
                for i, e := range elem {
                        var pattern []rune
                        for j, r := range e {
-                               if r == '*' || r == '?' || r == '\\' || r == '[' {
+                               if r == '*' || r == '?' || r == '\\' || r == '[' || r == '-' {
                                        pattern = append(pattern, '\\', r)
                                        continue
                                }
@@ -514,7 +513,7 @@ func (t *fsTester) checkFile(file string) {
                return
        }
 
-       data, err := ioutil.ReadAll(f)
+       data, err := io.ReadAll(f)
        if err != nil {
                f.Close()
                t.errorf("%s: Open+ReadAll: %v", file, err)
@@ -538,6 +537,18 @@ func (t *fsTester) checkFile(file string) {
                }
                t.checkFileRead(file, "ReadAll vs fsys.ReadFile", data, data2)
 
+               // Modify the data and check it again. Modifying the
+               // returned byte slice should not affect the next call.
+               for i := range data2 {
+                       data2[i]++
+               }
+               data2, err = fsys.ReadFile(file)
+               if err != nil {
+                       t.errorf("%s: second call to fsys.ReadFile: %v", file, err)
+                       return
+               }
+               t.checkFileRead(file, "Readall vs second fsys.ReadFile", data, data2)
+
                t.checkBadPath(file, "ReadFile",
                        func(name string) error { _, err := fsys.ReadFile(name); return err })
        }
index 5b8813c3431339fb98ea9e2ecacf188103550770..aefb4b33617ab119e30d259517d37694defbe560 100644 (file)
@@ -29,3 +29,12 @@ func TestSymlink(t *testing.T) {
                t.Fatal(err)
        }
 }
+
+func TestDash(t *testing.T) {
+       m := MapFS{
+               "a-b/a": {Data: []byte("a-b/a")},
+       }
+       if err := TestFS(m, "a-b/a"); err != nil {
+               t.Error(err)
+       }
+}
index 4dc83f7d32476247ec65b089520da4f4533d0933..d9e342d4951edd62ec5f1537f076b7d38846fb82 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !js
 // +build !js
 
 // TODO(@musiol, @odeke-em): re-unify this entire file back into
index 1d4164b61f9ecc37d7e98b6a7878da48245f29b1..d914633ba91889b975e9f764aaed56f9e9c0d90c 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build js
 // +build js
 
 package testing
index 5b226f85ad198d4280e322cced16157e8191c708..6c7d83aac2c036af89e65de2a1f35f44243f52a7 100644 (file)
@@ -822,7 +822,7 @@ func TestLogAfterComplete(t *T) {
                                                c2 <- fmt.Sprintf("subtest panic with unexpected value %v", p)
                                                return
                                        }
-                                       const want = "Log in goroutine after TestLateLog has completed"
+                                       const want = "Log in goroutine after TestLateLog has completed: log after test"
                                        if !strings.Contains(s, want) {
                                                c2 <- fmt.Sprintf("subtest panic %q does not contain %q", s, want)
                                        }
index 143d81c08a27d56c7bb32d721254cd7cc0c92604..4c823dcb36772a5f6f7e649012894ee20ad1da1d 100644 (file)
 //         }
 //     }
 //
-// The race detector kills the program if it exceeds 8192 concurrent goroutines,
+// The race detector kills the program if it exceeds 8128 concurrent goroutines,
 // so use care when running parallel tests with the -race flag set.
 //
 // Run does not return until parallel subtests have completed, providing a way
 //
 // Main
 //
-// It is sometimes necessary for a test program to do extra setup or teardown
-// before or after testing. It is also sometimes necessary for a test to control
+// It is sometimes necessary for a test or benchmark program to do extra setup or teardown
+// before or after it executes. It is also sometimes necessary to control
 // which code runs on the main thread. To support these and other cases,
 // if a test file contains a function:
 //
 //     func TestMain(m *testing.M)
 //
-// then the generated test will call TestMain(m) instead of running the tests
+// then the generated test will call TestMain(m) instead of running the tests or benchmarks
 // directly. TestMain runs in the main goroutine and can do whatever setup
 // and teardown is necessary around a call to m.Run. m.Run will return an exit
 // code that may be passed to os.Exit. If TestMain returns, the test wrapper
 //             os.Exit(m.Run())
 //     }
 //
+// TestMain is a low-level primitive and should not be necessary for casual
+// testing needs, where ordinary test functions suffice.
 package testing
 
 import (
@@ -242,6 +244,7 @@ import (
        "fmt"
        "internal/race"
        "io"
+       "math/rand"
        "os"
        "runtime"
        "runtime/debug"
@@ -251,6 +254,8 @@ import (
        "sync"
        "sync/atomic"
        "time"
+       "unicode"
+       "unicode/utf8"
 )
 
 var initRan bool
@@ -299,6 +304,7 @@ func Init() {
        cpuListStr = flag.String("test.cpu", "", "comma-separated `list` of cpu counts to run each test with")
        parallel = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "run at most `n` tests in parallel")
        testlog = flag.String("test.testlogfile", "", "write test action log to `file` (for use only by cmd/go)")
+       shuffle = flag.String("test.shuffle", "off", "randomize the execution order of tests and benchmarks")
 
        initBenchmarkFlags()
 }
@@ -325,6 +331,7 @@ var (
        timeout              *time.Duration
        cpuListStr           *string
        parallel             *int
+       shuffle              *string
        testlog              *string
 
        haveExamples bool // are there examples?
@@ -388,17 +395,17 @@ type common struct {
        w           io.Writer            // For flushToParent.
        ran         bool                 // Test or benchmark (or one of its subtests) was executed.
        failed      bool                 // Test or benchmark has failed.
-       skipped     bool                 // Test of benchmark has been skipped.
+       skipped     bool                 // Test or benchmark has been skipped.
        done        bool                 // Test is finished and all subtests have completed.
        helperPCs   map[uintptr]struct{} // functions to be skipped when writing file/line info
        helperNames map[string]struct{}  // helperPCs converted to function names
        cleanups    []func()             // optional functions to be called at the end of the test
        cleanupName string               // Name of the cleanup function.
        cleanupPc   []uintptr            // The stack trace at the point where Cleanup was called.
+       finished    bool                 // Test function has completed.
 
        chatty     *chattyPrinter // A copy of chattyPrinter, if the chatty flag is set.
        bench      bool           // Whether the current test is a benchmark.
-       finished   bool           // Test function has completed.
        hasSub     int32          // Written atomically.
        raceErrors int            // Number of races detected during test.
        runner     string         // Function name of tRunner running the test.
@@ -639,6 +646,7 @@ type TB interface {
        Log(args ...interface{})
        Logf(format string, args ...interface{})
        Name() string
+       Setenv(key, value string)
        Skip(args ...interface{})
        SkipNow()
        Skipf(format string, args ...interface{})
@@ -666,12 +674,17 @@ var _ TB = (*B)(nil)
 type T struct {
        common
        isParallel bool
+       isEnvSet   bool
        context    *testContext // For running tests and subtests.
 }
 
 func (c *common) private() {}
 
-// Name returns the name of the running test or benchmark.
+// Name returns the name of the running (sub-) test or benchmark.
+//
+// The name will include the name of the test along with the names of
+// any nested sub-tests. If two sibling sub-tests have the same name,
+// Name will append a suffix to guarantee the returned name is unique.
 func (c *common) Name() string {
        return c.name
 }
@@ -737,7 +750,9 @@ func (c *common) FailNow() {
        // it would run on a test failure. Because we send on c.signal during
        // a top-of-stack deferred function now, we know that the send
        // only happens after any other stacked defers have completed.
+       c.mu.Lock()
        c.finished = true
+       c.mu.Unlock()
        runtime.Goexit()
 }
 
@@ -761,7 +776,7 @@ func (c *common) logDepth(s string, depth int) {
                                return
                        }
                }
-               panic("Log in goroutine after " + c.name + " has completed")
+               panic("Log in goroutine after " + c.name + " has completed: " + s)
        } else {
                if c.chatty != nil {
                        if c.bench {
@@ -872,15 +887,11 @@ func (c *common) Skipf(format string, args ...interface{}) {
 // other goroutines created during the test. Calling SkipNow does not stop
 // those other goroutines.
 func (c *common) SkipNow() {
-       c.skip()
-       c.finished = true
-       runtime.Goexit()
-}
-
-func (c *common) skip() {
        c.mu.Lock()
-       defer c.mu.Unlock()
        c.skipped = true
+       c.finished = true
+       c.mu.Unlock()
+       runtime.Goexit()
 }
 
 // Skipped reports whether the test was skipped.
@@ -911,7 +922,7 @@ func (c *common) Helper() {
        }
 }
 
-// Cleanup registers a function to be called when the test and all its
+// Cleanup registers a function to be called when the test (or subtest) and all its
 // subtests complete. Cleanup functions will be called in last added,
 // first called order.
 func (c *common) Cleanup(f func()) {
@@ -942,11 +953,6 @@ func (c *common) Cleanup(f func()) {
        c.cleanups = append(c.cleanups, fn)
 }
 
-var tempDirReplacer struct {
-       sync.Once
-       r *strings.Replacer
-}
-
 // TempDir returns a temporary directory for the test to use.
 // The directory is automatically removed by Cleanup when the test and
 // all its subtests complete.
@@ -970,13 +976,26 @@ func (c *common) TempDir() string {
        if nonExistent {
                c.Helper()
 
-               // os.MkdirTemp doesn't like path separators in its pattern,
-               // so mangle the name to accommodate subtests.
-               tempDirReplacer.Do(func() {
-                       tempDirReplacer.r = strings.NewReplacer("/", "_", "\\", "_", ":", "_")
-               })
-               pattern := tempDirReplacer.r.Replace(c.Name())
-
+               // Drop unusual characters (such as path separators or
+               // characters interacting with globs) from the directory name to
+               // avoid surprising os.MkdirTemp behavior.
+               mapper := func(r rune) rune {
+                       if r < utf8.RuneSelf {
+                               const allowed = "!#$%&()+,-.=@^_{}~ "
+                               if '0' <= r && r <= '9' ||
+                                       'a' <= r && r <= 'z' ||
+                                       'A' <= r && r <= 'Z' {
+                                       return r
+                               }
+                               if strings.ContainsRune(allowed, r) {
+                                       return r
+                               }
+                       } else if unicode.IsLetter(r) || unicode.IsNumber(r) {
+                               return r
+                       }
+                       return -1
+               }
+               pattern := strings.Map(mapper, c.Name())
                c.tempDir, c.tempDirErr = os.MkdirTemp("", pattern)
                if c.tempDirErr == nil {
                        c.Cleanup(func() {
@@ -999,6 +1018,29 @@ func (c *common) TempDir() string {
        return dir
 }
 
+// Setenv calls os.Setenv(key, value) and uses Cleanup to
+// restore the environment variable to its original value
+// after the test.
+//
+// This cannot be used in parallel tests.
+func (c *common) Setenv(key, value string) {
+       prevValue, ok := os.LookupEnv(key)
+
+       if err := os.Setenv(key, value); err != nil {
+               c.Fatalf("cannot set environment variable: %v", err)
+       }
+
+       if ok {
+               c.Cleanup(func() {
+                       os.Setenv(key, prevValue)
+               })
+       } else {
+               c.Cleanup(func() {
+                       os.Unsetenv(key)
+               })
+       }
+}
+
 // panicHanding is an argument to runCleanup.
 type panicHandling int
 
@@ -1070,6 +1112,9 @@ func (t *T) Parallel() {
        if t.isParallel {
                panic("testing: t.Parallel called multiple times")
        }
+       if t.isEnvSet {
+               panic("testing: t.Parallel called after t.Setenv; cannot set environment variables in parallel tests")
+       }
        t.isParallel = true
 
        // We don't want to include the time we spend waiting for serial tests
@@ -1103,6 +1148,21 @@ func (t *T) Parallel() {
        t.raceErrors += -race.Errors()
 }
 
+// Setenv calls os.Setenv(key, value) and uses Cleanup to
+// restore the environment variable to its original value
+// after the test.
+//
+// This cannot be used in parallel tests.
+func (t *T) Setenv(key, value string) {
+       if t.isParallel {
+               panic("testing: t.Setenv called after t.Parallel; cannot set environment variables in parallel tests")
+       }
+
+       t.isEnvSet = true
+
+       t.common.Setenv(key, value)
+}
+
 // InternalTest is an internal type but exported because it is cross-package;
 // it is part of the implementation of the "go test" command.
 type InternalTest struct {
@@ -1132,10 +1192,16 @@ func tRunner(t *T, fn func(t *T)) {
                err := recover()
                signal := true
 
-               if !t.finished && err == nil {
+               t.mu.RLock()
+               finished := t.finished
+               t.mu.RUnlock()
+               if !finished && err == nil {
                        err = errNilPanicOrGoexit
                        for p := t.parent; p != nil; p = p.parent {
-                               if p.finished {
+                               p.mu.RLock()
+                               finished = p.finished
+                               p.mu.RUnlock()
+                               if finished {
                                        t.Errorf("%v: subtest may have called FailNow on a parent test", err)
                                        err = nil
                                        signal = false
@@ -1229,7 +1295,9 @@ func tRunner(t *T, fn func(t *T)) {
        fn(t)
 
        // code beyond here will not be executed when FailNow is invoked
+       t.mu.Lock()
        t.finished = true
+       t.mu.Unlock()
 }
 
 // Run runs f as a subtest of t called name. It runs f in a separate goroutine
@@ -1252,7 +1320,7 @@ func (t *T) Run(name string, f func(t *T)) bool {
        t = &T{
                common: common{
                        barrier: make(chan bool),
-                       signal:  make(chan bool),
+                       signal:  make(chan bool, 1),
                        name:    testName,
                        parent:  &t.common,
                        level:   t.level + 1,
@@ -1444,6 +1512,25 @@ func (m *M) Run() (code int) {
                return
        }
 
+       if *shuffle != "off" {
+               var n int64
+               var err error
+               if *shuffle == "on" {
+                       n = time.Now().UnixNano()
+               } else {
+                       n, err = strconv.ParseInt(*shuffle, 10, 64)
+                       if err != nil {
+                               fmt.Fprintln(os.Stderr, `testing: -shuffle should be "off", "on", or a valid integer:`, err)
+                               m.exitCode = 2
+                               return
+                       }
+               }
+               fmt.Println("-test.shuffle", n)
+               rng := rand.New(rand.NewSource(n))
+               rng.Shuffle(len(m.tests), func(i, j int) { m.tests[i], m.tests[j] = m.tests[j], m.tests[i] })
+               rng.Shuffle(len(m.benchmarks), func(i, j int) { m.benchmarks[i], m.benchmarks[j] = m.benchmarks[j], m.benchmarks[i] })
+       }
+
        parseCpuList()
 
        m.before()
@@ -1533,7 +1620,7 @@ func runTests(matchString func(pat, str string) (bool, error), tests []InternalT
                        ctx.deadline = deadline
                        t := &T{
                                common: common{
-                                       signal:  make(chan bool),
+                                       signal:  make(chan bool, 1),
                                        barrier: make(chan bool),
                                        w:       os.Stdout,
                                },
@@ -1546,11 +1633,12 @@ func runTests(matchString func(pat, str string) (bool, error), tests []InternalT
                                for _, test := range tests {
                                        t.Run(test.Name, test.F)
                                }
-                               // Run catching the signal rather than the tRunner as a separate
-                               // goroutine to avoid adding a goroutine during the sequential
-                               // phase as this pollutes the stacktrace output when aborting.
-                               go func() { <-t.signal }()
                        })
+                       select {
+                       case <-t.signal:
+                       default:
+                               panic("internal error: tRunner exited without sending on t.signal")
+                       }
                        ok = ok && !t.Failed()
                        ran = ran || t.ran
                }
index 0f096980ca4561798f227f567161cdc19d97d23a..08ae23991f18f6484e0cd10162ec879c5ca9bc90 100644 (file)
@@ -58,6 +58,9 @@ func TestTempDir(t *testing.T) {
        t.Run("test:subtest", testTempDir)
        t.Run("test/..", testTempDir)
        t.Run("../test", testTempDir)
+       t.Run("test[]", testTempDir)
+       t.Run("test*", testTempDir)
+       t.Run("äöüéè", testTempDir)
 }
 
 func testTempDir(t *testing.T) {
@@ -74,7 +77,7 @@ func testTempDir(t *testing.T) {
                        if err != nil {
                                t.Fatal(err)
                        }
-                       t.Errorf("directory %q stil exists: %v, isDir=%v", dir, fi, fi.IsDir())
+                       t.Errorf("directory %q still exists: %v, isDir=%v", dir, fi, fi.IsDir())
                default:
                        if !t.Failed() {
                                t.Fatal("never received dir channel")
@@ -108,4 +111,92 @@ func testTempDir(t *testing.T) {
        if len(files) > 0 {
                t.Errorf("unexpected %d files in TempDir: %v", len(files), files)
        }
+
+       glob := filepath.Join(dir, "*.txt")
+       if _, err := filepath.Glob(glob); err != nil {
+               t.Error(err)
+       }
+}
+
+func TestSetenv(t *testing.T) {
+       tests := []struct {
+               name               string
+               key                string
+               initialValueExists bool
+               initialValue       string
+               newValue           string
+       }{
+               {
+                       name:               "initial value exists",
+                       key:                "GO_TEST_KEY_1",
+                       initialValueExists: true,
+                       initialValue:       "111",
+                       newValue:           "222",
+               },
+               {
+                       name:               "initial value exists but empty",
+                       key:                "GO_TEST_KEY_2",
+                       initialValueExists: true,
+                       initialValue:       "",
+                       newValue:           "222",
+               },
+               {
+                       name:               "initial value is not exists",
+                       key:                "GO_TEST_KEY_3",
+                       initialValueExists: false,
+                       initialValue:       "",
+                       newValue:           "222",
+               },
+       }
+
+       for _, test := range tests {
+               if test.initialValueExists {
+                       if err := os.Setenv(test.key, test.initialValue); err != nil {
+                               t.Fatalf("unable to set env: got %v", err)
+                       }
+               } else {
+                       os.Unsetenv(test.key)
+               }
+
+               t.Run(test.name, func(t *testing.T) {
+                       t.Setenv(test.key, test.newValue)
+                       if os.Getenv(test.key) != test.newValue {
+                               t.Fatalf("unexpected value after t.Setenv: got %s, want %s", os.Getenv(test.key), test.newValue)
+                       }
+               })
+
+               got, exists := os.LookupEnv(test.key)
+               if got != test.initialValue {
+                       t.Fatalf("unexpected value after t.Setenv cleanup: got %s, want %s", got, test.initialValue)
+               }
+               if exists != test.initialValueExists {
+                       t.Fatalf("unexpected value after t.Setenv cleanup: got %t, want %t", exists, test.initialValueExists)
+               }
+       }
+}
+
+func TestSetenvWithParallelAfterSetenv(t *testing.T) {
+       defer func() {
+               want := "testing: t.Parallel called after t.Setenv; cannot set environment variables in parallel tests"
+               if got := recover(); got != want {
+                       t.Fatalf("expected panic; got %#v want %q", got, want)
+               }
+       }()
+
+       t.Setenv("GO_TEST_KEY_1", "value")
+
+       t.Parallel()
+}
+
+func TestSetenvWithParallelBeforeSetenv(t *testing.T) {
+       defer func() {
+               want := "testing: t.Setenv called after t.Parallel; cannot set environment variables in parallel tests"
+               if got := recover(); got != want {
+                       t.Fatalf("expected panic; got %#v want %q", got, want)
+               }
+       }()
+
+       t.Parallel()
+
+       t.Setenv("GO_TEST_KEY_1", "value")
 }
index e0847a7239680c286a4805834be680ff2104a754..c5fc4ff93b9061de0c32131d65dbadc324507b97 100644 (file)
@@ -23,7 +23,7 @@ import (
        "unicode/utf8"
 )
 
-// A source position is represented by a Position value.
+// Position is a value that represents a source position.
 // A position is valid if Line > 0.
 type Position struct {
        Filename string // filename, if any
index ab848055875c38926a86fa53d865924f4fe3cf8e..545820dd804495def92ec0f34c423dafb213a6d7 100644 (file)
@@ -181,10 +181,7 @@ func errRecover(errp *error) {
 // A template may be executed safely in parallel, although if parallel
 // executions share a Writer the output may be interleaved.
 func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
-       var tmpl *Template
-       if t.common != nil {
-               tmpl = t.tmpl[name]
-       }
+       tmpl := t.Lookup(name)
        if tmpl == nil {
                return fmt.Errorf("template: no template %q associated with template %q", name, t.name)
        }
@@ -232,6 +229,8 @@ func (t *Template) DefinedTemplates() string {
                return ""
        }
        var b strings.Builder
+       t.muTmpl.RLock()
+       defer t.muTmpl.RUnlock()
        for name, tmpl := range t.tmpl {
                if tmpl.Tree == nil || tmpl.Root == nil {
                        continue
@@ -403,7 +402,7 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
 
 func (s *state) walkTemplate(dot reflect.Value, t *parse.TemplateNode) {
        s.at(t)
-       tmpl := s.tmpl.tmpl[t.Name]
+       tmpl := s.tmpl.Lookup(t.Name)
        if tmpl == nil {
                s.errorf("template %q not defined", t.Name)
        }
@@ -617,7 +616,7 @@ func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node,
                tField, ok := receiver.Type().FieldByName(fieldName)
                if ok {
                        field := receiver.FieldByIndex(tField.Index)
-                       if tField.PkgPath != "" { // field is unexported
+                       if !tField.IsExported() {
                                s.errorf("%s is an unexported field of struct type %s", fieldName, typ)
                        }
                        // If it's a function, we must call it.
@@ -729,7 +728,7 @@ func (s *state) evalCall(dot, fun reflect.Value, node parse.Node, name string, a
        // error to the caller.
        if err != nil {
                s.at(node)
-               s.errorf("error calling %s: %v", name, err)
+               s.errorf("error calling %s: %w", name, err)
        }
        if v.Type() == reflectValueType {
                v = v.Interface().(reflect.Value)
index c821c05f3d8f1db5d1ef1ba384b4579dbdb40277..d64f690f87e0b6d32fdc058a4a531dc4c5ee8329 100644 (file)
@@ -12,6 +12,7 @@ import (
        "io"
        "reflect"
        "strings"
+       "sync"
        "testing"
 )
 
@@ -902,6 +903,28 @@ func TestExecError(t *testing.T) {
        }
 }
 
+type CustomError struct{}
+
+func (*CustomError) Error() string { return "heyo !" }
+
+// Check that a custom error can be returned.
+func TestExecError_CustomError(t *testing.T) {
+       failingFunc := func() (string, error) {
+               return "", &CustomError{}
+       }
+       tmpl := Must(New("top").Funcs(FuncMap{
+               "err": failingFunc,
+       }).Parse("{{ err }}"))
+
+       var b bytes.Buffer
+       err := tmpl.Execute(&b, nil)
+
+       var e *CustomError
+       if !errors.As(err, &e) {
+               t.Fatalf("expected custom error; got %s", err)
+       }
+}
+
 func TestJSEscaping(t *testing.T) {
        testCases := []struct {
                in, exp string
@@ -1178,8 +1201,11 @@ var cmpTests = []cmpTest{
        {"eq .Ptr .NilPtr", "false", true},
        {"eq .NilPtr .NilPtr", "true", true},
        {"eq .Iface1 .Iface1", "true", true},
-       {"eq .Iface1 .Iface2", "false", true},
-       {"eq .Iface2 .Iface2", "true", true},
+       {"eq .Iface1 .NilIface", "false", true},
+       {"eq .NilIface .NilIface", "true", true},
+       {"eq .NilIface .Iface1", "false", true},
+       {"eq .NilIface 0", "false", true},
+       {"eq 0 .NilIface", "false", true},
        // Errors
        {"eq `xy` 1", "", false},       // Different types.
        {"eq 2 2.0", "", false},        // Different types.
@@ -1194,12 +1220,12 @@ var cmpTests = []cmpTest{
 func TestComparison(t *testing.T) {
        b := new(bytes.Buffer)
        var cmpStruct = struct {
-               Uthree, Ufour  uint
-               NegOne, Three  int
-               Ptr, NilPtr    *int
-               Map            map[int]int
-               V1, V2         V
-               Iface1, Iface2 fmt.Stringer
+               Uthree, Ufour    uint
+               NegOne, Three    int
+               Ptr, NilPtr      *int
+               Map              map[int]int
+               V1, V2           V
+               Iface1, NilIface fmt.Stringer
        }{
                Uthree: 3,
                Ufour:  4,
@@ -1710,3 +1736,40 @@ func TestIssue43065(t *testing.T) {
                t.Errorf("%s", err)
        }
 }
+
+// Issue 39807: data race in html/template & text/template
+func TestIssue39807(t *testing.T) {
+       var wg sync.WaitGroup
+
+       tplFoo, err := New("foo").Parse(`{{ template "bar" . }}`)
+       if err != nil {
+               t.Error(err)
+       }
+
+       tplBar, err := New("bar").Parse("bar")
+       if err != nil {
+               t.Error(err)
+       }
+
+       gofuncs := 10
+       numTemplates := 10
+
+       for i := 1; i <= gofuncs; i++ {
+               wg.Add(1)
+               go func() {
+                       defer wg.Done()
+                       for j := 0; j < numTemplates; j++ {
+                               _, err := tplFoo.AddParseTree(tplBar.Name(), tplBar.Tree)
+                               if err != nil {
+                                       t.Error(err)
+                               }
+                               err = tplFoo.Execute(io.Discard, nil)
+                               if err != nil {
+                                       t.Error(err)
+                               }
+                       }
+               }()
+       }
+
+       wg.Wait()
+}
index 1b6940a84ae0d702f5775b8ca85efddd3b15afbb..fff833ed29813e21f8826914acf20b1e038ddf7b 100644 (file)
@@ -23,6 +23,9 @@ import (
 // return value evaluates to non-nil during execution, execution terminates and
 // Execute returns that error.
 //
+// Errors returned by Execute wrap the underlying error; call errors.As to
+// uncover them.
+//
 // When template execution invokes a function with an argument list, that list
 // must be assignable to the function's parameter types. Functions meant to
 // apply to arguments of arbitrary type can use parameters of type interface{} or
@@ -344,7 +347,7 @@ func call(fn reflect.Value, args ...reflect.Value) (reflect.Value, error) {
 
                var err error
                if argv[i], err = prepareArg(arg, argType); err != nil {
-                       return reflect.Value{}, fmt.Errorf("arg %d: %s", i, err)
+                       return reflect.Value{}, fmt.Errorf("arg %d: %w", i, err)
                }
        }
        return safeCall(fn, argv)
@@ -475,7 +478,9 @@ func eq(arg1 reflect.Value, arg2 ...reflect.Value) (bool, error) {
                        case k1 == uintKind && k2 == intKind:
                                truth = arg.Int() >= 0 && arg1.Uint() == uint64(arg.Int())
                        default:
-                               return false, errBadComparison
+                               if arg1 != zero && arg != zero {
+                                       return false, errBadComparison
+                               }
                        }
                } else {
                        switch k1 {
@@ -492,7 +497,7 @@ func eq(arg1 reflect.Value, arg2 ...reflect.Value) (bool, error) {
                        case uintKind:
                                truth = arg1.Uint() == arg.Uint()
                        default:
-                               if arg == zero {
+                               if arg == zero || arg1 == zero {
                                        truth = arg1 == arg
                                } else {
                                        if t2 := arg.Type(); !t2.Comparable() {
index 9dc70dfc0dae4457bed670dad14d1761a1429d97..e1d3136abe781137dc5c6fc9d58f1d4d0bf44c97 100644 (file)
@@ -39,11 +39,7 @@ func main() {
        t.Used()
 }
 `
-       td, err := os.MkdirTemp("", "text_template_TestDeadCodeElimination")
-       if err != nil {
-               t.Fatal(err)
-       }
-       defer os.RemoveAll(td)
+       td := t.TempDir()
 
        if err := os.WriteFile(filepath.Join(td, "x.go"), []byte(prog), 0644); err != nil {
                t.Fatal(err)
index 5e6e512eb4314cd9aaa6c6555ba9a2bc095916a1..1a63961c13ecce1c892584698d26e54836a1eed4 100644 (file)
@@ -39,6 +39,7 @@ type Mode uint
 
 const (
        ParseComments Mode = 1 << iota // parse comments and add them to AST
+       SkipFuncCheck                  // do not check that functions are defined
 )
 
 // Copy returns a copy of the Tree. Any parsing state is discarded.
@@ -689,7 +690,8 @@ func (t *Tree) operand() Node {
 func (t *Tree) term() Node {
        switch token := t.nextNonSpace(); token.typ {
        case itemIdentifier:
-               if !t.hasFunction(token.val) {
+               checkFunc := t.Mode&SkipFuncCheck == 0
+               if checkFunc && !t.hasFunction(token.val) {
                        t.errorf("function %q not defined", token.val)
                }
                return NewIdentifier(token.val).SetTree(t).SetPos(token.pos)
index 220f984777b74ec13d4b0bd616bfb98395860cae..9b1be272e573d98e38c3da477f50660fdeddd3d0 100644 (file)
@@ -379,6 +379,22 @@ func TestParseWithComments(t *testing.T) {
        }
 }
 
+func TestSkipFuncCheck(t *testing.T) {
+       oldTextFormat := textFormat
+       textFormat = "%q"
+       defer func() { textFormat = oldTextFormat }()
+       tr := New("skip func check")
+       tr.Mode = SkipFuncCheck
+       tmpl, err := tr.Parse("{{fn 1 2}}", "", "", make(map[string]*Tree))
+       if err != nil {
+               t.Fatalf("unexpected error: %v", err)
+       }
+       expected := "{{fn 1 2}}"
+       if result := tmpl.Root.String(); result != expected {
+               t.Errorf("got\n\t%v\nexpected\n\t%v", result, expected)
+       }
+}
+
 type isEmptyTest struct {
        name  string
        input string
index ec26eb4c50a7a4a17d2450b18cbdfebd31af01f1..fd74d45e9b1c6df9a0bf45206eba1d040dd0d3b9 100644 (file)
@@ -13,6 +13,7 @@ import (
 // common holds the information shared by related templates.
 type common struct {
        tmpl   map[string]*Template // Map from name to defined templates.
+       muTmpl sync.RWMutex         // protects tmpl
        option option
        // We use two maps, one for parsing and one for execution.
        // This separation makes the API cleaner since it doesn't
@@ -88,6 +89,8 @@ func (t *Template) Clone() (*Template, error) {
        if t.common == nil {
                return nt, nil
        }
+       t.muTmpl.RLock()
+       defer t.muTmpl.RUnlock()
        for k, v := range t.tmpl {
                if k == t.name {
                        nt.tmpl[t.name] = nt
@@ -124,6 +127,8 @@ func (t *Template) copy(c *common) *Template {
 // its definition. If it has been defined and already has that name, the existing
 // definition is replaced; otherwise a new template is created, defined, and returned.
 func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) {
+       t.muTmpl.Lock()
+       defer t.muTmpl.Unlock()
        t.init()
        nt := t
        if name != t.name {
@@ -142,6 +147,8 @@ func (t *Template) Templates() []*Template {
                return nil
        }
        // Return a slice so we don't expose the map.
+       t.muTmpl.RLock()
+       defer t.muTmpl.RUnlock()
        m := make([]*Template, 0, len(t.tmpl))
        for _, v := range t.tmpl {
                m = append(m, v)
@@ -182,6 +189,8 @@ func (t *Template) Lookup(name string) *Template {
        if t.common == nil {
                return nil
        }
+       t.muTmpl.RLock()
+       defer t.muTmpl.RUnlock()
        return t.tmpl[name]
 }
 
index cb4fdac4efa37e97fb0050f1cdd32b89e87239b2..34490c859ddb51af4c18ddddea22da1cace87a76 100644 (file)
@@ -5,6 +5,7 @@
 // This file is used with build tag timetzdata to embed tzdata into
 // the binary.
 
+//go:build timetzdata
 // +build timetzdata
 
 package time
index f4a8cd9b72af6842fa3744728deb0123fbbdcddb..9baad60a92aaf3f7078936cc7009384295e388a5 100644 (file)
@@ -51,6 +51,7 @@ const (
        RuleJulian       = RuleKind(ruleJulian)
        RuleDOY          = RuleKind(ruleDOY)
        RuleMonthWeekDay = RuleKind(ruleMonthWeekDay)
+       UnixToInternal   = unixToInternal
 )
 
 type Rule struct {
@@ -128,3 +129,5 @@ var StdChunkNames = map[int]string{
        stdFracSecond9 | 8<<stdArgShift: ".99999999",
        stdFracSecond9 | 9<<stdArgShift: ".999999999",
 }
+
+var Quote = quote
index f11fb7ed304b68fb6247fbef0f8cce98d7240773..bb173a21c2d4584f7b9015eb1c832ba7d63d86dc 100644 (file)
@@ -7,70 +7,89 @@ package time
 import "errors"
 
 // These are predefined layouts for use in Time.Format and time.Parse.
-// The reference time used in the layouts is the specific time:
-//     Mon Jan 2 15:04:05 MST 2006
-// which is Unix time 1136239445. Since MST is GMT-0700,
-// the reference time can be thought of as
+// The reference time used in these layouts is the specific time stamp:
 //     01/02 03:04:05PM '06 -0700
-// To define your own format, write down what the reference time would look
-// like formatted your way; see the values of constants like ANSIC,
-// StampMicro or Kitchen for examples. The model is to demonstrate what the
-// reference time looks like so that the Format and Parse methods can apply
-// the same transformation to a general time value.
+// (January 2, 15:04:05, 2006, in time zone seven hours west of GMT).
+// That value is recorded as the constant named Layout, listed below. As a Unix
+// time, this is 1136239445. Since MST is GMT-0700, the reference would be
+// printed by the Unix date command as:
+//     Mon Jan 2 15:04:05 MST 2006
+// It is a regrettable historic error that the date uses the American convention
+// of putting the numerical month before the day.
 //
-// Some valid layouts are invalid time values for time.Parse, due to formats
-// such as _ for space padding and Z for zone information.
+// The example for Time.Format demonstrates the working of the layout string
+// in detail and is a good reference.
 //
-// Within the format string, an underscore _ represents a space that may be
-// replaced by a digit if the following number (a day) has two digits; for
-// compatibility with fixed-width Unix time formats.
+// Note that the RFC822, RFC850, and RFC1123 formats should be applied
+// only to local times. Applying them to UTC times will use "UTC" as the
+// time zone abbreviation, while strictly speaking those RFCs require the
+// use of "GMT" in that case.
+// In general RFC1123Z should be used instead of RFC1123 for servers
+// that insist on that format, and RFC3339 should be preferred for new protocols.
+// RFC3339, RFC822, RFC822Z, RFC1123, and RFC1123Z are useful for formatting;
+// when used with time.Parse they do not accept all the time formats
+// permitted by the RFCs and they do accept time formats not formally defined.
+// The RFC3339Nano format removes trailing zeros from the seconds field
+// and thus may not sort correctly once formatted.
 //
-// A decimal point followed by one or more zeros represents a fractional
-// second, printed to the given number of decimal places. A decimal point
-// followed by one or more nines represents a fractional second, printed to
-// the given number of decimal places, with trailing zeros removed.
-// When parsing (only), the input may contain a fractional second
-// field immediately after the seconds field, even if the layout does not
-// signify its presence. In that case a decimal point followed by a maximal
-// series of digits is parsed as a fractional second.
+// Most programs can use one of the defined constants as the layout passed to
+// Format or Parse. The rest of this comment can be ignored unless you are
+// creating a custom layout string.
+//
+// To define your own format, write down what the reference time would look like
+// formatted your way; see the values of constants like ANSIC, StampMicro or
+// Kitchen for examples. The model is to demonstrate what the reference time
+// looks like so that the Format and Parse methods can apply the same
+// transformation to a general time value.
+//
+// Here is a summary of the components of a layout string. Each element shows by
+// example the formatting of an element of the reference time. Only these values
+// are recognized. Text in the layout string that is not recognized as part of
+// the reference time is echoed verbatim during Format and expected to appear
+// verbatim in the input to Parse.
+//
+//     Year: "2006" "06"
+//     Month: "Jan" "January"
+//     Textual day of the week: "Mon" "Monday"
+//     Numeric day of the month: "2" "_2" "02"
+//     Numeric day of the year: "__2" "002"
+//     Hour: "15" "3" "03" (PM or AM)
+//     Minute: "4" "04"
+//     Second: "5" "05"
+//     AM/PM mark: "PM"
 //
 // Numeric time zone offsets format as follows:
-//     -0700  ±hhmm
-//     -07:00 ±hh:mm
-//     -07    ±hh
+//     "-0700"  ±hhmm
+//     "-07:00" ±hh:mm
+//     "-07"    ±hh
 // Replacing the sign in the format with a Z triggers
 // the ISO 8601 behavior of printing Z instead of an
 // offset for the UTC zone. Thus:
-//     Z0700  Z or ±hhmm
-//     Z07:00 Z or ±hh:mm
-//     Z07    Z or ±hh
+//     "Z0700"  Z or ±hhmm
+//     "Z07:00" Z or ±hh:mm
+//     "Z07"    Z or ±hh
 //
-// The recognized day of week formats are "Mon" and "Monday".
-// The recognized month formats are "Jan" and "January".
+// Within the format string, the underscores in "_2" and "__2" represent spaces
+// that may be replaced by digits if the following number has multiple digits,
+// for compatibility with fixed-width Unix time formats. A leading zero represents
+// a zero-padded value.
 //
-// The formats 2, _2, and 02 are unpadded, space-padded, and zero-padded
-// day of month. The formats __2 and 002 are space-padded and zero-padded
+// The formats  and 002 are space-padded and zero-padded
 // three-character day of year; there is no unpadded day of year format.
 //
-// Text in the format string that is not recognized as part of the reference
-// time is echoed verbatim during Format and expected to appear verbatim
-// in the input to Parse.
+// A decimal point followed by one or more zeros represents a fractional
+// second, printed to the given number of decimal places.
+// Either a comma or decimal point followed by one or more nines represents
+// a fractional second, printed to the given number of decimal places, with
+// trailing zeros removed.
+// For example "15:04:05,000" or "15:04:05.000" formats or parses with
+// millisecond precision.
 //
-// The executable example for Time.Format demonstrates the working
-// of the layout string in detail and is a good reference.
+// Some valid layouts are invalid time values for time.Parse, due to formats
+// such as _ for space padding and Z for zone information.
 //
-// Note that the RFC822, RFC850, and RFC1123 formats should be applied
-// only to local times. Applying them to UTC times will use "UTC" as the
-// time zone abbreviation, while strictly speaking those RFCs require the
-// use of "GMT" in that case.
-// In general RFC1123Z should be used instead of RFC1123 for servers
-// that insist on that format, and RFC3339 should be preferred for new protocols.
-// RFC3339, RFC822, RFC822Z, RFC1123, and RFC1123Z are useful for formatting;
-// when used with time.Parse they do not accept all the time formats
-// permitted by the RFCs and they do accept time formats not formally defined.
-// The RFC3339Nano format removes trailing zeros from the seconds field
-// and thus may not sort correctly once formatted.
 const (
+       Layout      = "01/02 03:04:05PM '06 -0700" // The reference time, in numerical order.
        ANSIC       = "Mon Jan _2 15:04:05 2006"
        UnixDate    = "Mon Jan _2 15:04:05 MST 2006"
        RubyDate    = "Mon Jan 02 15:04:05 -0700 2006"
@@ -261,7 +280,7 @@ func nextStdChunk(layout string) (prefix string, std int, suffix string) {
                                return layout[0:i], stdISO8601ShortTZ, layout[i+3:]
                        }
 
-               case '.': // .000 or .999 - repeated digits for fractional seconds.
+               case '.', ',': // ,000, or .000, or ,999, or .999 - repeated digits for fractional seconds.
                        if i+1 < len(layout) && (layout[i+1] == '0' || layout[i+1] == '9') {
                                ch := layout[i+1]
                                j := i + 1
@@ -476,22 +495,66 @@ func (t Time) String() string {
        return s
 }
 
-// Format returns a textual representation of the time value formatted
-// according to layout, which defines the format by showing how the reference
-// time, defined to be
-//     Mon Jan 2 15:04:05 -0700 MST 2006
-// would be displayed if it were the value; it serves as an example of the
-// desired output. The same display rules will then be applied to the time
-// value.
-//
-// A fractional second is represented by adding a period and zeros
-// to the end of the seconds section of layout string, as in "15:04:05.000"
-// to format a time stamp with millisecond precision.
+// GoString implements fmt.GoStringer and formats t to be printed in Go source
+// code.
+func (t Time) GoString() string {
+       buf := []byte("time.Date(")
+       buf = appendInt(buf, t.Year(), 0)
+       month := t.Month()
+       if January <= month && month <= December {
+               buf = append(buf, ", time."...)
+               buf = append(buf, t.Month().String()...)
+       } else {
+               // It's difficult to construct a time.Time with a date outside the
+               // standard range but we might as well try to handle the case.
+               buf = appendInt(buf, int(month), 0)
+       }
+       buf = append(buf, ", "...)
+       buf = appendInt(buf, t.Day(), 0)
+       buf = append(buf, ", "...)
+       buf = appendInt(buf, t.Hour(), 0)
+       buf = append(buf, ", "...)
+       buf = appendInt(buf, t.Minute(), 0)
+       buf = append(buf, ", "...)
+       buf = appendInt(buf, t.Second(), 0)
+       buf = append(buf, ", "...)
+       buf = appendInt(buf, t.Nanosecond(), 0)
+       buf = append(buf, ", "...)
+       switch loc := t.Location(); loc {
+       case UTC, nil:
+               buf = append(buf, "time.UTC"...)
+       case Local:
+               buf = append(buf, "time.Local"...)
+       default:
+               // there are several options for how we could display this, none of
+               // which are great:
+               //
+               // - use Location(loc.name), which is not technically valid syntax
+               // - use LoadLocation(loc.name), which will cause a syntax error when
+               // embedded and also would require us to escape the string without
+               // importing fmt or strconv
+               // - try to use FixedZone, which would also require escaping the name
+               // and would represent e.g. "America/Los_Angeles" daylight saving time
+               // shifts inaccurately
+               // - use the pointer format, which is no worse than you'd get with the
+               // old fmt.Sprintf("%#v", t) format.
+               //
+               // Of these, Location(loc.name) is the least disruptive. This is an edge
+               // case we hope not to hit too often.
+               buf = append(buf, `time.Location(`...)
+               buf = append(buf, []byte(quote(loc.name))...)
+               buf = append(buf, `)`...)
+       }
+       buf = append(buf, ')')
+       return string(buf)
+}
+
+// Format returns a textual representation of the time value formatted according
+// to the layout defined by the argument. See the documentation for the
+// constant called Layout to see how to represent the layout format.
 //
-// Predefined layouts ANSIC, UnixDate, RFC3339 and others describe standard
-// and convenient representations of the reference time. For more information
-// about the formats and the definition of the reference time, see the
-// documentation for ANSIC and the other constants defined by this package.
+// The executable example for Time.Format demonstrates the working
+// of the layout string in detail and is a good reference.
 func (t Time) Format(layout string) string {
        const bufSize = 64
        var b []byte
@@ -686,8 +749,48 @@ type ParseError struct {
        Message    string
 }
 
+// These are borrowed from unicode/utf8 and strconv and replicate behavior in
+// that package, since we can't take a dependency on either.
+const (
+       lowerhex  = "0123456789abcdef"
+       runeSelf  = 0x80
+       runeError = '\uFFFD'
+)
+
 func quote(s string) string {
-       return "\"" + s + "\""
+       buf := make([]byte, 1, len(s)+2) // slice will be at least len(s) + quotes
+       buf[0] = '"'
+       for i, c := range s {
+               if c >= runeSelf || c < ' ' {
+                       // This means you are asking us to parse a time.Duration or
+                       // time.Location with unprintable or non-ASCII characters in it.
+                       // We don't expect to hit this case very often. We could try to
+                       // reproduce strconv.Quote's behavior with full fidelity but
+                       // given how rarely we expect to hit these edge cases, speed and
+                       // conciseness are better.
+                       var width int
+                       if c == runeError {
+                               width = 1
+                               if i+2 < len(s) && s[i:i+3] == string(runeError) {
+                                       width = 3
+                               }
+                       } else {
+                               width = len(string(c))
+                       }
+                       for j := 0; j < width; j++ {
+                               buf = append(buf, `\x`...)
+                               buf = append(buf, lowerhex[s[i+j]>>4])
+                               buf = append(buf, lowerhex[s[i+j]&0xF])
+                       }
+               } else {
+                       if c == '"' || c == '\\' {
+                               buf = append(buf, '\\')
+                       }
+                       buf = append(buf, string(c)...)
+               }
+       }
+       buf = append(buf, '"')
+       return string(buf)
 }
 
 // Error returns the string representation of a ParseError.
@@ -771,21 +874,19 @@ func skip(value, prefix string) (string, error) {
 }
 
 // Parse parses a formatted string and returns the time value it represents.
-// The layout defines the format by showing how the reference time,
-// defined to be
-//     Mon Jan 2 15:04:05 -0700 MST 2006
-// would be interpreted if it were the value; it serves as an example of
-// the input format. The same interpretation will then be made to the
-// input string.
+// See the documentation for the constant called Layout to see how to
+// represent the format. The second argument must be parseable using
+// the format string (layout) provided as the first argument.
 //
-// Predefined layouts ANSIC, UnixDate, RFC3339 and others describe standard
-// and convenient representations of the reference time. For more information
-// about the formats and the definition of the reference time, see the
-// documentation for ANSIC and the other constants defined by this package.
-// Also, the executable example for Time.Format demonstrates the working
-// of the layout string in detail and is a good reference.
+// The example for Time.Format demonstrates the working of the layout string
+// in detail and is a good reference.
+//
+// When parsing (only), the input may contain a fractional second
+// field immediately after the seconds field, even if the layout does not
+// signify its presence. In that case either a comma or a decimal point
+// followed by a maximal series of digits is parsed as a fractional second.
 //
-// Elements omitted from the value are assumed to be zero or, when
+// Elements omitted from the layout are assumed to be zero or, when
 // zero is impossible, one, so parsing "3:04pm" returns the time
 // corresponding to Jan 1, year 0, 15:04:00 UTC (note that because the year is
 // 0, this time is before the zero Time).
@@ -795,6 +896,8 @@ func skip(value, prefix string) (string, error) {
 // For layouts specifying the two-digit year 06, a value NN >= 69 will be treated
 // as 19NN and a value NN < 69 will be treated as 20NN.
 //
+// The remainder of this comment describes the handling of time zones.
+//
 // In the absence of a time zone indicator, Parse returns a time in UTC.
 //
 // When parsing a time with a zone offset like -0700, if the offset corresponds
@@ -940,7 +1043,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
                        }
                        // Special case: do we have a fractional second but no
                        // fractional second in the format?
-                       if len(value) >= 2 && value[0] == '.' && isDigit(value, 1) {
+                       if len(value) >= 2 && commaOrPeriod(value[0]) && isDigit(value, 1) {
                                _, std, _ = nextStdChunk(layout)
                                std &= stdMask
                                if std == stdFracSecond0 || std == stdFracSecond9 {
@@ -1070,7 +1173,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
                        value = value[ndigit:]
 
                case stdFracSecond9:
-                       if len(value) < 2 || value[0] != '.' || value[1] < '0' || '9' < value[1] {
+                       if len(value) < 2 || !commaOrPeriod(value[0]) || value[1] < '0' || '9' < value[1] {
                                // Fractional second omitted.
                                break
                        }
@@ -1152,7 +1255,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
 
                // Look for local zone with the given offset.
                // If that zone was in effect at the given time, use it.
-               name, offset, _, _ := local.lookup(t.unixSec())
+               name, offset, _, _, _ := local.lookup(t.unixSec())
                if offset == zoneOffset && (zoneName == "" || name == zoneName) {
                        t.setLoc(local)
                        return t, nil
@@ -1279,8 +1382,12 @@ func parseSignedOffset(value string) int {
        return len(value) - len(rem)
 }
 
+func commaOrPeriod(b byte) bool {
+       return b == '.' || b == ','
+}
+
 func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, err error) {
-       if value[0] != '.' {
+       if !commaOrPeriod(value[0]) {
                err = errBad
                return
        }
index 676117c4386f229b8bea68eafdda2f0cf1a42b4b..eda5fde7a36e737f3624e6e3585cbf49b6127136 100644 (file)
@@ -129,6 +129,31 @@ func TestFormat(t *testing.T) {
        }
 }
 
+var goStringTests = []struct {
+       in   Time
+       want string
+}{
+       {Date(2009, February, 5, 5, 0, 57, 12345600, UTC),
+               "time.Date(2009, time.February, 5, 5, 0, 57, 12345600, time.UTC)"},
+       {Date(2009, February, 5, 5, 0, 57, 12345600, Local),
+               "time.Date(2009, time.February, 5, 5, 0, 57, 12345600, time.Local)"},
+       {Date(2009, February, 5, 5, 0, 57, 12345600, FixedZone("Europe/Berlin", 3*60*60)),
+               `time.Date(2009, time.February, 5, 5, 0, 57, 12345600, time.Location("Europe/Berlin"))`,
+       },
+       {Date(2009, February, 5, 5, 0, 57, 12345600, FixedZone("Non-ASCII character ⏰", 3*60*60)),
+               `time.Date(2009, time.February, 5, 5, 0, 57, 12345600, time.Location("Non-ASCII character \xe2\x8f\xb0"))`,
+       },
+}
+
+func TestGoString(t *testing.T) {
+       // The numeric time represents Thu Feb  4 21:00:57.012345600 PST 2009
+       for _, tt := range goStringTests {
+               if tt.in.GoString() != tt.want {
+                       t.Errorf("GoString (%q): got %q want %q", tt.in, tt.in.GoString(), tt.want)
+               }
+       }
+}
+
 // issue 12440.
 func TestFormatSingleDigits(t *testing.T) {
        time := Date(2001, 2, 3, 4, 5, 6, 700000000, UTC)
@@ -207,9 +232,13 @@ var parseTests = []ParseTest{
        {"ANSIC", ANSIC, "THU FEB 4 21:00:57 2010", false, true, 1, 0},
        {"ANSIC", ANSIC, "thu feb 4 21:00:57 2010", false, true, 1, 0},
        // Fractional seconds.
-       {"millisecond", "Mon Jan _2 15:04:05.000 2006", "Thu Feb  4 21:00:57.012 2010", false, true, 1, 3},
-       {"microsecond", "Mon Jan _2 15:04:05.000000 2006", "Thu Feb  4 21:00:57.012345 2010", false, true, 1, 6},
-       {"nanosecond", "Mon Jan _2 15:04:05.000000000 2006", "Thu Feb  4 21:00:57.012345678 2010", false, true, 1, 9},
+       {"millisecond:: dot separator", "Mon Jan _2 15:04:05.000 2006", "Thu Feb  4 21:00:57.012 2010", false, true, 1, 3},
+       {"microsecond:: dot separator", "Mon Jan _2 15:04:05.000000 2006", "Thu Feb  4 21:00:57.012345 2010", false, true, 1, 6},
+       {"nanosecond:: dot separator", "Mon Jan _2 15:04:05.000000000 2006", "Thu Feb  4 21:00:57.012345678 2010", false, true, 1, 9},
+       {"millisecond:: comma separator", "Mon Jan _2 15:04:05,000 2006", "Thu Feb  4 21:00:57.012 2010", false, true, 1, 3},
+       {"microsecond:: comma separator", "Mon Jan _2 15:04:05,000000 2006", "Thu Feb  4 21:00:57.012345 2010", false, true, 1, 6},
+       {"nanosecond:: comma separator", "Mon Jan _2 15:04:05,000000000 2006", "Thu Feb  4 21:00:57.012345678 2010", false, true, 1, 9},
+
        // Leading zeros in other places should not be taken as fractional seconds.
        {"zero1", "2006.01.02.15.04.05.0", "2010.02.04.21.00.57.0", false, false, 1, 1},
        {"zero2", "2006.01.02.15.04.05.00", "2010.02.04.21.00.57.01", false, false, 1, 2},
@@ -222,12 +251,20 @@ var parseTests = []ParseTest{
        // Accept any number of fractional second digits (including none) for .999...
        // In Go 1, .999... was completely ignored in the format, meaning the first two
        // cases would succeed, but the next four would not. Go 1.1 accepts all six.
+       // decimal "." separator.
        {"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57 -0800 PST", true, false, 1, 0},
        {"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57 -0800 PST", true, false, 1, 0},
        {"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57.0123 -0800 PST", true, false, 1, 4},
        {"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57.0123 -0800 PST", true, false, 1, 4},
        {"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57.012345678 -0800 PST", true, false, 1, 9},
        {"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57.012345678 -0800 PST", true, false, 1, 9},
+       // comma "," separator.
+       {"", "2006-01-02 15:04:05,9999 -0700 MST", "2010-02-04 21:00:57 -0800 PST", true, false, 1, 0},
+       {"", "2006-01-02 15:04:05,999999999 -0700 MST", "2010-02-04 21:00:57 -0800 PST", true, false, 1, 0},
+       {"", "2006-01-02 15:04:05,9999 -0700 MST", "2010-02-04 21:00:57.0123 -0800 PST", true, false, 1, 4},
+       {"", "2006-01-02 15:04:05,999999999 -0700 MST", "2010-02-04 21:00:57.0123 -0800 PST", true, false, 1, 4},
+       {"", "2006-01-02 15:04:05,9999 -0700 MST", "2010-02-04 21:00:57.012345678 -0800 PST", true, false, 1, 9},
+       {"", "2006-01-02 15:04:05,999999999 -0700 MST", "2010-02-04 21:00:57.012345678 -0800 PST", true, false, 1, 9},
 
        // issue 4502.
        {"", StampNano, "Feb  4 21:00:57.012345678", false, false, -1, 9},
@@ -553,6 +590,10 @@ var parseErrorTests = []ParseErrorTest{
        // invalid or mismatched day-of-year
        {"Jan _2 002 2006", "Feb  4 034 2006", "day-of-year does not match day"},
        {"Jan _2 002 2006", "Feb  4 004 2006", "day-of-year does not match month"},
+
+       // issue 45391.
+       {`"2006-01-02T15:04:05Z07:00"`, "0", `parsing time "0" as "\"2006-01-02T15:04:05Z07:00\"": cannot parse "0" as "\""`},
+       {RFC3339, "\"", `parsing time "\"" as "2006-01-02T15:04:05Z07:00": cannot parse "\"" as "2006"`},
 }
 
 func TestParseErrors(t *testing.T) {
@@ -772,3 +813,24 @@ func TestParseYday(t *testing.T) {
                }
        }
 }
+
+// Issue 45391.
+func TestQuote(t *testing.T) {
+       tests := []struct {
+               s, want string
+       }{
+               {`"`, `"\""`},
+               {`abc"xyz"`, `"abc\"xyz\""`},
+               {"", `""`},
+               {"abc", `"abc"`},
+               {`☺`, `"\xe2\x98\xba"`},
+               {`☺ hello ☺ hello`, `"\xe2\x98\xba hello \xe2\x98\xba hello"`},
+               {"\x04", `"\x04"`},
+       }
+       for _, tt := range tests {
+               if q := Quote(tt.s); q != tt.want {
+                       t.Errorf("Quote(%q) = got %q, want %q", tt.s, q, tt.want)
+               }
+       }
+
+}
index 9825e705d24dc6e620c28ae4271893a0051b2b4d..9fd2f2b7626ea68170e1bd0bf16f32c438d79e22 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 //
index 362ce4919c1219ae50edaa36804d528874c3d249..93942d27b4a8a8293a9d07b3931606f51efe349e 100644 (file)
@@ -67,4 +67,6 @@ func CheckRuntimeTimerPeriodOverflow() {
 var (
        MinMonoTime = Time{wall: 1 << 63, ext: -1 << 63, loc: UTC}
        MaxMonoTime = Time{wall: 1 << 63, ext: 1<<63 - 1, loc: UTC}
+
+       NotMonoNegativeTime = Time{wall: 0, ext: -1<<63 + 50}
 )
index fb66e70c5faa5dd5a9209b271fa0d687d354e2ba..2c8db0aa7b8f7e78b50e30da6310f5b626232685 100644 (file)
@@ -528,6 +528,40 @@ func TestZeroTimer(t *testing.T) {
        }
 }
 
+// Test that rapidly moving a timer earlier doesn't cause it to get dropped.
+// Issue 47329.
+func TestTimerModifiedEarlier(t *testing.T) {
+       past := Until(Unix(0, 0))
+       count := 1000
+       fail := 0
+       for i := 0; i < count; i++ {
+               timer := NewTimer(Hour)
+               for j := 0; j < 10; j++ {
+                       if !timer.Stop() {
+                               <-timer.C
+                       }
+                       timer.Reset(past)
+               }
+
+               deadline := NewTimer(10 * Second)
+               defer deadline.Stop()
+               now := Now()
+               select {
+               case <-timer.C:
+                       if since := Since(now); since > 8*Second {
+                               t.Errorf("timer took too long (%v)", since)
+                               fail++
+                       }
+               case <-deadline.C:
+                       t.Error("deadline expired")
+               }
+       }
+
+       if fail > 0 {
+               t.Errorf("%d failures", fail)
+       }
+}
+
 // Benchmark timer latency when the thread that creates the timer is busy with
 // other work and the timers must be serviced by other threads.
 // https://golang.org/issue/38860
index b7fba0802c2b717fa30d33fa30c5d04a7cf4b80c..4dc55e44aa5fb6a92ad1b7b28db4ea27b83d4549 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build plan9
 // +build plan9
 
 package time
index ec98d6e6f39db4113f032df70e99beca6b410d61..b9f8c766d6cfd3ba8b88356b6171ce5f8f6b8348 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris
 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris
 
 package time
diff --git a/libgo/go/time/testdata/2020b_Europe_Berlin b/libgo/go/time/testdata/2020b_Europe_Berlin
new file mode 100644 (file)
index 0000000..465546b
Binary files /dev/null and b/libgo/go/time/testdata/2020b_Europe_Berlin differ
diff --git a/libgo/go/time/testdata/2021a_America_Nuuk b/libgo/go/time/testdata/2021a_America_Nuuk
new file mode 100644 (file)
index 0000000..4ddc99d
Binary files /dev/null and b/libgo/go/time/testdata/2021a_America_Nuuk differ
diff --git a/libgo/go/time/testdata/2021a_Asia_Gaza b/libgo/go/time/testdata/2021a_Asia_Gaza
new file mode 100644 (file)
index 0000000..58e9fdf
Binary files /dev/null and b/libgo/go/time/testdata/2021a_Asia_Gaza differ
diff --git a/libgo/go/time/testdata/2021a_Europe_Dublin b/libgo/go/time/testdata/2021a_Europe_Dublin
new file mode 100644 (file)
index 0000000..4a45ea8
Binary files /dev/null and b/libgo/go/time/testdata/2021a_Europe_Dublin differ
index 9a1cdf9ab2eaa57b619a6e697767c2cb98c32a51..b5d0a189bc84045782f5d190af1b5b5b15a0afca 100644 (file)
@@ -52,9 +52,14 @@ func TestTicker(t *testing.T) {
                t1 := Now()
                dt := t1.Sub(t0)
                target := 3 * delta * Duration(count/2)
-               slop := target * 2 / 10
+               slop := target * 3 / 10
                if dt < target-slop || dt > target+slop {
-                       errs = append(errs, fmt.Sprintf("%d %s ticks took %s, expected [%s,%s]", count, delta, dt, target-slop, target+slop))
+                       errs = append(errs, fmt.Sprintf("%d %s ticks then %d %s ticks took %s, expected [%s,%s]", count/2, delta, count/2, delta*2, dt, target-slop, target+slop))
+                       if dt > target+slop {
+                               // System may be overloaded; sleep a bit
+                               // in the hopes it will recover.
+                               Sleep(Second / 2)
+                       }
                        continue
                }
                // Now test that the ticker stopped.
index 8ae62308e5b22540a0a20ef0d5108063890865ca..4ecc3d82dcc95895742e6219c95503c994722c0f 100644 (file)
@@ -189,8 +189,15 @@ func (t *Time) addSec(d int64) {
                t.stripMono()
        }
 
-       // TODO: Check for overflow.
-       t.ext += d
+       // Check if the sum of t.ext and d overflows and handle it properly.
+       sum := t.ext + d
+       if (sum > t.ext) == (d > 0) {
+               t.ext = sum
+       } else if d > 0 {
+               t.ext = 1<<63 - 1
+       } else {
+               t.ext = -(1<<63 - 1)
+       }
 }
 
 // setLoc sets the location associated with the time.
@@ -440,7 +447,7 @@ func (t Time) abs() uint64 {
                if l.cacheZone != nil && l.cacheStart <= sec && sec < l.cacheEnd {
                        sec += int64(l.cacheZone.offset)
                } else {
-                       _, offset, _, _ := l.lookup(sec)
+                       _, offset, _, _, _ := l.lookup(sec)
                        sec += int64(offset)
                }
        }
@@ -461,7 +468,7 @@ func (t Time) locabs() (name string, offset int, abs uint64) {
                        name = l.cacheZone.name
                        offset = l.cacheZone.offset
                } else {
-                       name, offset, _, _ = l.lookup(sec)
+                       name, offset, _, _, _ = l.lookup(sec)
                }
                sec += int64(offset)
        } else {
@@ -1114,7 +1121,7 @@ func (t Time) Location() *Location {
 // Zone computes the time zone in effect at time t, returning the abbreviated
 // name of the zone (such as "CET") and its offset in seconds east of UTC.
 func (t Time) Zone() (name string, offset int) {
-       name, offset, _, _ = t.loc.lookup(t.unixSec())
+       name, offset, _, _, _ = t.loc.lookup(t.unixSec())
        return
 }
 
@@ -1128,6 +1135,24 @@ func (t Time) Unix() int64 {
        return t.unixSec()
 }
 
+// UnixMilli returns t as a Unix time, the number of milliseconds elapsed since
+// January 1, 1970 UTC. The result is undefined if the Unix time in
+// milliseconds cannot be represented by an int64 (a date more than 292 million
+// years before or after 1970). The result does not depend on the
+// location associated with t.
+func (t Time) UnixMilli() int64 {
+       return t.unixSec()*1e3 + int64(t.nsec())/1e6
+}
+
+// UnixMicro returns t as a Unix time, the number of microseconds elapsed since
+// January 1, 1970 UTC. The result is undefined if the Unix time in
+// microseconds cannot be represented by an int64 (a date before year -290307 or
+// after year 294246). The result does not depend on the location associated
+// with t.
+func (t Time) UnixMicro() int64 {
+       return t.unixSec()*1e6 + int64(t.nsec())/1e3
+}
+
 // UnixNano returns t as a Unix time, the number of nanoseconds elapsed
 // since January 1, 1970 UTC. The result is undefined if the Unix time
 // in nanoseconds cannot be represented by an int64 (a date before the year
@@ -1212,7 +1237,7 @@ func (t *Time) UnmarshalBinary(data []byte) error {
 
        if offset == -1*60 {
                t.setLoc(&utcLoc)
-       } else if _, localoff, _, _ := Local.lookup(t.unixSec()); offset == localoff {
+       } else if _, localoff, _, _, _ := Local.lookup(t.unixSec()); offset == localoff {
                t.setLoc(Local)
        } else {
                t.setLoc(FixedZone("", offset))
@@ -1302,6 +1327,24 @@ func Unix(sec int64, nsec int64) Time {
        return unixTime(sec, int32(nsec))
 }
 
+// UnixMilli returns the local Time corresponding to the given Unix time,
+// msec milliseconds since January 1, 1970 UTC.
+func UnixMilli(msec int64) Time {
+       return Unix(msec/1e3, (msec%1e3)*1e6)
+}
+
+// UnixMicro returns the local Time corresponding to the given Unix time,
+// usec microseconds since January 1, 1970 UTC.
+func UnixMicro(usec int64) Time {
+       return Unix(usec/1e6, (usec%1e6)*1e3)
+}
+
+// IsDST reports whether the time in the configured location is in Daylight Savings Time.
+func (t Time) IsDST() bool {
+       _, _, _, _, isDST := t.loc.lookup(t.Unix())
+       return isDST
+}
+
 func isLeap(year int) bool {
        return year%4 == 0 && (year%100 != 0 || year%400 == 0)
 }
@@ -1377,13 +1420,13 @@ func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) T
        // The lookup function expects UTC, so we pass t in the
        // hope that it will not be too close to a zone transition,
        // and then adjust if it is.
-       _, offset, start, end := loc.lookup(unix)
+       _, offset, start, end, _ := loc.lookup(unix)
        if offset != 0 {
                switch utc := unix - int64(offset); {
                case utc < start:
-                       _, offset, _, _ = loc.lookup(start - 1)
+                       _, offset, _, _, _ = loc.lookup(start - 1)
                case utc >= end:
-                       _, offset, _, _ = loc.lookup(end)
+                       _, offset, _, _, _ = loc.lookup(end)
                }
                unix -= int64(offset)
        }
index 154198a1ce613fae0d38f7e496f741ec10b2689f..cea5f2d3f5acebcd18214e0167bf6a2a8de9f5d7 100644 (file)
@@ -202,6 +202,28 @@ func TestNanosecondsToUTCAndBack(t *testing.T) {
        }
 }
 
+func TestUnixMilli(t *testing.T) {
+       f := func(msec int64) bool {
+               t := UnixMilli(msec)
+               return t.UnixMilli() == msec
+       }
+       cfg := &quick.Config{MaxCount: 10000}
+       if err := quick.Check(f, cfg); err != nil {
+               t.Fatal(err)
+       }
+}
+
+func TestUnixMicro(t *testing.T) {
+       f := func(usec int64) bool {
+               t := UnixMicro(usec)
+               return t.UnixMicro() == usec
+       }
+       cfg := &quick.Config{MaxCount: 10000}
+       if err := quick.Check(f, cfg); err != nil {
+               t.Fatal(err)
+       }
+}
+
 // The time routines provide no way to get absolute time
 // (seconds since zero), but we need it to compute the right
 // answer for bizarre roundings like "to the nearest 3 ns".
@@ -895,6 +917,11 @@ var parseDurationErrorTests = []struct {
        {".s", `".s"`},
        {"+.s", `"+.s"`},
        {"1d", `"1d"`},
+       {"\x85\x85", `"\x85\x85"`},
+       {"\xffff", `"\xffff"`},
+       {"hello \xffff world", `"hello \xffff world"`},
+       {"\uFFFD", `"\xef\xbf\xbd"`},                                             // utf8.RuneError
+       {"\uFFFD hello \uFFFD world", `"\xef\xbf\xbd hello \xef\xbf\xbd world"`}, // utf8.RuneError
        // overflow
        {"9223372036854775810ns", `"9223372036854775810ns"`},
        {"9223372036854775808ns", `"9223372036854775808ns"`},
@@ -959,6 +986,8 @@ var mallocTest = []struct {
 }{
        {0, `time.Now()`, func() { t = Now() }},
        {0, `time.Now().UnixNano()`, func() { u = Now().UnixNano() }},
+       {0, `time.Now().UnixMilli()`, func() { u = Now().UnixMilli() }},
+       {0, `time.Now().UnixMicro()`, func() { u = Now().UnixMicro() }},
 }
 
 func TestCountMallocs(t *testing.T) {
@@ -1249,6 +1278,8 @@ var defaultLocTests = []struct {
 
        {"Unix", func(t1, t2 Time) bool { return t1.Unix() == t2.Unix() }},
        {"UnixNano", func(t1, t2 Time) bool { return t1.UnixNano() == t2.UnixNano() }},
+       {"UnixMilli", func(t1, t2 Time) bool { return t1.UnixMilli() == t2.UnixMilli() }},
+       {"UnixMicro", func(t1, t2 Time) bool { return t1.UnixMicro() == t2.UnixMicro() }},
 
        {"MarshalBinary", func(t1, t2 Time) bool {
                a1, b1 := t1.MarshalBinary()
@@ -1301,6 +1332,18 @@ func BenchmarkNowUnixNano(b *testing.B) {
        }
 }
 
+func BenchmarkNowUnixMilli(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               u = Now().UnixMilli()
+       }
+}
+
+func BenchmarkNowUnixMicro(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               u = Now().UnixMicro()
+       }
+}
+
 func BenchmarkFormat(b *testing.B) {
        t := Unix(1265346057, 0)
        for i := 0; i < b.N; i++ {
@@ -1465,3 +1508,64 @@ func TestConcurrentTimerResetStop(t *testing.T) {
        }
        wg.Wait()
 }
+
+func TestTimeIsDST(t *testing.T) {
+       ForceZipFileForTesting(true)
+       defer ForceZipFileForTesting(false)
+
+       tzWithDST, err := LoadLocation("Australia/Sydney")
+       if err != nil {
+               t.Fatalf("could not load tz 'Australia/Sydney': %v", err)
+       }
+       tzWithoutDST, err := LoadLocation("Australia/Brisbane")
+       if err != nil {
+               t.Fatalf("could not load tz 'Australia/Brisbane': %v", err)
+       }
+       tzFixed := FixedZone("FIXED_TIME", 12345)
+
+       tests := [...]struct {
+               time Time
+               want bool
+       }{
+               0: {Date(2009, 1, 1, 12, 0, 0, 0, UTC), false},
+               1: {Date(2009, 6, 1, 12, 0, 0, 0, UTC), false},
+               2: {Date(2009, 1, 1, 12, 0, 0, 0, tzWithDST), true},
+               3: {Date(2009, 6, 1, 12, 0, 0, 0, tzWithDST), false},
+               4: {Date(2009, 1, 1, 12, 0, 0, 0, tzWithoutDST), false},
+               5: {Date(2009, 6, 1, 12, 0, 0, 0, tzWithoutDST), false},
+               6: {Date(2009, 1, 1, 12, 0, 0, 0, tzFixed), false},
+               7: {Date(2009, 6, 1, 12, 0, 0, 0, tzFixed), false},
+       }
+
+       for i, tt := range tests {
+               got := tt.time.IsDST()
+               if got != tt.want {
+                       t.Errorf("#%d:: (%#v).IsDST()=%t, want %t", i, tt.time.Format(RFC3339), got, tt.want)
+               }
+       }
+}
+
+func TestTimeAddSecOverflow(t *testing.T) {
+       // Test it with positive delta.
+       var maxInt64 int64 = 1<<63 - 1
+       timeExt := maxInt64 - UnixToInternal - 50
+       notMonoTime := Unix(timeExt, 0)
+       for i := int64(0); i < 100; i++ {
+               sec := notMonoTime.Unix()
+               notMonoTime = notMonoTime.Add(Duration(i * 1e9))
+               if newSec := notMonoTime.Unix(); newSec != sec+i && newSec+UnixToInternal != maxInt64 {
+                       t.Fatalf("time ext: %d overflows with positive delta, overflow threshold: %d", newSec, maxInt64)
+               }
+       }
+
+       // Test it with negative delta.
+       maxInt64 = -maxInt64
+       notMonoTime = NotMonoNegativeTime
+       for i := int64(0); i > -100; i-- {
+               sec := notMonoTime.Unix()
+               notMonoTime = notMonoTime.Add(Duration(i * 1e9))
+               if newSec := notMonoTime.Unix(); newSec != sec+i && newSec+UnixToInternal != maxInt64 {
+                       t.Fatalf("time ext: %d overflows with positive delta, overflow threshold: %d", newSec, maxInt64)
+               }
+       }
+}
index 21357fbf1c5ef433fc69ce9008b28f02a6d764e8..64b5b1b22c234fcba7056e93ce9c72145a5e5c52 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ignore
 // +build ignore
 
 // This program generates zipdata.go from $GOROOT/lib/time/zoneinfo.zip.
index 57052338d0aaa5b2890d9eb0b39d3f71f2a24881..57aed03fec36cc5300913fc5c12b48febb6b4e3f 100644 (file)
@@ -121,7 +121,7 @@ func FixedZone(name string, offset int) *Location {
 // the start and end times bracketing sec when that zone is in effect,
 // the offset in seconds east of UTC (such as -5*60*60), and whether
 // the daylight savings is being observed at that time.
-func (l *Location) lookup(sec int64) (name string, offset int, start, end int64) {
+func (l *Location) lookup(sec int64) (name string, offset int, start, end int64, isDST bool) {
        l = l.get()
 
        if len(l.zone) == 0 {
@@ -129,6 +129,7 @@ func (l *Location) lookup(sec int64) (name string, offset int, start, end int64)
                offset = 0
                start = alpha
                end = omega
+               isDST = false
                return
        }
 
@@ -137,6 +138,7 @@ func (l *Location) lookup(sec int64) (name string, offset int, start, end int64)
                offset = zone.offset
                start = l.cacheStart
                end = l.cacheEnd
+               isDST = zone.isDST
                return
        }
 
@@ -150,6 +152,7 @@ func (l *Location) lookup(sec int64) (name string, offset int, start, end int64)
                } else {
                        end = omega
                }
+               isDST = zone.isDST
                return
        }
 
@@ -174,12 +177,13 @@ func (l *Location) lookup(sec int64) (name string, offset int, start, end int64)
        offset = zone.offset
        start = tx[lo].when
        // end = maintained during the search
+       isDST = zone.isDST
 
        // If we're at the end of the known zone transitions,
        // try the extend string.
        if lo == len(tx)-1 && l.extend != "" {
-               if ename, eoffset, estart, eend, _, ok := tzset(l.extend, end, sec); ok {
-                       return ename, eoffset, estart, eend
+               if ename, eoffset, estart, eend, eisDST, ok := tzset(l.extend, end, sec); ok {
+                       return ename, eoffset, estart, eend, eisDST
                }
        }
 
@@ -592,7 +596,7 @@ func (l *Location) lookupName(name string, unix int64) (offset int, ok bool) {
        for i := range l.zone {
                zone := &l.zone[i]
                if zone.name == name {
-                       nam, offset, _, _ := l.lookup(unix - int64(zone.offset))
+                       nam, offset, _, _, _ := l.lookup(unix - int64(zone.offset))
                        if nam == zone.name {
                                return offset, true
                        }
index 0f1e9334b5df5fc40ccdb4b82bad418db1cc3024..044691e13058520fdb290497731aa5db98a95b09 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build ios
 // +build ios
 
 package time
index 2d76a571f2178fec234e839a2802f205539846a0..8245614d2e15c158d16a1c805c80409539c5f43a 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build js && wasm
 // +build js,wasm
 
 package time
index a9b4f077856da30b875f6fa185209e18d50caa76..54dae17b3e52a23fbce2deeae8318f605c496250 100644 (file)
@@ -25,8 +25,7 @@ func TestEnvVarUsage(t *testing.T) {
        const testZoneinfo = "foo.zip"
        const env = "ZONEINFO"
 
-       defer os.Setenv(env, os.Getenv(env))
-       os.Setenv(env, testZoneinfo)
+       t.Setenv(env, testZoneinfo)
 
        // Result isn't important, we're testing the side effect of this command
        time.LoadLocation("Asia/Jerusalem")
@@ -50,8 +49,7 @@ func TestBadLocationErrMsg(t *testing.T) {
 func TestLoadLocationValidatesNames(t *testing.T) {
        time.ResetZoneinfoForTesting()
        const env = "ZONEINFO"
-       defer os.Setenv(env, os.Getenv(env))
-       os.Setenv(env, "")
+       t.Setenv(env, "")
 
        bad := []string{
                "/usr/foo/Foo",
@@ -191,7 +189,7 @@ func TestMalformedTZData(t *testing.T) {
 
 var slimTests = []struct {
        zoneName   string
-       tzData     string
+       fileName   string
        date       func(*time.Location) time.Time
        wantName   string
        wantOffset int
@@ -199,7 +197,7 @@ var slimTests = []struct {
        {
                // 2020b slim tzdata for Europe/Berlin.
                zoneName:   "Europe/Berlin",
-               tzData:     "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xffo\xa2a\xf8\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9b\xd5\xda\xf0\xff\xff\xff\xff\x9cٮ\x90\xff\xff\xff\xff\x9d\xa4\xb5\x90\xff\xff\xff\xff\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\xc8\tq\x90\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xffѶ\x96\x00\xff\xff\xff\xff\xd2X\xbe\x80\xff\xff\xff\xffҡO\x10\xff\xff\xff\xff\xd3c\x1b\x90\xff\xff\xff\xff\xd4K#\x90\xff\xff\xff\xff\xd59\xd1 \xff\xff\xff\xff\xd5g\xe7\x90\xff\xff\xff\xffըs\x00\xff\xff\xff\xff\xd6)\xb4\x10\xff\xff\xff\xff\xd7,\x1a\x10\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xd9\x02\xc1\x90\xff\xff\xff\xff\xd9\xe9x\x10\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#<E\x10\x00\x00\x00\x00$,6\x10\x00\x00\x00\x00%\x1c'\x10\x00\x00\x00\x00&\f\x18\x10\x00\x00\x00\x00'\x05C\x90\x00\x00\x00\x00'\xf54\x90\x00\x00\x00\x00(\xe5%\x90\x00\x00\x00\x00)\xd5\x16\x90\x00\x00\x00\x00*\xc5\a\x90\x00\x00\x00\x00+\xb4\xf8\x90\x00\x00\x00\x00,\xa4\xe9\x90\x00\x00\x00\x00-\x94ڐ\x00\x00\x00\x00.\x84ː\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000d\xad\x90\x00\x00\x00\x001]\xd9\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x03\x01\x02\x01\x02\x01\x03\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00\f\x88\x00\x00\x00\x00\x1c \x01\x04\x00\x00\x0e\x10\x00\t\x00\x00*0\x01\rLMT\x00CEST\x00CET\x00CEMT\x00\nCET-1CEST,M3.5.0,M10.5.0/3\n",
+               fileName:   "2020b_Europe_Berlin",
                date:       func(loc *time.Location) time.Time { return time.Date(2020, time.October, 29, 15, 30, 0, 0, loc) },
                wantName:   "CET",
                wantOffset: 3600,
@@ -207,7 +205,7 @@ var slimTests = []struct {
        {
                // 2021a slim tzdata for America/Nuuk.
                zoneName:   "America/Nuuk",
-               tzData:     "TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x9b\x80h\x00\x00\x00\x00\x00\x13M|P\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#<E\x10\x00\x00\x00\x00$,6\x10\x00\x00\x00\x00%\x1c'\x10\x00\x00\x00\x00&\f\x18\x10\x00\x00\x00\x00'\x05C\x90\x00\x00\x00\x00'\xf54\x90\x00\x00\x00\x00(\xe5%\x90\x00\x00\x00\x00)\xd5\x16\x90\x00\x00\x00\x00*\xc5\a\x90\x00\x00\x00\x00+\xb4\xf8\x90\x00\x00\x00\x00,\xa4\xe9\x90\x00\x00\x00\x00-\x94ڐ\x00\x00\x00\x00.\x84ː\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000d\xad\x90\x00\x00\x00\x001]\xd9\x10\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xffπ\x00\x00\xff\xff\xd5\xd0\x00\x04\xff\xff\xe3\xe0\x01\bLMT\x00-03\x00-02\x00\n<-03>3<-02>,M3.5.0/-2,M10.5.0/-1\n",
+               fileName:   "2021a_America_Nuuk",
                date:       func(loc *time.Location) time.Time { return time.Date(2020, time.October, 29, 15, 30, 0, 0, loc) },
                wantName:   "-03",
                wantOffset: -10800,
@@ -215,7 +213,7 @@ var slimTests = []struct {
        {
                // 2021a slim tzdata for Asia/Gaza.
                zoneName:   "Asia/Gaza",
-               tzData:     "TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00s\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xff}\xbdJ\xb0\xff\xff\xff\xff\xc8Y\xcf\x00\xff\xff\xff\xff\xc8\xfa\xa6\x00\xff\xff\xff\xff\xc98\x9c\x80\xff\xff\xff\xff\xcc\xe5\xeb\x80\xff\xff\xff\xffͬ\xfe\x00\xff\xff\xff\xff\xce\xc7\x1f\x00\xff\xff\xff\xffϏ\x83\x00\xff\xff\xff\xffЩ\xa4\x00\xff\xff\xff\xffф}\x00\xff\xff\xff\xffҊ׀\xff\xff\xff\xff\xd3e\xb0\x80\xff\xff\xff\xff\xd4l\v\x00\xff\xff\xff\xff\xe86c`\xff\xff\xff\xff\xe8\xf4-P\xff\xff\xff\xff\xea\v\xb9`\xff\xff\xff\xff\xea\xd5`\xd0\xff\xff\xff\xff\xeb\xec\xfa\xf0\xff\xff\xff\xff\xec\xb5m\x00\xff\xff\xff\xff\xed\xcf\u007f\xf0\xff\xff\xff\xff\xee\x97\xf2\x00\xff\xff\xff\xffﰳp\xff\xff\xff\xff\xf0y%\x80\xff\xff\xff\xff\xf1\x91\xe6\xf0\xff\xff\xff\xff\xf2ZY\x00\xff\xff\xff\xff\xf3s\x1ap\xff\xff\xff\xff\xf4;\x8c\x80\xff\xff\xff\xff\xf5U\x9fp\xff\xff\xff\xff\xf6\x1e\x11\x80\xff\xff\xff\xff\xf76\xd2\xf0\xff\xff\xff\xff\xf7\xffE\x00\xff\xff\xff\xff\xf9\x18\x06p\xff\xff\xff\xff\xf9\xe1\xca\x00\xff\xff\xff\xff\xfa\xf99\xf0\xff\xff\xff\xff\xfb'BP\x00\x00\x00\x00\b|\x8b\xe0\x00\x00\x00\x00\b\xfd\xb0\xd0\x00\x00\x00\x00\t\xf6\xea`\x00\x00\x00\x00\n\xa63\xd0\x00\x00\x00\x00\x13\xe9\xfc`\x00\x00\x00\x00\x14![`\x00\x00\x00\x00\x1a\xfa\xc6`\x00\x00\x00\x00\x1b\x8en`\x00\x00\x00\x00\x1c\xbe\xf8\xe0\x00\x00\x00\x00\x1dw|\xd0\x00\x00\x00\x00\x1e\xcc\xff`\x00\x00\x00\x00\x1f`\x99P\x00\x00\x00\x00 \x82\xb1`\x00\x00\x00\x00!I\xb5\xd0\x00\x00\x00\x00\"^\x9e\xe0\x00\x00\x00\x00# ]P\x00\x00\x00\x00$Z0`\x00\x00\x00\x00%\x00?P\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00&\xd6\xe6\xd0\x00\x00\x00\x00'\xeb\xcf\xe0\x00\x00\x00\x00(\xc0\x03P\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xa9\x1f\xd0\x00\x00\x00\x00+\xbbe\xe0\x00\x00\x00\x00,\x89\x01\xd0\x00\x00\x00\x00-\x9bG\xe0\x00\x00\x00\x00._\xa9P\x00\x00\x00\x00/{)\xe0\x00\x00\x00\x000H\xc5\xd0\x00\x00\x00\x000\xe7\a\xe0\x00\x00\x00\x001dF`\x00\x00\x00\x002A\xc2`\x00\x00\x00\x003D(`\x00\x00\x00\x004!\xa4`\x00\x00\x00\x005$\n`\x00\x00\x00\x006\x01\x86`\x00\x00\x00\x007\x16a`\x00\x00\x00\x008\x06DP\x00\x00\x00\x008\xff}\xe0\x00\x00\x00\x009\xef`\xd0\x00\x00\x00\x00:\xdf_\xe0\x00\x00\x00\x00;\xcfB\xd0\x00\x00\x00\x00<\xbfA\xe0\x00\x00\x00\x00=\xaf$\xd0\x00\x00\x00\x00>\x9f#\xe0\x00\x00\x00\x00?\x8f\x06\xd0\x00\x00\x00\x00@\u007f\x05\xe0\x00\x00\x00\x00A\\\x81\xe0\x00\x00\x00\x00B^\xe7\xe0\x00\x00\x00\x00CA\xb7\xf0\x00\x00\x00\x00D-\xa6`\x00\x00\x00\x00E\x12\xfdP\x00\x00\x00\x00F\x0e\xd9\xe0\x00\x00\x00\x00F\xe8op\x00\x00\x00\x00G\xec\x18\xe0\x00\x00\x00\x00H\xb7\x11\xd0\x00\x00\x00\x00I\xcb\xfa\xe0\x00\x00\x00\x00J\xa0<`\x00\x00\x00\x00K\xad.\x9c\x00\x00\x00\x00La\xbd\xd0\x00\x00\x00\x00M\x94\xf9\x9c\x00\x00\x00\x00N5\xc2P\x00\x00\x00\x00Ot\xdb`\x00\x00\x00\x00P[\x91\xe0\x00\x00\x00\x00QT\xbd`\x00\x00\x00\x00RD\xa0P\x00\x00\x00\x00S4\x9f`\x00\x00\x00\x00TIlP\x00\x00\x00\x00U\x15\xd2\xe0\x00\x00\x00\x00V)\\`\x00\x00\x00\x00V\xf5\xc2\xf0\x00\x00\x00\x00X\x13\xca`\x00\x00\x00\x00Xդ\xf0\x00\x00\x00\x00Y\xf3\xac`\x00\x00\x00\x00Z\xb5\x86\xf0\x00\x00\x00\x00[ӎ`\x00\x00\x00\x00\\\x9dC\xe0\x00\x00\x00\x00]\xb3bP\x00\x00\x00\x00^~w`\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00 P\x00\x00\x00\x00*0\x01\x04\x00\x00\x1c \x00\t\x00\x00*0\x01\r\x00\x00\x1c \x00\x11LMT\x00EEST\x00EET\x00IDT\x00IST\x00\nEET-2EEST,M3.4.4/48,M10.4.4/49\n",
+               fileName:   "2021a_Asia_Gaza",
                date:       func(loc *time.Location) time.Time { return time.Date(2020, time.October, 29, 15, 30, 0, 0, loc) },
                wantName:   "EET",
                wantOffset: 7200,
@@ -223,7 +221,7 @@ var slimTests = []struct {
        {
                // 2021a slim tzdata for Europe/Dublin.
                zoneName:   "Europe/Dublin",
-               tzData:     "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x91\x00\x00\x00\x08\x00\x00\x00\x14\xff\xff\xff\xffW\xd1\n\xdc\xff\xff\xff\xff\x9b&\xb3\x91\xff\xff\xff\xff\x9b\xd6\x0b\x11\xff\xff\xff\xff\x9c\xcf0\xa0\xff\xff\xff\xff\x9d\xa4\xc3\xa0\xff\xff\xff\xff\x9e\x9c\x9d\xa0\xff\xff\xff\xff\x9f\x97\x1a\xa0\xff\xff\xff\xff\xa0\x85\xba\x20\xff\xff\xff\xff\xa1v\xfc\xa0\xff\xff\xff\xff\xa2e\x9c\x20\xff\xff\xff\xff\xa3{\xc8\xa0\xff\xff\xff\xff\xa4N\xb8\xa0\xff\xff\xff\xff\xa5?\xfb\x20\xff\xff\xff\xff\xa6%`\x20\xff\xff\xff\xff\xa7'\xc6\x20\xff\xff\xff\xff\xa8*,\x20\xff\xff\xff\xff\xa8\xeb\xf8\xa0\xff\xff\xff\xff\xaa\x00\xd3\xa0\xff\xff\xff\xff\xaa\xd5\x15\x20\xff\xff\xff\xff\xab\xe9\xf0\x20\xff\xff\xff\xff\xac\xc7l\x20\xff\xff\xff\xff\xad\xc9\xd2\x20\xff\xff\xff\xff\xae\xa7N\x20\xff\xff\xff\xff\xaf\xa0y\xa0\xff\xff\xff\xff\xb0\x870\x20\xff\xff\xff\xff\xb1\x92\xd0\xa0\xff\xff\xff\xff\xb2pL\xa0\xff\xff\xff\xff\xb3r\xb2\xa0\xff\xff\xff\xff\xb4P.\xa0\xff\xff\xff\xff\xb5IZ\x20\xff\xff\xff\xff\xb60\x10\xa0\xff\xff\xff\xff\xb72v\xa0\xff\xff\xff\xff\xb8\x0f\xf2\xa0\xff\xff\xff\xff\xb9\x12X\xa0\xff\xff\xff\xff\xb9\xef\xd4\xa0\xff\xff\xff\xff\xba\xe9\x00\x20\xff\xff\xff\xff\xbb\xd8\xf1\x20\xff\xff\xff\xff\xbc\xdbW\x20\xff\xff\xff\xff\xbd\xb8\xd3\x20\xff\xff\xff\xff\xbe\xb1\xfe\xa0\xff\xff\xff\xff\xbf\x98\xb5\x20\xff\xff\xff\xff\xc0\x9b\x1b\x20\xff\xff\xff\xff\xc1x\x97\x20\xff\xff\xff\xff\xc2z\xfd\x20\xff\xff\xff\xff\xc3Xy\x20\xff\xff\xff\xff\xc4Q\xa4\xa0\xff\xff\xff\xff\xc58[\x20\xff\xff\xff\xff\xc6:\xc1\x20\xff\xff\xff\xff\xc7X\xd6\xa0\xff\xff\xff\xff\xc7\xda\x09\xa0\xff\xff\xff\xff\xd4I\xe0\x20\xff\xff\xff\xff\xd5\x1e!\xa0\xff\xff\xff\xff\xd6N\xac\x20\xff\xff\xff\xff\xd7,(\x20\xff\xff\xff\xff\xd8.\x8e\x20\xff\xff\xff\xff\xd8\xf9\x95\x20\xff\xff\xff\xff\xda\x0ep\x20\xff\xff\xff\xff\xda\xeb\xec\x20\xff\xff\xff\xff\xdb\xe5\x17\xa0\xff\xff\xff\xff\xdc\xcb\xce\x20\xff\xff\xff\xff\xdd\xc4\xf9\xa0\xff\xff\xff\xff\xde\xb4\xea\xa0\xff\xff\xff\xff\xdf\xae\x16\x20\xff\xff\xff\xff\xe0\x94\xcc\xa0\xff\xff\xff\xff\xe1rH\xa0\xff\xff\xff\xff\xe2kt\x20\xff\xff\xff\xff\xe3R*\xa0\xff\xff\xff\xff\xe4T\x90\xa0\xff\xff\xff\xff\xe52\x0c\xa0\xff\xff\xff\xff\xe6=\xad\x20\xff\xff\xff\xff\xe7\x1b)\x20\xff\xff\xff\xff\xe8\x14T\xa0\xff\xff\xff\xff\xe8\xfb\x0b\x20\xff\xff\xff\xff\xe9\xfdq\x20\xff\xff\xff\xff\xea\xda\xed\x20\xff\xff\xff\xff\xeb\xddS\x20\xff\xff\xff\xff\xec\xba\xcf\x20\xff\xff\xff\xff\xed\xb3\xfa\xa0\xff\xff\xff\xff\xee\x9a\xb1\x20\xff\xff\xff\xff\xef\x81g\xa0\xff\xff\xff\xff\xf0\x9f}\x20\xff\xff\xff\xff\xf1aI\xa0\xff\xff\xff\xff\xf2\x7f_\x20\xff\xff\xff\xff\xf3Jf\x20\xff\xff\xff\xff\xf4_A\x20\xff\xff\xff\xff\xf5!\x0d\xa0\xff\xff\xff\xff\xf6?#\x20\xff\xff\xff\xff\xf7\x00\xef\xa0\xff\xff\xff\xff\xf8\x1f\x05\x20\xff\xff\xff\xff\xf8\xe0\xd1\xa0\xff\xff\xff\xff\xf9\xfe\xe7\x20\xff\xff\xff\xff\xfa\xc0\xb3\xa0\xff\xff\xff\xff\xfb\xe8\x03\xa0\xff\xff\xff\xff\xfc{\xab\xa0\xff\xff\xff\xff\xfd\xc7\xbbp\x00\x00\x00\x00\x03p\xc6\x20\x00\x00\x00\x00\x04)X\x20\x00\x00\x00\x00\x05P\xa8\x20\x00\x00\x00\x00\x06\x09:\x20\x00\x00\x00\x00\x070\x8a\x20\x00\x00\x00\x00\x07\xe9\x1c\x20\x00\x00\x00\x00\x09\x10l\x20\x00\x00\x00\x00\x09\xc8\xfe\x20\x00\x00\x00\x00\n\xf0N\x20\x00\x00\x00\x00\x0b\xb2\x1a\xa0\x00\x00\x00\x00\x0c\xd00\x20\x00\x00\x00\x00\x0d\x91\xfc\xa0\x00\x00\x00\x00\x0e\xb0\x12\x20\x00\x00\x00\x00\x0fq\xde\xa0\x00\x00\x00\x00\x10\x99.\xa0\x00\x00\x00\x00\x11Q\xc0\xa0\x00\x00\x00\x00\x12y\x10\xa0\x00\x00\x00\x00\x131\xa2\xa0\x00\x00\x00\x00\x14X\xf2\xa0\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x168\xc6\x90\x00\x00\x00\x00\x17\x03\xcd\x90\x00\x00\x00\x00\x18\x18\xa8\x90\x00\x00\x00\x00\x18\xe3\xaf\x90\x00\x00\x00\x00\x19\xf8\x8a\x90\x00\x00\x00\x00\x1a\xc3\x91\x90\x00\x00\x00\x00\x1b\xe1\xa7\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\xc1\x89\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f\xa1k\x10\x00\x00\x00\x00\x20lr\x10\x00\x00\x00\x00!\x81M\x10\x00\x00\x00\x00\x22LT\x10\x00\x00\x00\x00#a/\x10\x00\x00\x00\x00$,6\x10\x00\x00\x00\x00%JK\x90\x00\x00\x00\x00&\x0c\x18\x10\x00\x00\x00\x00'*-\x90\x00\x00\x00\x00'\xf54\x90\x00\x00\x00\x00)\n\x0f\x90\x00\x00\x00\x00)\xd5\x16\x90\x00\x00\x00\x00*\xe9\xf1\x90\x00\x00\x00\x00+\xb4\xf8\x90\x00\x00\x00\x00,\xc9\xd3\x90\x00\x00\x00\x00-\x94\xda\x90\x00\x00\x00\x00.\xa9\xb5\x90\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000\x89\x97\x90\x00\x00\x00\x001]\xd9\x10\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\x06\x07\xff\xff\xfa$\x00\x00\xff\xff\xfa\x0f\x00\x04\x00\x00\x08\x1f\x01\x08\x00\x00\x0e\x10\x01\x0c\x00\x00\x00\x00\x00\x10\x00\x00\x0e\x10\x01\x08\x00\x00\x00\x00\x01\x10\x00\x00\x0e\x10\x00\x08LMT\x00DMT\x00IST\x00BST\x00GMT\x00\nIST-1GMT0,M10.5.0,M3.5.0/1\n",
+               fileName:   "2021a_Europe_Dublin",
                date:       func(loc *time.Location) time.Time { return time.Date(2021, time.April, 2, 11, 12, 13, 0, loc) },
                wantName:   "IST",
                wantOffset: 3600,
@@ -232,9 +230,15 @@ var slimTests = []struct {
 
 func TestLoadLocationFromTZDataSlim(t *testing.T) {
        for _, test := range slimTests {
-               reference, err := time.LoadLocationFromTZData(test.zoneName, []byte(test.tzData))
+               tzData, err := os.ReadFile("testdata/" + test.fileName)
                if err != nil {
-                       t.Fatal(err)
+                       t.Error(err)
+                       continue
+               }
+               reference, err := time.LoadLocationFromTZData(test.zoneName, tzData)
+               if err != nil {
+                       t.Error(err)
+                       continue
                }
 
                d := test.date(reference)
index 926f309c6b8533d741f4b201366504d80ee28448..6e2c08dc83bd12abf7f861220d769cf9456eb660 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || (darwin && !ios) || dragonfly || freebsd || hurd || (linux && !android) || netbsd || openbsd || solaris
 // +build aix darwin,!ios dragonfly freebsd hurd linux,!android netbsd openbsd solaris
 
 // Parse "zoneinfo" time zone file.
index f290ae754f1856044bf4a7f129f346ed3a479b58..b75b374c3d535123a0ef21e41af50d368d4ce403 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build aix || (darwin && !ios) || dragonfly || freebsd || (linux && !android) || netbsd || openbsd || solaris
 // +build aix darwin,!ios dragonfly freebsd linux,!android netbsd openbsd solaris
 
 package time_test
index a57566f0a527cf7132f52ea1bd99caf02087dfab..268e457a875311bb01b34a6d7e106bae1dde4428 100644 (file)
@@ -154,7 +154,8 @@ func is32(ranges []Range32, r uint32) bool {
 // Is reports whether the rune is in the specified table of ranges.
 func Is(rangeTab *RangeTable, r rune) bool {
        r16 := rangeTab.R16
-       if len(r16) > 0 && r <= rune(r16[len(r16)-1].Hi) {
+       // Compare as uint32 to correctly handle negative runes.
+       if len(r16) > 0 && uint32(r) <= uint32(r16[len(r16)-1].Hi) {
                return is16(r16, uint16(r))
        }
        r32 := rangeTab.R32
@@ -166,7 +167,8 @@ func Is(rangeTab *RangeTable, r rune) bool {
 
 func isExcludingLatin(rangeTab *RangeTable, r rune) bool {
        r16 := rangeTab.R16
-       if off := rangeTab.LatinOffset; len(r16) > off && r <= rune(r16[len(r16)-1].Hi) {
+       // Compare as uint32 to correctly handle negative runes.
+       if off := rangeTab.LatinOffset; len(r16) > off && uint32(r) <= uint32(r16[len(r16)-1].Hi) {
                return is16(r16[off:], uint16(r))
        }
        r32 := rangeTab.R32
index 19ee535d57e15e3dee16fa73cf1e368781f330d9..a91e3a326fd2903b0081697d9e8a15241bfc8e74 100644 (file)
@@ -563,3 +563,82 @@ func TestSpecialCaseNoMapping(t *testing.T) {
                t.Errorf("got %q; want %q", got, want)
        }
 }
+
+func TestNegativeRune(t *testing.T) {
+       // Issue 43254
+       // These tests cover negative rune handling by testing values which,
+       // when cast to uint8 or uint16, look like a particular valid rune.
+       // This package has Latin-1-specific optimizations, so we test all of
+       // Latin-1 and representative non-Latin-1 values in the character
+       // categories covered by IsGraphic, etc.
+       nonLatin1 := []uint32{
+               // Lu: LATIN CAPITAL LETTER A WITH MACRON
+               0x0100,
+               // Ll: LATIN SMALL LETTER A WITH MACRON
+               0x0101,
+               // Lt: LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON
+               0x01C5,
+               // M: COMBINING GRAVE ACCENT
+               0x0300,
+               // Nd: ARABIC-INDIC DIGIT ZERO
+               0x0660,
+               // P: GREEK QUESTION MARK
+               0x037E,
+               // S: MODIFIER LETTER LEFT ARROWHEAD
+               0x02C2,
+               // Z: OGHAM SPACE MARK
+               0x1680,
+       }
+       for i := 0; i < MaxLatin1+len(nonLatin1); i++ {
+               base := uint32(i)
+               if i >= MaxLatin1 {
+                       base = nonLatin1[i-MaxLatin1]
+               }
+
+               // Note r is negative, but uint8(r) == uint8(base) and
+               // uint16(r) == uint16(base).
+               r := rune(base - 1<<31)
+               if Is(Letter, r) {
+                       t.Errorf("Is(Letter, 0x%x - 1<<31) = true, want false", base)
+               }
+               if IsControl(r) {
+                       t.Errorf("IsControl(0x%x - 1<<31) = true, want false", base)
+               }
+               if IsDigit(r) {
+                       t.Errorf("IsDigit(0x%x - 1<<31) = true, want false", base)
+               }
+               if IsGraphic(r) {
+                       t.Errorf("IsGraphic(0x%x - 1<<31) = true, want false", base)
+               }
+               if IsLetter(r) {
+                       t.Errorf("IsLetter(0x%x - 1<<31) = true, want false", base)
+               }
+               if IsLower(r) {
+                       t.Errorf("IsLower(0x%x - 1<<31) = true, want false", base)
+               }
+               if IsMark(r) {
+                       t.Errorf("IsMark(0x%x - 1<<31) = true, want false", base)
+               }
+               if IsNumber(r) {
+                       t.Errorf("IsNumber(0x%x - 1<<31) = true, want false", base)
+               }
+               if IsPrint(r) {
+                       t.Errorf("IsPrint(0x%x - 1<<31) = true, want false", base)
+               }
+               if IsPunct(r) {
+                       t.Errorf("IsPunct(0x%x - 1<<31) = true, want false", base)
+               }
+               if IsSpace(r) {
+                       t.Errorf("IsSpace(0x%x - 1<<31) = true, want false", base)
+               }
+               if IsSymbol(r) {
+                       t.Errorf("IsSymbol(0x%x - 1<<31) = true, want false", base)
+               }
+               if IsTitle(r) {
+                       t.Errorf("IsTitle(0x%x - 1<<31) = true, want false", base)
+               }
+               if IsUpper(r) {
+                       t.Errorf("IsUpper(0x%x - 1<<31) = true, want false", base)
+               }
+       }
+}
index b18d36639a1426843acc678f626f21e995909c83..ff01db5cdc77fe99287db108845ae5403a729678 100644 (file)
@@ -1,5 +1,5 @@
-# golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
-## explicit
+# golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e
+## explicit; go 1.17
 golang.org/x/crypto/chacha20
 golang.org/x/crypto/chacha20poly1305
 golang.org/x/crypto/cryptobyte
@@ -8,8 +8,8 @@ golang.org/x/crypto/curve25519
 golang.org/x/crypto/hkdf
 golang.org/x/crypto/internal/subtle
 golang.org/x/crypto/poly1305
-# golang.org/x/net v0.0.0-20210428183300-3f4a416c7d3b
-## explicit
+# golang.org/x/net v0.0.0-20210510120150-4163338589ed
+## explicit; go 1.17
 golang.org/x/net/dns/dnsmessage
 golang.org/x/net/http/httpguts
 golang.org/x/net/http/httpproxy
@@ -18,11 +18,11 @@ golang.org/x/net/idna
 golang.org/x/net/lif
 golang.org/x/net/nettest
 golang.org/x/net/route
-# golang.org/x/sys v0.0.0-20201204225414-ed752295db88
-## explicit
+# golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744
+## explicit; go 1.17
 golang.org/x/sys/cpu
-# golang.org/x/text v0.3.4
-## explicit
+# golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f
+## explicit; go 1.17
 golang.org/x/text/secure/bidirule
 golang.org/x/text/transform
 golang.org/x/text/unicode/bidi
index a5b6217c931193f4cda5bac1f3577682b99035fc..977f318b34e02b7e05701f66b40be8d54041658a 100755 (executable)
@@ -39,6 +39,7 @@ maxalign=8
 minframesize=0
 pcquantum=1
 ptrsize=8
+stackalign=8
 
 case $goarch in
     386)
@@ -46,6 +47,7 @@ case $goarch in
        int64align=4
        maxalign=4
        ptrsize=4
+       stackalign=4
        ;;
     alpha)
        family=ALPHA
@@ -58,6 +60,7 @@ case $goarch in
     amd64p32)
        family=AMD64
        ptrsize=4
+       stackalign=4
        ;;
     arm | armbe)
        family=ARM
@@ -65,6 +68,7 @@ case $goarch in
        minframesize=4
        pcquantum=4
        ptrsize=4
+       stackalign=4
        case $goarch in
            *be)
                bigendian=true
@@ -77,6 +81,7 @@ case $goarch in
        defaultphyspagesize=65536
        minframesize=8
        pcquantum=4
+       stackalign=16
        case $goarch in
            *be)
                bigendian=true
@@ -96,6 +101,7 @@ case $goarch in
        maxalign=2
        pcquantum=4
        ptrsize=4
+       stackalign=4
        ;;
     mips | mipsle | mips64p32 | mips64p32le)
        family=MIPS
@@ -105,6 +111,7 @@ case $goarch in
        minframesize=4
        pcquantum=4
        ptrsize=4
+       stackalign=4
        case $goarch in
            *le)
                bigendian=false
@@ -130,6 +137,7 @@ case $goarch in
         minframesize=16
         pcquantum=4
         ptrsize=4
+       stackalign=4
         ;;
     ppc)
        family=PPC
@@ -138,6 +146,7 @@ case $goarch in
        minframesize=32
        pcquantum=4
        ptrsize=4
+       stackalign=4
        ;;
     ppc64 | ppc64le)
        family=PPC64
@@ -145,6 +154,7 @@ case $goarch in
        defaultphyspagesize=65536
        minframesize=32
        pcquantum=4
+       stackalign=16
        case $goarch in
            *le)
                bigendian=false
@@ -155,6 +165,7 @@ case $goarch in
        family=RISCV
        pcquantum=2
        ptrsize=4
+       stackalign=4
        ;;
     riscv64)
        family=RISCV64
@@ -167,6 +178,7 @@ case $goarch in
        minframesize=4
        pcquantum=2
        ptrsize=4
+       stackalign=4
        ;;
     s390x)
        family=S390X
@@ -182,6 +194,7 @@ case $goarch in
        minframesize=4
        pcquantum=2
        ptrsize=4
+       stackalign=4
        case $goarch in
            *be)
                bigendian=true
@@ -194,6 +207,7 @@ case $goarch in
        defaultphyspagesize=8192
        pcquantum=4
        ptrsize=4
+       stackalign=4
        ;;
     sparc64)
        family=SPARC64
@@ -244,6 +258,9 @@ case $keyword in
     ptrsize)
        echo $ptrsize
        ;;
+    stackalign)
+       echo $stackalign
+       ;;
     *)
        echo 1>&2 "unrecognized keyword \"$keyword\""
        exit 1
index f28ad6977aa88636618f24f0d4d59d1c408a8bdb..15c928ff7fb86676d279981916d77bf182a225a6 100644 (file)
@@ -27,7 +27,6 @@ cmd/go/internal/modinfo
 cmd/go/internal/modload
 cmd/go/internal/mvs
 cmd/go/internal/par
-cmd/go/internal/renameio
 cmd/go/internal/robustio
 cmd/go/internal/run
 cmd/go/internal/search
@@ -86,6 +85,7 @@ golang.org/x/tools/go/analysis/passes/nilfunc
 golang.org/x/tools/go/analysis/passes/pkgfact
 golang.org/x/tools/go/analysis/passes/printf
 golang.org/x/tools/go/analysis/passes/shift
+golang.org/x/tools/go/analysis/passes/sigchanyzer
 golang.org/x/tools/go/analysis/passes/stdmethods
 golang.org/x/tools/go/analysis/passes/stringintconv
 golang.org/x/tools/go/analysis/passes/structtag
index 707def56de700cebf0b8747d67e120c6461924f6..4fc8c843f0219012dc2db1fea1d62d636f533053 100644 (file)
@@ -19,7 +19,9 @@ crypto/dsa
 crypto/ecdsa
 crypto/ed25519
 crypto/ed25519/internal/edwards25519
+crypto/ed25519/internal/edwards25519/field
 crypto/elliptic
+crypto/elliptic/internal/fiat
 crypto/hmac
 crypto/internal/randutil
 crypto/internal/subtle
@@ -69,6 +71,7 @@ go/importer
 go/internal/gccgoimporter
 go/internal/gcimporter
 go/internal/srcimporter
+go/internal/typeparams
 go/parser
 go/printer
 go/scanner
@@ -110,13 +113,16 @@ image/internal/imageutil
 image/jpeg
 image/png
 index/suffixarray
+internal/buildcfg
 internal/bytealg
 internal/cfg
 internal/cpu
 internal/execabs
 internal/fmtsort
+internal/goexperiment
 internal/goroot
 internal/goversion
+internal/itoa
 internal/lazyregexp
 internal/lazytemplate
 internal/nettrace
@@ -157,6 +163,8 @@ net/http/httptest
 net/http/httptrace
 net/http/httputil
 net/http/internal
+net/http/internal/ascii
+net/http/internal/testcert
 net/http/pprof
 net/internal/socktest
 net/mail
@@ -173,9 +181,12 @@ os/user
 path
 path/filepath
 reflect
+reflect/internal/example1
+reflect/internal/example2
 regexp
 regexp/syntax
 runtime
+runtime/cgo
 runtime/debug
 runtime/internal/atomic
 runtime/internal/math
index cc15a12c6749f913fc8200087d0a671f4a9366f0..bf4f141e04a7ab87cb5a4fc0a146bc8c1c74149d 100755 (executable)
@@ -119,6 +119,11 @@ for f in $gofiles; do
        386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | nios2 | ppc | ppc64 | ppc64le | riscv | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64 | wasm)
            tag1=nonmatchingtag
            ;;
+       *)
+           # File name like x_amd64_random.go, where tag1=random.
+           # Don't match based on tag2.
+           tag2=
+           ;;
     esac
 
     case "$tag2" in
@@ -151,18 +156,18 @@ for f in $gofiles; do
                    fi
                    match=false
                    ;;
-               $goos | $goarch | $cgotag | $cmdlinetag | "gccgo" | go1.[0-9] | go1.[0-9][0-9])
+               $goos | $goarch | $cgotag | $cmdlinetag | "gccgo" | "goexperiment.fieldtrack" | go1.[0-9] | go1.[0-9][0-9])
                    match=true
                    ;;
-               "!"$goos | "!"$goarch | "!"$cgotag | "!"$cmdlinetag | "!gccgo" | "!"go1.[0-9] | "!"go1.1[0-6])
+               "!"$goos | "!"$goarch | "!"$cgotag | "!"$cmdlinetag | "!gccgo" | "!goexperiment.fieldtrack" | "!"go1.[0-9] | "!"go1.1[0-7])
                    ;;
                *,*)
                    cmatch=true
                    for ctag in `echo $tag | sed -e 's/,/ /g'`; do
                        case $ctag in
-                           $goos | $goarch | $cgotag | $cmdlinetag | "gccgo" | go1.[0-9] | go1.[0-9][0-9])
+                           $goos | $goarch | $cgotag | $cmdlinetag | "gccgo" | "goexperiment.fieldtrack" | go1.[0-9] | go1.[0-9][0-9])
                                ;;
-                           "!"$goos | "!"$goarch | "!"$cgotag | "!"$cmdlinetag | "!gccgo" | "!"go1.[0-9] | "!"go1.1[0-6])
+                           "!"$goos | "!"$goarch | "!"$cgotag | "!"$cmdlinetag | "!gccgo" | "!goexperiment.fieldtrack" | "!"go1.[0-9] | "!"go1.1[0-7])
                                cmatch=false
                                ;;
                            "!"*)
diff --git a/libgo/misc/cgo/errors/argposition_test.go b/libgo/misc/cgo/errors/argposition_test.go
new file mode 100644 (file)
index 0000000..331095f
--- /dev/null
@@ -0,0 +1,134 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 42580: cmd/cgo: shifting identifier position in ast
+
+package errorstest
+
+import (
+       "bytes"
+       "fmt"
+       "go/ast"
+       "go/parser"
+       "go/token"
+       "io/ioutil"
+       "os"
+       "os/exec"
+       "path/filepath"
+       "strings"
+       "testing"
+)
+
+type ShortPosition struct {
+       Line    int
+       Column  int
+       Visited bool
+}
+
+type IdentPositionInfo map[string][]ShortPosition
+
+type Visitor struct {
+       identPosInfo IdentPositionInfo
+       fset         *token.FileSet
+       t            *testing.T
+}
+
+func (v *Visitor) Visit(node ast.Node) ast.Visitor {
+       if ident, ok := node.(*ast.Ident); ok {
+               if expectedPositions, ok := v.identPosInfo[ident.Name]; ok {
+                       gotMatch := false
+                       var errorMessage strings.Builder
+                       for caseIndex, expectedPos := range expectedPositions {
+                               actualPosition := v.fset.PositionFor(ident.Pos(), true)
+                               errorOccured := false
+                               if expectedPos.Line != actualPosition.Line {
+                                       fmt.Fprintf(&errorMessage, "wrong line number for ident %s: expected: %d got: %d\n", ident.Name, expectedPos.Line, actualPosition.Line)
+                                       errorOccured = true
+                               }
+                               if expectedPos.Column != actualPosition.Column {
+                                       fmt.Fprintf(&errorMessage, "wrong column number for ident %s: expected: %d got: %d\n", ident.Name, expectedPos.Column, actualPosition.Column)
+                                       errorOccured = true
+                               }
+                               if errorOccured {
+                                       continue
+                               }
+                               gotMatch = true
+                               expectedPositions[caseIndex].Visited = true
+                       }
+
+                       if !gotMatch {
+                               v.t.Errorf(errorMessage.String())
+                       }
+               }
+       }
+       return v
+}
+
+func TestArgumentsPositions(t *testing.T) {
+       testdata, err := filepath.Abs("testdata")
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       tmpPath := t.TempDir()
+
+       dir := filepath.Join(tmpPath, "src", "testpositions")
+       if err := os.MkdirAll(dir, 0755); err != nil {
+               t.Fatal(err)
+       }
+
+       cmd := exec.Command("go", "tool", "cgo",
+               "-srcdir", testdata,
+               "-objdir", dir,
+               "issue42580.go")
+       cmd.Stderr = new(bytes.Buffer)
+
+       err = cmd.Run()
+       if err != nil {
+               t.Fatalf("%s: %v\n%s", cmd, err, cmd.Stderr)
+       }
+       mainProcessed, err := ioutil.ReadFile(filepath.Join(dir, "issue42580.cgo1.go"))
+       if err != nil {
+               t.Fatal(err)
+       }
+       fset := token.NewFileSet()
+       f, err := parser.ParseFile(fset, "", mainProcessed, parser.AllErrors)
+       if err != nil {
+               fmt.Println(err)
+               return
+       }
+
+       expectation := IdentPositionInfo{
+               "checkedPointer": []ShortPosition{
+                       ShortPosition{
+                               Line:   32,
+                               Column: 56,
+                       },
+               },
+               "singleInnerPointerChecked": []ShortPosition{
+                       ShortPosition{
+                               Line:   37,
+                               Column: 91,
+                       },
+               },
+               "doublePointerChecked": []ShortPosition{
+                       ShortPosition{
+                               Line:   42,
+                               Column: 91,
+                       },
+               },
+       }
+       for _, decl := range f.Decls {
+               if fdecl, ok := decl.(*ast.FuncDecl); ok {
+                       ast.Walk(&Visitor{expectation, fset, t}, fdecl.Body)
+               }
+       }
+       for ident, positions := range expectation {
+               for _, position := range positions {
+                       if !position.Visited {
+                               t.Errorf("Position %d:%d missed for %s ident", position.Line, position.Column, ident)
+                       }
+               }
+       }
+}
index b2701bf922e52927f0a34b28fc7cdffe62008f7a..fc687567bf71b2aa962a0b6f79d6e67627d24479 100644 (file)
@@ -6,7 +6,6 @@ package errorstest
 
 import (
        "bytes"
-       "io/ioutil"
        "os"
        "os/exec"
        "path/filepath"
@@ -55,7 +54,7 @@ func TestBadSymbol(t *testing.T) {
 
        makeFile := func(mdir, base, source string) string {
                ret := filepath.Join(mdir, base)
-               if err := ioutil.WriteFile(ret, []byte(source), 0644); err != nil {
+               if err := os.WriteFile(ret, []byte(source), 0644); err != nil {
                        t.Fatal(err)
                }
                return ret
@@ -100,7 +99,7 @@ func TestBadSymbol(t *testing.T) {
        // _cgo_import.go.
 
        rewrite := func(from, to string) {
-               obj, err := ioutil.ReadFile(from)
+               obj, err := os.ReadFile(from)
                if err != nil {
                        t.Fatal(err)
                }
@@ -115,7 +114,7 @@ func TestBadSymbol(t *testing.T) {
 
                obj = bytes.ReplaceAll(obj, []byte(magicInput), []byte(magicReplace))
 
-               if err := ioutil.WriteFile(to, obj, 0644); err != nil {
+               if err := os.WriteFile(to, obj, 0644); err != nil {
                        t.Fatal(err)
                }
        }
index 1bdf843451d366b693857abe92a11d31ede08d6f..68a30a44fe427d434df9dc634f702fc38552aa5e 100644 (file)
@@ -7,7 +7,6 @@ package errorstest
 import (
        "bytes"
        "fmt"
-       "io/ioutil"
        "os"
        "os/exec"
        "path/filepath"
@@ -25,7 +24,7 @@ func check(t *testing.T, file string) {
        t.Run(file, func(t *testing.T) {
                t.Parallel()
 
-               contents, err := ioutil.ReadFile(path(file))
+               contents, err := os.ReadFile(path(file))
                if err != nil {
                        t.Fatal(err)
                }
@@ -41,7 +40,8 @@ func check(t *testing.T, file string) {
                        if len(frags) == 1 {
                                continue
                        }
-                       re, err := regexp.Compile(string(frags[1]))
+                       frag := fmt.Sprintf(":%d:.*%s", i+1, frags[1])
+                       re, err := regexp.Compile(frag)
                        if err != nil {
                                t.Errorf("Invalid regexp after `ERROR HERE: `: %#q", frags[1])
                                continue
@@ -56,7 +56,7 @@ func check(t *testing.T, file string) {
 }
 
 func expect(t *testing.T, file string, errors []*regexp.Regexp) {
-       dir, err := ioutil.TempDir("", filepath.Base(t.Name()))
+       dir, err := os.MkdirTemp("", filepath.Base(t.Name()))
        if err != nil {
                t.Fatal(err)
        }
index 4a46b6023bb510ab70e146c80358b7f56bee5f52..0f39dc8e547ed0f47f51749b7e3c22173b5f2ea3 100644 (file)
@@ -10,7 +10,6 @@ import (
        "bytes"
        "flag"
        "fmt"
-       "io/ioutil"
        "os"
        "os/exec"
        "path/filepath"
@@ -463,7 +462,7 @@ func buildPtrTests(t *testing.T) (dir, exe string) {
                gopath = *tmp
                dir = ""
        } else {
-               d, err := ioutil.TempDir("", filepath.Base(t.Name()))
+               d, err := os.MkdirTemp("", filepath.Base(t.Name()))
                if err != nil {
                        t.Fatal(err)
                }
@@ -475,7 +474,7 @@ func buildPtrTests(t *testing.T) (dir, exe string) {
        if err := os.MkdirAll(src, 0777); err != nil {
                t.Fatal(err)
        }
-       if err := ioutil.WriteFile(filepath.Join(src, "go.mod"), []byte("module ptrtest"), 0666); err != nil {
+       if err := os.WriteFile(filepath.Join(src, "go.mod"), []byte("module ptrtest"), 0666); err != nil {
                t.Fatal(err)
        }
 
@@ -535,10 +534,10 @@ func buildPtrTests(t *testing.T) (dir, exe string) {
        fmt.Fprintf(&cgo1, "}\n\n")
        fmt.Fprintf(&cgo1, "%s\n", ptrTestMain)
 
-       if err := ioutil.WriteFile(filepath.Join(src, "cgo1.go"), cgo1.Bytes(), 0666); err != nil {
+       if err := os.WriteFile(filepath.Join(src, "cgo1.go"), cgo1.Bytes(), 0666); err != nil {
                t.Fatal(err)
        }
-       if err := ioutil.WriteFile(filepath.Join(src, "cgo2.go"), cgo2.Bytes(), 0666); err != nil {
+       if err := os.WriteFile(filepath.Join(src, "cgo2.go"), cgo2.Bytes(), 0666); err != nil {
                t.Fatal(err)
        }
 
index 1d22401aee53a6e0783b3dc16d7a1555d67d4180..a90598fe35b6304434bba7253c29b1d62173dcc4 100644 (file)
@@ -40,15 +40,15 @@ func main() {
        C.foop = x // ERROR HERE
 
        // issue 13129: used to output error about C.unsignedshort with CC=clang
-       var x C.ushort
-       x = int(0) // ERROR HERE: C\.ushort
+       var x1 C.ushort
+       x1 = int(0) // ERROR HERE: C\.ushort
 
        // issue 13423
        _ = C.fopen() // ERROR HERE
 
        // issue 13467
-       var x rune = '✈'
-       var _ rune = C.transform(x) // ERROR HERE: C\.int
+       var x2 rune = '✈'
+       var _ rune = C.transform(x2) // ERROR HERE: C\.int
 
        // issue 13635: used to output error about C.unsignedchar.
        // This test tests all such types.
@@ -91,10 +91,10 @@ func main() {
 
        // issue 26745
        _ = func(i int) int {
-               return C.i + 1 // ERROR HERE: :13
+               return C.i + 1 // ERROR HERE: 14
        }
        _ = func(i int) {
-               C.fi(i) // ERROR HERE: :6
+               C.fi(i) // ERROR HERE: 7
        }
 
        C.fi = C.fi // ERROR HERE
diff --git a/libgo/misc/cgo/errors/testdata/issue42580.go b/libgo/misc/cgo/errors/testdata/issue42580.go
new file mode 100644 (file)
index 0000000..aba80df
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 42580: cmd/cgo: shifting identifier position in ast
+
+package cgotest
+
+// typedef int (*intFunc) ();
+//
+// char* strarg = "";
+//
+// int func_with_char(char* arg, void* dummy)
+// {return 5;}
+//
+// int* get_arr(char* arg, void* dummy)
+// {return NULL;}
+import "C"
+import "unsafe"
+
+// Test variables
+var (
+       checkedPointer            = []byte{1}
+       doublePointerChecked      = []byte{1}
+       singleInnerPointerChecked = []byte{1}
+)
+
+// This test checks the positions of variable identifiers.
+// Changing the positions of the test variables idents after this point will break the test.
+
+func TestSingleArgumentCast() C.int {
+       retcode := C.func_with_char((*C.char)(unsafe.Pointer(&checkedPointer[0])), unsafe.Pointer(C.strarg))
+       return retcode
+}
+
+func TestSingleArgumentCastRecFuncAsSimpleArg() C.int {
+       retcode := C.func_with_char((*C.char)(unsafe.Pointer(C.get_arr((*C.char)(unsafe.Pointer(&singleInnerPointerChecked[0])), unsafe.Pointer(C.strarg)))), nil)
+       return retcode
+}
+
+func TestSingleArgumentCastRecFunc() C.int {
+       retcode := C.func_with_char((*C.char)(unsafe.Pointer(C.get_arr((*C.char)(unsafe.Pointer(&doublePointerChecked[0])), unsafe.Pointer(C.strarg)))), unsafe.Pointer(C.strarg))
+       return retcode
+}
index 3c95d87d8ade053b1fc3108df6c98f59a68b845c..0becb262b43e9ab8cafcccd5148d798ea451ac64 100644 (file)
@@ -6,7 +6,6 @@ package life_test
 
 import (
        "bytes"
-       "io/ioutil"
        "log"
        "os"
        "os/exec"
@@ -21,7 +20,7 @@ func TestMain(m *testing.M) {
 }
 
 func testMain(m *testing.M) int {
-       GOPATH, err := ioutil.TempDir("", "cgolife")
+       GOPATH, err := os.MkdirTemp("", "cgolife")
        if err != nil {
                log.Panic(err)
        }
@@ -38,7 +37,7 @@ func testMain(m *testing.M) int {
                log.Panic(err)
        }
        os.Setenv("PWD", modRoot)
-       if err := ioutil.WriteFile("go.mod", []byte("module cgolife\n"), 0666); err != nil {
+       if err := os.WriteFile("go.mod", []byte("module cgolife\n"), 0666); err != nil {
                log.Panic(err)
        }
 
index ab5d328f676cd564bc71fab1dc5a5ae93de0edb6..675418f98d026e22a61d3a4088c4100638127f84 100644 (file)
@@ -6,7 +6,6 @@ package stdio_test
 
 import (
        "bytes"
-       "io/ioutil"
        "log"
        "os"
        "os/exec"
@@ -21,7 +20,7 @@ func TestMain(m *testing.M) {
 }
 
 func testMain(m *testing.M) int {
-       GOPATH, err := ioutil.TempDir("", "cgostdio")
+       GOPATH, err := os.MkdirTemp("", "cgostdio")
        if err != nil {
                log.Panic(err)
        }
@@ -38,7 +37,7 @@ func testMain(m *testing.M) int {
                log.Panic(err)
        }
        os.Setenv("PWD", modRoot)
-       if err := ioutil.WriteFile("go.mod", []byte("module cgostdio\n"), 0666); err != nil {
+       if err := os.WriteFile("go.mod", []byte("module cgostdio\n"), 0666); err != nil {
                log.Panic(err)
        }
 
index 814888e3ac5d9a7fad84e00dfb90e5e4c01d1bdd..08dd9b39d8191ec1a2d4a7ef30151724ffa4b85e 100644 (file)
@@ -182,7 +182,7 @@ func testCallbackCallers(t *testing.T) {
                "runtime.cgocallbackg1",
                "runtime.cgocallbackg",
                "runtime.cgocallback",
-               "runtime.asmcgocall",
+               "runtime.systemstack_switch",
                "runtime.cgocall",
                "test._Cfunc_callback",
                "test.nestedCall.func1",
index f7a76d047bd9515eff224e909dda41b1a89cf08e..143f23f0e0cc36983ad44595469b5b7f55ff0d56 100644 (file)
@@ -59,6 +59,7 @@ func Test28896(t *testing.T)                 { test28896(t) }
 func Test30065(t *testing.T)                 { test30065(t) }
 func Test32579(t *testing.T)                 { test32579(t) }
 func Test31891(t *testing.T)                 { test31891(t) }
+func Test45451(t *testing.T)                 { test45451(t) }
 func TestAlign(t *testing.T)                 { testAlign(t) }
 func TestAtol(t *testing.T)                  { testAtol(t) }
 func TestBlocking(t *testing.T)              { testBlocking(t) }
@@ -80,6 +81,7 @@ func TestNamedEnum(t *testing.T)             { testNamedEnum(t) }
 func TestCastToEnum(t *testing.T)            { testCastToEnum(t) }
 func TestErrno(t *testing.T)                 { testErrno(t) }
 func TestFpVar(t *testing.T)                 { testFpVar(t) }
+func TestHandle(t *testing.T)                { testHandle(t) }
 func TestHelpers(t *testing.T)               { testHelpers(t) }
 func TestLibgcc(t *testing.T)                { testLibgcc(t) }
 func TestMultipleAssign(t *testing.T)        { testMultipleAssign(t) }
index a1c7cacde73844b55fc42dc8cb6e7e08469559fc..91db155c90b9836eb38042725612b9737512c28f 100644 (file)
@@ -2,13 +2,15 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build linux && cgo
 // +build linux,cgo
 
 package cgotest
 
 import (
        "fmt"
-       "io/ioutil"
+       "os"
+       "sort"
        "strings"
        "syscall"
        "testing"
@@ -64,7 +66,7 @@ import "C"
 func compareStatus(filter, expect string) error {
        expected := filter + expect
        pid := syscall.Getpid()
-       fs, err := ioutil.ReadDir(fmt.Sprintf("/proc/%d/task", pid))
+       fs, err := os.ReadDir(fmt.Sprintf("/proc/%d/task", pid))
        if err != nil {
                return fmt.Errorf("unable to find %d tasks: %v", pid, err)
        }
@@ -72,7 +74,7 @@ func compareStatus(filter, expect string) error {
        foundAThread := false
        for _, f := range fs {
                tf := fmt.Sprintf("/proc/%s/status", f.Name())
-               d, err := ioutil.ReadFile(tf)
+               d, err := os.ReadFile(tf)
                if err != nil {
                        // There are a surprising number of ways this
                        // can error out on linux.  We've seen all of
@@ -105,11 +107,23 @@ func compareStatus(filter, expect string) error {
                                // "Pid:\t".
                        }
                        if strings.HasPrefix(line, filter) {
-                               if line != expected {
-                                       return fmt.Errorf("%q got:%q want:%q (bad) [pid=%d file:'%s' %v]\n", tf, line, expected, pid, string(d), expectedProc)
+                               if line == expected {
+                                       foundAThread = true
+                                       break
+                               }
+                               if filter == "Groups:" && strings.HasPrefix(line, "Groups:\t") {
+                                       // https://github.com/golang/go/issues/46145
+                                       // Containers don't reliably output this line in sorted order so manually sort and compare that.
+                                       a := strings.Split(line[8:], " ")
+                                       sort.Strings(a)
+                                       got := strings.Join(a, " ")
+                                       if got == expected[8:] {
+                                               foundAThread = true
+                                               break
+                                       }
+
                                }
-                               foundAThread = true
-                               break
+                               return fmt.Errorf("%q got:%q want:%q (bad) [pid=%d file:'%s' %v]\n", tf, line, expected, pid, string(d), expectedProc)
                        }
                }
        }
index 0c98ea0794eec302d134e0855769758c7286ec35..4acc8c1a07062710cb33075dc5730d5d67e695bf 100644 (file)
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !android
 // +build !android
 
 // Test that pthread_cancel works as expected
-// (NPTL uses SIGRTMIN to implement thread cancelation)
+// (NPTL uses SIGRTMIN to implement thread cancellation)
 // See https://golang.org/issue/6997
 package cgotest
 
@@ -17,8 +18,10 @@ extern int CancelThread();
 */
 import "C"
 
-import "testing"
-import "time"
+import (
+       "testing"
+       "time"
+)
 
 func test6997(t *testing.T) {
        r := C.StartThread()
similarity index 62%
rename from libgo/go/syscall/export_test.go
rename to libgo/misc/cgo/test/issue8148.c
index 55c09e667e22948653699ef221f752ad33c75e45..927b4346cbe03df4339c3a342629921bf1dc4b6c 100644 (file)
@@ -2,6 +2,10 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package syscall
+#include "_cgo_export.h"
 
-var Itoa = itoa
+int get8148(void) {
+       T t;
+       t.i = 42;
+       return issue8148Callback(&t);
+}
index f704788aef8a45da1d8d195f8c478ee7d617f3e5..aee9003d5075bf02751a477e9fc7ffb8da2d4009 100644 (file)
@@ -10,14 +10,7 @@ package cgotest
 
 /*
 typedef struct { int i; } T;
-
-int issue8148Callback(T*);
-
-static int get() {
-       T t;
-       t.i = 42;
-       return issue8148Callback(&t);
-}
+int get8148(void);
 */
 import "C"
 
@@ -27,5 +20,5 @@ func issue8148Callback(t *C.T) C.int {
 }
 
 func Issue8148() int {
-       return int(C.get())
+       return int(C.get8148())
 }
index 94abaa03e8d4b98cd679bcb69f5a3c38c6110ef6..14013a4cd962b621f6e5a9a4cade19c0504edcb6 100644 (file)
@@ -5,7 +5,6 @@
 package cgotest
 
 import (
-       "io/ioutil"
        "os"
        "os/exec"
        "path/filepath"
@@ -37,7 +36,7 @@ func TestCrossPackageTests(t *testing.T) {
                }
        }
 
-       GOPATH, err := ioutil.TempDir("", "cgotest")
+       GOPATH, err := os.MkdirTemp("", "cgotest")
        if err != nil {
                t.Fatal(err)
        }
@@ -47,7 +46,7 @@ func TestCrossPackageTests(t *testing.T) {
        if err := overlayDir(modRoot, "testdata"); err != nil {
                t.Fatal(err)
        }
-       if err := ioutil.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgotest\n"), 0666); err != nil {
+       if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgotest\n"), 0666); err != nil {
                t.Fatal(err)
        }
 
index 6773f94d3d6816c6cbdab8e827e22a908b70ef18..7c64946cb34b68fa1770fbfdc9cbf1f3ab7d1092 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Test that setgid does not hang on GNU/Linux.
+// Test that setgid does not hang on Linux.
 // See https://golang.org/issue/3871 for details.
 
 package cgotest
index 65823b1ca0e95189576b265ba6e097933428c1d6..3b8f548b13dd206fedd0653d8472c5b8d9958d12 100644 (file)
@@ -899,6 +899,10 @@ static uint16_t issue31093F(uint16_t v) { return v; }
 // issue 32579
 typedef struct S32579 { unsigned char data[1]; } S32579;
 
+// issue 37033, cgo.Handle
+extern void GoFunc37033(uintptr_t handle);
+void cFunc37033(uintptr_t handle) { GoFunc37033(handle); }
+
 // issue 38649
 // Test that #define'd type aliases work.
 #define netbsd_gid unsigned int
@@ -908,6 +912,9 @@ typedef struct S32579 { unsigned char data[1]; } S32579;
 enum Enum40494 { X_40494 };
 union Union40494 { int x; };
 void issue40494(enum Enum40494 e, union Union40494* up) {}
+
+// Issue 45451, bad handling of go:notinheap types.
+typedef struct issue45451Undefined issue45451;
 */
 import "C"
 
@@ -920,6 +927,7 @@ import (
        "os/signal"
        "reflect"
        "runtime"
+       "runtime/cgo"
        "sync"
        "syscall"
        "testing"
@@ -2230,6 +2238,23 @@ func test32579(t *testing.T) {
        }
 }
 
+// issue 37033, check if cgo.Handle works properly
+
+func testHandle(t *testing.T) {
+       ch := make(chan int)
+
+       for i := 0; i < 42; i++ {
+               h := cgo.NewHandle(ch)
+               go func() {
+                       C.cFunc37033(C.uintptr_t(h))
+               }()
+               if v := <-ch; issue37033 != v {
+                       t.Fatalf("unexpected receiving value: got %d, want %d", v, issue37033)
+               }
+               h.Delete()
+       }
+}
+
 // issue 38649
 
 var issue38649 C.netbsd_gid = 42
@@ -2244,3 +2269,19 @@ var issue39877 *C.void = nil
 func Issue40494() {
        C.issue40494(C.enum_Enum40494(C.X_40494), (*C.union_Union40494)(nil))
 }
+
+// Issue 45451.
+func test45451(t *testing.T) {
+       var u *C.issue45451
+       typ := reflect.ValueOf(u).Type().Elem()
+
+       // The type is undefined in C so allocating it should panic.
+       defer func() {
+               if r := recover(); r == nil {
+                       t.Error("expected panic")
+               }
+       }()
+
+       _ = reflect.New(typ)
+       t.Errorf("reflect.New(%v) should have panicked", typ)
+}
index 7f158b5c39d8d299d4fbfbcac465ad71efb30fd9..96b8b60c10f589dbb7f17de0eb1805cfa959082c 100644 (file)
@@ -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 !gccgo
+// +build gc
 
 #include "textflag.h"
 
index 48b86190a59fc6378b8a7dda8a644c1da4a52414..99509bce5e1518cfdc20d329fa5c936eb1721a4b 100644 (file)
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // +build amd64 amd64p32
-// +build !gccgo
+// +build gc
 
 #include "textflag.h"
 
index 96c278520f398d2106ef2220c88462ef0c30cafd..cc92856c2ff482f6015f0f4e0f62fd9047daf16c 100644 (file)
@@ -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 !gccgo
+// +build gc
 
 #include "textflag.h"
 
index 2ebbfcca3b607580fbd3c93384ef9a40de172171..2565793f9ab00d3e068dc8e6e76b6b014c43c1fc 100644 (file)
@@ -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 !gccgo
+// +build gc
 
 #include "textflag.h"
 
index 63dc90605e6f8edf4f5d42150283efe2fad66ed1..693231ddfe1b94a8cd896cd3a29aaff2b3d52a94 100644 (file)
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // +build mips64 mips64le
-// +build !gccgo
+// +build gc
 
 #include "textflag.h"
 
index 7a92735194245ca6d850ec35d844d0677174f118..63261bbf9d08d82e3c85d52a99e2adfb96afecee 100644 (file)
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // +build mips mipsle
-// +build !gccgo
+// +build gc
 
 #include "textflag.h"
 
index c88ec3b21e76517d9ec44d0a0b5fe0f236a41d52..b5613fb6ec73f6f2b5daa70095c314a44870394f 100644 (file)
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // +build ppc64 ppc64le
-// +build !gccgo
+// +build gc
 
 #include "textflag.h"
 
index 20fcc0066d6b2b272534fdaf464b623947431d32..244dadac35097526a7a7d4384aae91d321eb7900 100644 (file)
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // +build riscv64
-// +build !gccgo
+// +build gc
 
 #include "textflag.h"
 
index fc9ad724c15fc11b4544b7fb06cf9c0e68ae30bd..4856492958b116f6105c464c810a428819000d1a 100644 (file)
@@ -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 !gccgo
+// +build gc
 
 #include "textflag.h"
 
diff --git a/libgo/misc/cgo/test/testx.c b/libgo/misc/cgo/test/testx.c
new file mode 100644 (file)
index 0000000..1258e32
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "_cgo_export.h"
+
+void lockOSThreadC(void) {
+       lockOSThreadCallback();
+}
+
+void issue7978c(uint32_t *sync) {
+       while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 0)
+               ;
+       __atomic_add_fetch(sync, 1, __ATOMIC_SEQ_CST);
+       while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 2)
+               ;
+       issue7978cb();
+       __atomic_add_fetch(sync, 1, __ATOMIC_SEQ_CST);
+       while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 6)
+               ;
+}
+
+void f7665(void) {
+}
index 2b2e69ec00f162e7f2c9c0f141c73704ec2c7c83..823c3e13d2927aac7bfd240ddd46b69882a8aff0 100644 (file)
@@ -12,6 +12,7 @@ package cgotest
 
 import (
        "runtime"
+       "runtime/cgo"
        "runtime/debug"
        "strings"
        "sync"
@@ -26,7 +27,6 @@ import (
 extern void doAdd(int, int);
 
 // issue 1328
-extern void BackIntoGo(void);
 void IntoC(void);
 
 // issue 1560
@@ -38,11 +38,7 @@ long long mysleep(int seconds);
 long long twoSleep(int);
 
 // issue 3775
-void lockOSThreadCallback(void);
-inline static void lockOSThreadC(void)
-{
-        lockOSThreadCallback();
-}
+void lockOSThreadC(void);
 int usleep(unsigned usec);
 
 // issue 4054 part 2 - part 1 in test.go
@@ -81,21 +77,9 @@ extern void f7665(void);
 
 #include <stdint.h>
 
-void issue7978cb(void);
-
 // use ugly atomic variable sync since that doesn't require calling back into
 // Go code or OS dependencies
-static void issue7978c(uint32_t *sync) {
-       while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 0)
-               ;
-       __atomic_add_fetch(sync, 1, __ATOMIC_SEQ_CST);
-       while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 2)
-               ;
-       issue7978cb();
-       __atomic_add_fetch(sync, 1, __ATOMIC_SEQ_CST);
-       while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 6)
-               ;
-}
+void issue7978c(uint32_t *sync);
 
 // issue 8331 part 2 - part 1 in test.go
 // A typedef of an unnamed struct is the same struct when
@@ -428,9 +412,6 @@ func test6907Go(t *testing.T) {
 
 // issue 7665
 
-//export f7665
-func f7665() {}
-
 var bad7665 unsafe.Pointer = C.f7665
 var good7665 uintptr = uintptr(C.f7665)
 
@@ -558,6 +539,17 @@ func test31891(t *testing.T) {
        C.callIssue31891()
 }
 
+// issue 37033, check if cgo.Handle works properly
+
+var issue37033 = 42
+
+//export GoFunc37033
+func GoFunc37033(handle C.uintptr_t) {
+       h := cgo.Handle(handle)
+       ch := h.Value().(chan int)
+       ch <- issue37033
+}
+
 // issue 38408
 // A typedef pointer can be used as the element type.
 // No runtime test; just make sure it compiles.
index b67cb2e0cd0db7df43b03a3c0bc86c00426eb12c..e5db0d628a48a3ac88040410011963b3d8748053 100644 (file)
@@ -10,7 +10,6 @@ import (
        "debug/elf"
        "flag"
        "fmt"
-       "io/ioutil"
        "log"
        "os"
        "os/exec"
@@ -53,7 +52,7 @@ func testMain(m *testing.M) int {
        // We need a writable GOPATH in which to run the tests.
        // Construct one in a temporary directory.
        var err error
-       GOPATH, err = ioutil.TempDir("", "carchive_test")
+       GOPATH, err = os.MkdirTemp("", "carchive_test")
        if err != nil {
                log.Panic(err)
        }
@@ -74,7 +73,7 @@ func testMain(m *testing.M) int {
                log.Panic(err)
        }
        os.Setenv("PWD", modRoot)
-       if err := ioutil.WriteFile("go.mod", []byte("module testcarchive\n"), 0666); err != nil {
+       if err := os.WriteFile("go.mod", []byte("module testcarchive\n"), 0666); err != nil {
                log.Panic(err)
        }
 
@@ -176,7 +175,7 @@ func genHeader(t *testing.T, header, dir string) {
        // The 'cgo' command generates a number of additional artifacts,
        // but we're only interested in the header.
        // Shunt the rest of the outputs to a temporary directory.
-       objDir, err := ioutil.TempDir(GOPATH, "_obj")
+       objDir, err := os.MkdirTemp(GOPATH, "_obj")
        if err != nil {
                t.Fatal(err)
        }
@@ -252,7 +251,7 @@ var badLineRegexp = regexp.MustCompile(`(?m)^#line [0-9]+ "/.*$`)
 // the user and make the files change based on details of the location
 // of GOPATH.
 func checkLineComments(t *testing.T, hdrname string) {
-       hdr, err := ioutil.ReadFile(hdrname)
+       hdr, err := os.ReadFile(hdrname)
        if err != nil {
                if !os.IsNotExist(err) {
                        t.Error(err)
@@ -618,7 +617,7 @@ func TestExtar(t *testing.T) {
                t.Fatal(err)
        }
        s := strings.Replace(testar, "PWD", dir, 1)
-       if err := ioutil.WriteFile("testar", []byte(s), 0777); err != nil {
+       if err := os.WriteFile("testar", []byte(s), 0777); err != nil {
                t.Fatal(err)
        }
 
@@ -776,7 +775,7 @@ func TestSIGPROF(t *testing.T) {
 // tool with -buildmode=c-archive, it passes -shared to the compiler,
 // so we override that. The go tool doesn't work this way, but Bazel
 // will likely do it in the future. And it ought to work. This test
-// was added because at one time it did not work on PPC GNU/Linux.
+// was added because at one time it did not work on PPC Linux.
 func TestCompileWithoutShared(t *testing.T) {
        // For simplicity, reuse the signal forwarding test.
        checkSignalForwardingTest(t)
index 4cb05dc61786ab0f1278ab493996c20022fb044a..31527c59af1213aeee245b5daa545ee7194fa93d 100644 (file)
@@ -5,7 +5,7 @@
 package main
 
 import (
-       "io/ioutil"
+       "io"
        "runtime/pprof"
 )
 
@@ -13,7 +13,7 @@ import "C"
 
 //export go_start_profile
 func go_start_profile() {
-       pprof.StartCPUProfile(ioutil.Discard)
+       pprof.StartCPUProfile(io.Discard)
 }
 
 //export go_stop_profile
index 3a4886cf30a88be4fcd62dff23256a4ec058097d..19ad8c76a838b54bad64c35635216088ff40db80 100644 (file)
@@ -11,7 +11,6 @@ import (
        "encoding/binary"
        "flag"
        "fmt"
-       "io/ioutil"
        "log"
        "os"
        "os/exec"
@@ -125,7 +124,7 @@ func testMain(m *testing.M) int {
        // Copy testdata into GOPATH/src/testcshared, along with a go.mod file
        // declaring the same path.
 
-       GOPATH, err := ioutil.TempDir("", "cshared_test")
+       GOPATH, err := os.MkdirTemp("", "cshared_test")
        if err != nil {
                log.Panic(err)
        }
@@ -140,7 +139,7 @@ func testMain(m *testing.M) int {
                log.Panic(err)
        }
        os.Setenv("PWD", modRoot)
-       if err := ioutil.WriteFile("go.mod", []byte("module testcshared\n"), 0666); err != nil {
+       if err := os.WriteFile("go.mod", []byte("module testcshared\n"), 0666); err != nil {
                log.Panic(err)
        }
 
@@ -260,7 +259,7 @@ func createHeaders() error {
        // The 'cgo' command generates a number of additional artifacts,
        // but we're only interested in the header.
        // Shunt the rest of the outputs to a temporary directory.
-       objDir, err := ioutil.TempDir("", "testcshared_obj")
+       objDir, err := os.MkdirTemp("", "testcshared_obj")
        if err != nil {
                return err
        }
@@ -293,11 +292,60 @@ func createHeaders() error {
                "-installsuffix", "testcshared",
                "-o", libgoname,
                filepath.Join(".", "libgo", "libgo.go")}
+       if GOOS == "windows" && strings.HasSuffix(args[6], ".a") {
+               args[6] = strings.TrimSuffix(args[6], ".a") + ".dll"
+       }
        cmd = exec.Command(args[0], args[1:]...)
        out, err = cmd.CombinedOutput()
        if err != nil {
                return fmt.Errorf("command failed: %v\n%v\n%s\n", args, err, out)
        }
+       if GOOS == "windows" {
+               // We can't simply pass -Wl,--out-implib, because this relies on having imports from multiple packages,
+               // which results in the linkers output implib getting overwritten at each step. So instead build the
+               // import library the traditional way, using a def file.
+               err = os.WriteFile("libgo.def",
+                       []byte("LIBRARY libgo.dll\nEXPORTS\n\tDidInitRun\n\tDidMainRun\n\tDivu\n\tFromPkg\n\t_cgo_dummy_export\n"),
+                       0644)
+               if err != nil {
+                       return fmt.Errorf("unable to write def file: %v", err)
+               }
+               out, err = exec.Command(cc[0], append(cc[1:], "-print-prog-name=dlltool")...).CombinedOutput()
+               if err != nil {
+                       return fmt.Errorf("unable to find dlltool path: %v\n%s\n", err, out)
+               }
+               args := []string{strings.TrimSpace(string(out)), "-D", args[6], "-l", libgoname, "-d", "libgo.def"}
+
+               // This is an unfortunate workaround for https://github.com/mstorsjo/llvm-mingw/issues/205 in which
+               // we basically reimplement the contents of the dlltool.sh wrapper: https://git.io/JZFlU
+               dlltoolContents, err := os.ReadFile(args[0])
+               if err != nil {
+                       return fmt.Errorf("unable to read dlltool: %v\n", err)
+               }
+               if bytes.HasPrefix(dlltoolContents, []byte("#!/bin/sh")) && bytes.Contains(dlltoolContents, []byte("llvm-dlltool")) {
+                       base, name := filepath.Split(args[0])
+                       args[0] = filepath.Join(base, "llvm-dlltool")
+                       var machine string
+                       switch strings.SplitN(name, "-", 2)[0] {
+                       case "i686":
+                               machine = "i386"
+                       case "x86_64":
+                               machine = "i386:x86-64"
+                       case "armv7":
+                               machine = "arm"
+                       case "aarch64":
+                               machine = "arm64"
+                       }
+                       if len(machine) > 0 {
+                               args = append(args, "-m", machine)
+                       }
+               }
+
+               out, err = exec.Command(args[0], args[1:]...).CombinedOutput()
+               if err != nil {
+                       return fmt.Errorf("unable to run dlltool to create import library: %v\n%s\n", err, out)
+               }
+       }
 
        if runtime.GOOS != GOOS && GOOS == "android" {
                args = append(adbCmd(), "push", libgoname, fmt.Sprintf("%s/%s", androiddir, libgoname))
@@ -381,7 +429,7 @@ func main() {
 
        srcfile := filepath.Join(tmpdir, "test.go")
        objfile := filepath.Join(tmpdir, "test.dll")
-       if err := ioutil.WriteFile(srcfile, []byte(prog), 0666); err != nil {
+       if err := os.WriteFile(srcfile, []byte(prog), 0666); err != nil {
                t.Fatal(err)
        }
        argv := []string{"build", "-buildmode=c-shared"}
@@ -401,7 +449,7 @@ func main() {
        defer f.Close()
        section := f.Section(".edata")
        if section == nil {
-               t.Fatalf(".edata section is not present")
+               t.Skip(".edata section is not present")
        }
 
        // TODO: deduplicate this struct from cmd/link/internal/ld/pe.go
@@ -643,7 +691,7 @@ func TestPIE(t *testing.T) {
 
 // Test that installing a second time recreates the header file.
 func TestCachedInstall(t *testing.T) {
-       tmpdir, err := ioutil.TempDir("", "cshared")
+       tmpdir, err := os.MkdirTemp("", "cshared")
        if err != nil {
                t.Fatal(err)
        }
@@ -719,14 +767,14 @@ func TestCachedInstall(t *testing.T) {
 // copyFile copies src to dst.
 func copyFile(t *testing.T, dst, src string) {
        t.Helper()
-       data, err := ioutil.ReadFile(src)
+       data, err := os.ReadFile(src)
        if err != nil {
                t.Fatal(err)
        }
        if err := os.MkdirAll(filepath.Dir(dst), 0777); err != nil {
                t.Fatal(err)
        }
-       if err := ioutil.WriteFile(dst, data, 0666); err != nil {
+       if err := os.WriteFile(dst, data, 0666); err != nil {
                t.Fatal(err)
        }
 }
@@ -743,14 +791,19 @@ func TestGo2C2Go(t *testing.T) {
 
        t.Parallel()
 
-       tmpdir, err := ioutil.TempDir("", "cshared-TestGo2C2Go")
+       tmpdir, err := os.MkdirTemp("", "cshared-TestGo2C2Go")
        if err != nil {
                t.Fatal(err)
        }
        defer os.RemoveAll(tmpdir)
 
        lib := filepath.Join(tmpdir, "libtestgo2c2go."+libSuffix)
-       run(t, nil, "go", "build", "-buildmode=c-shared", "-o", lib, "./go2c2go/go")
+       var env []string
+       if GOOS == "windows" && strings.HasSuffix(lib, ".a") {
+               env = append(env, "CGO_LDFLAGS=-Wl,--out-implib,"+lib, "CGO_LDFLAGS_ALLOW=.*")
+               lib = strings.TrimSuffix(lib, ".a") + ".dll"
+       }
+       run(t, env, "go", "build", "-buildmode=c-shared", "-o", lib, "./go2c2go/go")
 
        cgoCflags := os.Getenv("CGO_CFLAGS")
        if cgoCflags != "" {
index 4c2312c1c89633803f76def2a6733e0fa64a6f3c..aae34043605d340a64c6ede42b79ce1ca4575a6e 100644 (file)
@@ -6,7 +6,6 @@ package testgodefs
 
 import (
        "bytes"
-       "io/ioutil"
        "os"
        "os/exec"
        "path/filepath"
@@ -34,7 +33,7 @@ func TestGoDefs(t *testing.T) {
                t.Fatal(err)
        }
 
-       gopath, err := ioutil.TempDir("", "testgodefs-gopath")
+       gopath, err := os.MkdirTemp("", "testgodefs-gopath")
        if err != nil {
                t.Fatal(err)
        }
@@ -58,20 +57,20 @@ func TestGoDefs(t *testing.T) {
                        t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr)
                }
 
-               if err := ioutil.WriteFile(filepath.Join(dir, fp+"_defs.go"), out, 0644); err != nil {
+               if err := os.WriteFile(filepath.Join(dir, fp+"_defs.go"), out, 0644); err != nil {
                        t.Fatal(err)
                }
        }
 
-       main, err := ioutil.ReadFile(filepath.Join("testdata", "main.go"))
+       main, err := os.ReadFile(filepath.Join("testdata", "main.go"))
        if err != nil {
                t.Fatal(err)
        }
-       if err := ioutil.WriteFile(filepath.Join(dir, "main.go"), main, 0644); err != nil {
+       if err := os.WriteFile(filepath.Join(dir, "main.go"), main, 0644); err != nil {
                t.Fatal(err)
        }
 
-       if err := ioutil.WriteFile(filepath.Join(dir, "go.mod"), []byte("module testgodefs\ngo 1.14\n"), 0644); err != nil {
+       if err := os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module testgodefs\ngo 1.14\n"), 0644); err != nil {
                t.Fatal(err)
        }
 
index 8869528015d86d2a8ef8252c930d1ab8ab97a491..9697dbf7a78e3c35b2a60ed168f8a254e67e94b0 100644 (file)
@@ -9,7 +9,6 @@ import (
        "context"
        "flag"
        "fmt"
-       "io/ioutil"
        "log"
        "os"
        "os/exec"
@@ -31,15 +30,28 @@ func TestMain(m *testing.M) {
        os.Exit(testMain(m))
 }
 
+// tmpDir is used to cleanup logged commands -- s/tmpDir/$TMPDIR/
+var tmpDir string
+
+// prettyPrintf prints lines with tmpDir sanitized.
+func prettyPrintf(format string, args ...interface{}) {
+       s := fmt.Sprintf(format, args...)
+       if tmpDir != "" {
+               s = strings.ReplaceAll(s, tmpDir, "$TMPDIR")
+       }
+       fmt.Print(s)
+}
+
 func testMain(m *testing.M) int {
        // Copy testdata into GOPATH/src/testplugin, along with a go.mod file
        // declaring the same path.
 
-       GOPATH, err := ioutil.TempDir("", "plugin_test")
+       GOPATH, err := os.MkdirTemp("", "plugin_test")
        if err != nil {
                log.Panic(err)
        }
        defer os.RemoveAll(GOPATH)
+       tmpDir = GOPATH
 
        modRoot := filepath.Join(GOPATH, "src", "testplugin")
        altRoot := filepath.Join(GOPATH, "alt", "src", "testplugin")
@@ -50,14 +62,20 @@ func testMain(m *testing.M) int {
                if err := overlayDir(dstRoot, srcRoot); err != nil {
                        log.Panic(err)
                }
-               if err := ioutil.WriteFile(filepath.Join(dstRoot, "go.mod"), []byte("module testplugin\n"), 0666); err != nil {
+               prettyPrintf("mkdir -p %s\n", dstRoot)
+               prettyPrintf("rsync -a %s/ %s\n", srcRoot, dstRoot)
+
+               if err := os.WriteFile(filepath.Join(dstRoot, "go.mod"), []byte("module testplugin\n"), 0666); err != nil {
                        log.Panic(err)
                }
+               prettyPrintf("echo 'module testplugin' > %s/go.mod\n", dstRoot)
        }
 
        os.Setenv("GOPATH", filepath.Join(GOPATH, "alt"))
        if err := os.Chdir(altRoot); err != nil {
                log.Panic(err)
+       } else {
+               prettyPrintf("cd %s\n", altRoot)
        }
        os.Setenv("PWD", altRoot)
        goCmd(nil, "build", "-buildmode=plugin", "-o", filepath.Join(modRoot, "plugin-mismatch.so"), "./plugin-mismatch")
@@ -65,6 +83,8 @@ func testMain(m *testing.M) int {
        os.Setenv("GOPATH", GOPATH)
        if err := os.Chdir(modRoot); err != nil {
                log.Panic(err)
+       } else {
+               prettyPrintf("cd %s\n", modRoot)
        }
        os.Setenv("PWD", modRoot)
 
@@ -72,13 +92,14 @@ func testMain(m *testing.M) int {
 
        goCmd(nil, "build", "-buildmode=plugin", "./plugin1")
        goCmd(nil, "build", "-buildmode=plugin", "./plugin2")
-       so, err := ioutil.ReadFile("plugin2.so")
+       so, err := os.ReadFile("plugin2.so")
        if err != nil {
                log.Panic(err)
        }
-       if err := ioutil.WriteFile("plugin2-dup.so", so, 0444); err != nil {
+       if err := os.WriteFile("plugin2-dup.so", so, 0444); err != nil {
                log.Panic(err)
        }
+       prettyPrintf("cp plugin2.so plugin2-dup.so\n")
 
        goCmd(nil, "build", "-buildmode=plugin", "-o=sub/plugin1.so", "./sub/plugin1")
        goCmd(nil, "build", "-buildmode=plugin", "-o=unnamed1.so", "./unnamed1/main.go")
@@ -95,8 +116,53 @@ func goCmd(t *testing.T, op string, args ...string) {
        run(t, "go", append([]string{op, "-gcflags", gcflags}, args...)...)
 }
 
+// escape converts a string to something suitable for a shell command line.
+func escape(s string) string {
+       s = strings.Replace(s, "\\", "\\\\", -1)
+       s = strings.Replace(s, "'", "\\'", -1)
+       // Conservative guess at characters that will force quoting
+       if s == "" || strings.ContainsAny(s, "\\ ;#*&$~?!|[]()<>{}`") {
+               s = "'" + s + "'"
+       }
+       return s
+}
+
+// asCommandLine renders cmd as something that could be copy-and-pasted into a command line
+func asCommandLine(cwd string, cmd *exec.Cmd) string {
+       s := "("
+       if cmd.Dir != "" && cmd.Dir != cwd {
+               s += "cd" + escape(cmd.Dir) + ";"
+       }
+       for _, e := range cmd.Env {
+               if !strings.HasPrefix(e, "PATH=") &&
+                       !strings.HasPrefix(e, "HOME=") &&
+                       !strings.HasPrefix(e, "USER=") &&
+                       !strings.HasPrefix(e, "SHELL=") {
+                       s += " "
+                       s += escape(e)
+               }
+       }
+       // These EVs are relevant to this test.
+       for _, e := range os.Environ() {
+               if strings.HasPrefix(e, "PWD=") ||
+                       strings.HasPrefix(e, "GOPATH=") ||
+                       strings.HasPrefix(e, "LD_LIBRARY_PATH=") {
+                       s += " "
+                       s += escape(e)
+               }
+       }
+       for _, a := range cmd.Args {
+               s += " "
+               s += escape(a)
+       }
+       s += " )"
+       return s
+}
+
 func run(t *testing.T, bin string, args ...string) string {
        cmd := exec.Command(bin, args...)
+       cmdLine := asCommandLine(".", cmd)
+       prettyPrintf("%s\n", cmdLine)
        cmd.Stderr = new(strings.Builder)
        out, err := cmd.Output()
        if err != nil {
@@ -197,6 +263,17 @@ func TestIssue25756(t *testing.T) {
        }
 }
 
+// Test with main using -buildmode=pie with plugin for issue #43228
+func TestIssue25756pie(t *testing.T) {
+       if os.Getenv("GO_BUILDER_NAME") == "darwin-arm64-11_0-toothrot" {
+               t.Skip("broken on darwin/arm64 builder in sharded mode; see issue 46239")
+       }
+
+       goCmd(t, "build", "-buildmode=plugin", "-o", "life.so", "./issue25756/plugin")
+       goCmd(t, "build", "-buildmode=pie", "-o", "issue25756pie.exe", "./issue25756/main.go")
+       run(t, "./issue25756pie.exe")
+}
+
 func TestMethod(t *testing.T) {
        // Exported symbol's method must be live.
        goCmd(t, "build", "-buildmode=plugin", "-o", "plugin.so", "./method/plugin.go")
index 6a87e7b6a0fe0d83cc1f87c7ae2b93d1d9cb71c3..89afbda3d479af1e0c3f520bbd000c973d9af2dd 100644 (file)
@@ -15,7 +15,7 @@ import (
 
 var t p.T
 
-type I interface { M() }
+type I interface{ M() }
 
 func main() {
        pl, err := plugin.Open("method2.so")
index 0192a663dddabe58ea68c34f010e09fdfa552d04..384b6250e1ef168ae130f6d77a5e302341d1cd99 100644 (file)
@@ -11,7 +11,6 @@ import (
        "encoding/json"
        "errors"
        "fmt"
-       "io/ioutil"
        "os"
        "os/exec"
        "path/filepath"
@@ -36,7 +35,7 @@ func requireOvercommit(t *testing.T) {
 
        overcommit.Once.Do(func() {
                var out []byte
-               out, overcommit.err = ioutil.ReadFile("/proc/sys/vm/overcommit_memory")
+               out, overcommit.err = os.ReadFile("/proc/sys/vm/overcommit_memory")
                if overcommit.err != nil {
                        return
                }
@@ -313,14 +312,14 @@ int main() {
 `)
 
 func (c *config) checkCSanitizer() (skip bool, err error) {
-       dir, err := ioutil.TempDir("", c.sanitizer)
+       dir, err := os.MkdirTemp("", c.sanitizer)
        if err != nil {
                return false, fmt.Errorf("failed to create temp directory: %v", err)
        }
        defer os.RemoveAll(dir)
 
        src := filepath.Join(dir, "return0.c")
-       if err := ioutil.WriteFile(src, cMain, 0600); err != nil {
+       if err := os.WriteFile(src, cMain, 0600); err != nil {
                return false, fmt.Errorf("failed to write C source file: %v", err)
        }
 
@@ -418,7 +417,7 @@ func (d *tempDir) Join(name string) string {
 
 func newTempDir(t *testing.T) *tempDir {
        t.Helper()
-       dir, err := ioutil.TempDir("", filepath.Dir(t.Name()))
+       dir, err := os.MkdirTemp("", filepath.Dir(t.Name()))
        if err != nil {
                t.Fatalf("Failed to create temp dir: %v", err)
        }
@@ -440,3 +439,14 @@ func hangProneCmd(name string, arg ...string) *exec.Cmd {
        }
        return cmd
 }
+
+// mSanSupported is a copy of the function cmd/internal/sys.MSanSupported,
+// because the internal pacakage can't be used here.
+func mSanSupported(goos, goarch string) bool {
+       switch goos {
+       case "linux":
+               return goarch == "amd64" || goarch == "arm64"
+       default:
+               return false
+       }
+}
index 56063ea620162c8ae5ab6a99dc9c3ad5bae59512..8fd03715a11bd8f9bc3076904049d88bad7a24eb 100644 (file)
@@ -6,7 +6,7 @@ package sanitizers_test
 
 import (
        "fmt"
-       "io/ioutil"
+       "os"
        "strings"
        "testing"
 )
@@ -19,6 +19,12 @@ func TestShared(t *testing.T) {
        if err != nil {
                t.Fatal(err)
        }
+
+       GOARCH, err := goEnv("GOARCH")
+       if err != nil {
+               t.Fatal(err)
+       }
+
        libExt := "so"
        if GOOS == "darwin" {
                libExt = "dylib"
@@ -41,6 +47,11 @@ func TestShared(t *testing.T) {
        for _, tc := range cases {
                tc := tc
                name := strings.TrimSuffix(tc.src, ".go")
+               //The memory sanitizer tests require support for the -msan option.
+               if tc.sanitizer == "memory" && !mSanSupported(GOOS, GOARCH) {
+                       t.Logf("skipping %s test on %s/%s; -msan option is not supported.", name, GOOS, GOARCH)
+                       continue
+               }
                t.Run(name, func(t *testing.T) {
                        t.Parallel()
                        config := configure(tc.sanitizer)
@@ -53,7 +64,7 @@ func TestShared(t *testing.T) {
                        mustRun(t, config.goCmd("build", "-buildmode=c-shared", "-o", lib, srcPath(tc.src)))
 
                        cSrc := dir.Join("main.c")
-                       if err := ioutil.WriteFile(cSrc, cMain, 0600); err != nil {
+                       if err := os.WriteFile(cSrc, cMain, 0600); err != nil {
                                t.Fatalf("failed to write C source file: %v", err)
                        }
 
index 5e2f9759baef49c1f92b9feed27f0de24e6c3000..2a3494fbfc1d3f4eff846a0f9582440c49e1db97 100644 (file)
@@ -10,6 +10,19 @@ import (
 )
 
 func TestMSAN(t *testing.T) {
+       goos, err := goEnv("GOOS")
+       if err != nil {
+               t.Fatal(err)
+       }
+       goarch, err := goEnv("GOARCH")
+       if err != nil {
+               t.Fatal(err)
+       }
+       // The msan tests require support for the -msan option.
+       if !mSanSupported(goos, goarch) {
+               t.Skipf("skipping on %s/%s; -msan option is not supported.", goos, goarch)
+       }
+
        t.Parallel()
        requireOvercommit(t)
        config := configure("memory")
index f166d8b495ac458a4a6dd236d0913cd90a68a0e9..06304be751b5e217113a7d280c31ca61636117a2 100644 (file)
@@ -44,7 +44,7 @@ void spin() {
 import "C"
 
 import (
-       "io/ioutil"
+       "io"
        "runtime/pprof"
        "time"
 )
@@ -60,7 +60,7 @@ func goSpin() {
 }
 
 func main() {
-       pprof.StartCPUProfile(ioutil.Discard)
+       pprof.StartCPUProfile(io.Discard)
        go C.spin()
        goSpin()
        pprof.StopCPUProfile()
index f52391c6f6c6ab1750fce523ad87606f25a5c708..e77f84891543f584ccb5bd2aa538f0e6237e9d17 100644 (file)
@@ -13,7 +13,6 @@ import (
        "fmt"
        "go/build"
        "io"
-       "io/ioutil"
        "log"
        "os"
        "os/exec"
@@ -90,7 +89,7 @@ func goCmd(t *testing.T, args ...string) string {
 
 // TestMain calls testMain so that the latter can use defer (TestMain exits with os.Exit).
 func testMain(m *testing.M) (int, error) {
-       workDir, err := ioutil.TempDir("", "shared_test")
+       workDir, err := os.MkdirTemp("", "shared_test")
        if err != nil {
                return 0, err
        }
@@ -177,7 +176,7 @@ func cloneTestdataModule(gopath string) (string, error) {
        if err := overlayDir(modRoot, "testdata"); err != nil {
                return "", err
        }
-       if err := ioutil.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module testshared\n"), 0644); err != nil {
+       if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module testshared\n"), 0644); err != nil {
                return "", err
        }
        return modRoot, nil
@@ -318,7 +317,7 @@ func TestShlibnameFiles(t *testing.T) {
        }
        for _, pkg := range pkgs {
                shlibnamefile := filepath.Join(gorootInstallDir, pkg+".shlibname")
-               contentsb, err := ioutil.ReadFile(shlibnamefile)
+               contentsb, err := os.ReadFile(shlibnamefile)
                if err != nil {
                        t.Errorf("error reading shlibnamefile for %s: %v", pkg, err)
                        continue
@@ -791,7 +790,7 @@ func resetFileStamps() {
 // It also sets the time of the file, so that we can see if it is rewritten.
 func touch(t *testing.T, path string) (cleanup func()) {
        t.Helper()
-       data, err := ioutil.ReadFile(path)
+       data, err := os.ReadFile(path)
        if err != nil {
                t.Fatal(err)
        }
@@ -837,14 +836,14 @@ func touch(t *testing.T, path string) (cleanup func()) {
        // user-writable.
        perm := fi.Mode().Perm() | 0200
 
-       if err := ioutil.WriteFile(path, data, perm); err != nil {
+       if err := os.WriteFile(path, data, perm); err != nil {
                t.Fatal(err)
        }
        if err := os.Chtimes(path, nearlyNew, nearlyNew); err != nil {
                t.Fatal(err)
        }
        return func() {
-               if err := ioutil.WriteFile(path, old, perm); err != nil {
+               if err := os.WriteFile(path, old, perm); err != nil {
                        t.Fatal(err)
                }
        }
index a8acf77f0b941d918214a4773f9a892e5fca8cb4..0f1111f3927d3625330bcd04b7f55632a21ad7e8 100644 (file)
@@ -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 !gccgo
+// +build gc
 
 #include "textflag.h"
 
index 04534f38dddf97d4283807f1f8c6e34abc64327f..c77953803bd51338a3d245ecf3fe2dfaa9836b8a 100644 (file)
@@ -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 !gccgo
+// +build gc
 
 package depBase
 
index 57f0fd34f78aca081045e20a22c9f3c68e10cbbd..6d14e32dc6caa474d9ca85082407c50db8b5e56c 100644 (file)
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build cgo
 // +build cgo
 
 package so_test
 
 import (
-       "io/ioutil"
        "log"
        "os"
        "os/exec"
@@ -37,7 +37,7 @@ func requireTestSOSupported(t *testing.T) {
 func TestSO(t *testing.T) {
        requireTestSOSupported(t)
 
-       GOPATH, err := ioutil.TempDir("", "cgosotest")
+       GOPATH, err := os.MkdirTemp("", "cgosotest")
        if err != nil {
                log.Fatal(err)
        }
@@ -47,7 +47,7 @@ func TestSO(t *testing.T) {
        if err := overlayDir(modRoot, "testdata"); err != nil {
                log.Panic(err)
        }
-       if err := ioutil.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil {
+       if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil {
                log.Panic(err)
        }
 
@@ -80,6 +80,10 @@ func TestSO(t *testing.T) {
        case "windows":
                ext = "dll"
                args = append(args, "-DEXPORT_DLL")
+               // At least in mingw-clang it is not permitted to just name a .dll
+               // on the command line. You must name the corresponding import
+               // library instead, even though the dll is used when the executable is run.
+               args = append(args, "-Wl,-out-implib,libcgosotest.a")
        case "aix":
                ext = "so.1"
        }
index bba5de331212f2506e630e5c484cc1cc0aa905fc..b59b2a8e8b1541f6a2a351b8e716267a5441d13d 100644 (file)
@@ -14,7 +14,7 @@ package cgosotest
 #cgo solaris LDFLAGS: -L. -lcgosotest
 #cgo netbsd LDFLAGS: -L. libcgosotest.so
 #cgo darwin LDFLAGS: -L. libcgosotest.dylib
-#cgo windows LDFLAGS: -L. libcgosotest.dll
+#cgo windows LDFLAGS: -L. libcgosotest.a
 #cgo aix LDFLAGS: -L. -l cgosotest
 
 void init(void);
index 57f0fd34f78aca081045e20a22c9f3c68e10cbbd..6d14e32dc6caa474d9ca85082407c50db8b5e56c 100644 (file)
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build cgo
 // +build cgo
 
 package so_test
 
 import (
-       "io/ioutil"
        "log"
        "os"
        "os/exec"
@@ -37,7 +37,7 @@ func requireTestSOSupported(t *testing.T) {
 func TestSO(t *testing.T) {
        requireTestSOSupported(t)
 
-       GOPATH, err := ioutil.TempDir("", "cgosotest")
+       GOPATH, err := os.MkdirTemp("", "cgosotest")
        if err != nil {
                log.Fatal(err)
        }
@@ -47,7 +47,7 @@ func TestSO(t *testing.T) {
        if err := overlayDir(modRoot, "testdata"); err != nil {
                log.Panic(err)
        }
-       if err := ioutil.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil {
+       if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil {
                log.Panic(err)
        }
 
@@ -80,6 +80,10 @@ func TestSO(t *testing.T) {
        case "windows":
                ext = "dll"
                args = append(args, "-DEXPORT_DLL")
+               // At least in mingw-clang it is not permitted to just name a .dll
+               // on the command line. You must name the corresponding import
+               // library instead, even though the dll is used when the executable is run.
+               args = append(args, "-Wl,-out-implib,libcgosotest.a")
        case "aix":
                ext = "so.1"
        }
index 9c7f95e92ea454e68ff238aa6bf18ee2732e3a94..d9deb556da87758e579d1996439ea9cfb70cf4ea 100644 (file)
@@ -18,7 +18,7 @@ package cgosotest
 #cgo solaris LDFLAGS: -L. -lcgosotest
 #cgo netbsd LDFLAGS: -L. libcgosotest.so
 #cgo darwin LDFLAGS: -L. libcgosotest.dylib
-#cgo windows LDFLAGS: -L. libcgosotest.dll
+#cgo windows LDFLAGS: -L. libcgosotest.a
 #cgo aix LDFLAGS: -L. -l cgosotest
 
 #include "cgoso_c.h"
index 1c02e5220e4d3ab9bfe2fb4f6d7e34ee5560440c..e1dcd180860ca2c67c58d18e1d80002f0f106e8e 100644 (file)
@@ -8,7 +8,7 @@
 
 #include "runtime.h"
 
-// Return current time.  This is the implementation of time.walltime1().
+// Return current time.  This is the implementation of runtime.walltime().
 
 struct walltime_ret
 {
@@ -16,7 +16,7 @@ struct walltime_ret
   int32_t nsec;
 };
 
-struct walltime_ret now(void) __asm__ (GOSYM_PREFIX "runtime.walltime1")
+struct walltime_ret now(void) __asm__ (GOSYM_PREFIX "runtime.walltime")
   __attribute__ ((no_split_stack));
 
 struct walltime_ret
index bc920a5d406fa09444a9e3af9968ccc7fe3c9bc8..f92bdd43bc9c85afede216d417c528b41a12bc47 100644 (file)
@@ -199,10 +199,13 @@ getEnd()
 uintptr getText(void)
   __asm__ (GOSYM_PREFIX "runtime.getText");
 
+extern void main_main(void*)
+  __asm__(GOSYM_PREFIX "main.main");
+
 uintptr
 getText(void)
 {
-  return (uintptr)(const void *)(getText);
+  return (uintptr)(const void *)(main_main);
 }
 
 // Return the end of the text segment, assumed to come after the
@@ -224,6 +227,24 @@ getEtext(void)
   return (uintptr)(p);
 }
 
+// Return the start of the BSS section.
+
+uintptr getBSS(void)
+  __asm__ (GOSYM_PREFIX "runtime.getBSS");
+
+uintptr
+getBSS(void)
+{
+  const void *p;
+
+  p = __edata;
+  if (p == NULL)
+    p = _edata;
+  if (p == NULL)
+    p = __bss_start;
+  return (uintptr)(p);
+}
+
 // CPU-specific initialization.
 // Fetch CPUID info on x86.
 
index c78f0c4595b3766a9bea8843bfcc3eff4061cafb..0c0c30e46acdf31ee12ab406a1eb572e221a7c0f 100644 (file)
@@ -23,7 +23,7 @@ bool runtime_usestackmaps;
 #pragma GCC optimize ("-fno-optimize-sibling-calls")
 
 extern void scanstackblock(uintptr addr, uintptr size, void *gcw)
-  __asm__("runtime.scanstackblock");
+  __asm__(GOSYM_PREFIX "runtime.scanstackblock");
 
 static bool doscanstack1(G*, void*)
   __attribute__ ((noinline));
@@ -125,3 +125,66 @@ static bool doscanstack1(G *gp, void *gcw) {
 #endif
        return true;
 }
+
+extern bool onCurrentStack(uintptr p)
+  __asm__(GOSYM_PREFIX "runtime.onCurrentStack");
+
+bool onCurrentStack(uintptr p)
+{
+#ifdef USING_SPLIT_STACK
+
+       void* sp;
+       size_t spsize;
+       void* next_segment;
+       void* next_sp;
+       void* initial_sp;
+
+       sp = __splitstack_find(nil, nil, &spsize, &next_segment, &next_sp,
+                              &initial_sp);
+       while (sp != nil) {
+               if (p >= (uintptr)(sp) && p < (uintptr)(sp) + spsize) {
+                       return true;
+               }
+               sp = __splitstack_find(next_segment, next_sp, &spsize,
+                                      &next_segment, &next_sp, &initial_sp);
+       }
+       return false;
+
+#else
+
+       G* gp;
+       byte* bottom;
+       byte* top;
+       byte* temp;
+       byte* nextsp2;
+       byte* initialsp2;
+
+       gp = runtime_g();
+       bottom = (byte*)(&p);
+       top = (byte*)(void*)(gp->gcinitialsp) + gp->gcstacksize;
+       if ((uintptr)(top) < (uintptr)(bottom)) {
+               temp = top;
+               top = bottom;
+               bottom = temp;
+       }
+       if (p >= (uintptr)(bottom) && p < (uintptr)(top)) {
+               return true;
+       }
+
+       nextsp2 = secondary_stack_pointer();
+       if (nextsp2 != nil) {
+               initialsp2 = (byte*)(void*)(gp->gcinitialsp2);
+               if (uintptr(initialsp2) < uintptr(nextsp2)) {
+                       temp = initialsp2;
+                       initialsp2 = nextsp2;
+                       nextsp2 = temp;
+               }
+               if (p >= (uintptr)(nextsp2) && p < (uintptr)(initialsp2)) {
+                       return true;
+               }
+       }
+
+       return false;
+
+#endif
+}
index 9eda2ccc70da8b2d6b10345e7fcdaf67a558b8c6..e0dd16610db6769758d5ae9b1f7c23c6716f0e5a 100755 (executable)
@@ -311,6 +311,11 @@ x)
            386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | nios2 | ppc | ppc64 | ppc64le | riscv | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64 | wasm)
                tag1=nonmatchingtag
                ;;
+           *)
+               # File name like x_amd64_random.go, where tag1=random.
+               # Don't match based on tag2.
+               tag2=
+               ;;
            esac
 
            case "$tag2" in
@@ -342,18 +347,18 @@ x)
                        fi
                        match=false
                        ;;
-                   $goos | $goarch | cgo | gccgo | go1.[0-9] | go1.[0-9][0-9])
+                   $goos | $goarch | cgo | gccgo | goexperiment.fieldtrack | go1.[0-9] | go1.[0-9][0-9])
                        match=true
                        ;;
-                   "!"$goos | "!"$goarch | "!cgo" | "!gccgo" | "!"go1.[0-9] | "!"go1.1[0-6])
+                   "!"$goos | "!"$goarch | "!cgo" | "!gccgo" | "!goexperiment.fieldtrack" | "!"go1.[0-9] | "!"go1.1[0-7])
                        ;;
                    *,*)
                        cmatch=true
                        for ctag in `echo $tag | sed -e 's/,/ /g'`; do
                            case $ctag in
-                           $goos | $goarch | cgo | gccgo | go1.[0-9] | go1.[0-9][0-9])
+                           $goos | $goarch | cgo | gccgo | goexperiment.fieldtrack | go1.[0-9] | go1.[0-9][0-9])
                                ;;
-                           "!"$goos | "!"$goarch | "!cgo" | "!gccgo" | "!"go1.[0-9] | "!"go1.1[0-6])
+                           "!"$goos | "!"$goarch | "!cgo" | "!gccgo" | "!goexperiment.fieldtrack" | "!"go1.[0-9] | "!"go1.1[0-7])
                                cmatch=false
                                ;;
                            "!"*)
This page took 4.883747 seconds and 5 git commands to generate.